diff --git a/Plugins/CesiumForUnreal/CHANGES.md b/Plugins/CesiumForUnreal/CHANGES.md new file mode 100644 index 0000000000000000000000000000000000000000..06037a3988dd75f09238ac7b4cce8bb13111ee9c --- /dev/null +++ b/Plugins/CesiumForUnreal/CHANGES.md @@ -0,0 +1,573 @@ +# Change Log + +### 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. + +### 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 0000000000000000000000000000000000000000..eb762c81f5c2fe72fb0c3ea40f70118fd10c3d2f --- /dev/null +++ b/Plugins/CesiumForUnreal/CesiumForUnreal.uplugin @@ -0,0 +1,59 @@ +{ + "FileVersion": 3, + "Version": 36, + "VersionName": "1.20.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.1.0", + "CanContainContent": true, + "Installed": true, + "SupportedTargetPlatforms": [ + "Win64", + "Mac", + "Linux", + "Android", + "IOS" + ], + "Modules": [ + { + "Name": "CesiumRuntime", + "Type": "Runtime", + "LoadingPhase": "Default", + "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/Engine.ini b/Plugins/CesiumForUnreal/Config/Engine.ini new file mode 100644 index 0000000000000000000000000000000000000000..2652f1c9c49ef7bf43f7ea267aacecbf1543002c --- /dev/null +++ b/Plugins/CesiumForUnreal/Config/Engine.ini @@ -0,0 +1,55 @@ +[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="InaccurateSetGeoreferenceOriginLongitudeLatitudeHeight") + ++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="GetGeoreferenceOriginLongitudeLatitudeHeight") ++FunctionRedirects=(OldName="CesiumGeoreference.InaccurateSetGeoreferenceOriginLongitudeLatitudeHeight",NewName="SetGeoreferenceOriginLongitudeLatitudeHeight") ++FunctionRedirects=(OldName="CesiumGeoreference.InaccurateSetGeoreferenceOriginEcef",NewName="SetGeoreferenceOriginEcef") ++FunctionRedirects=(OldName="CesiumGeoreference.InaccurateTransformLongitudeLatitudeHeightToEcef",NewName="TransformLongitudeLatitudeHeightToEcef") ++FunctionRedirects=(OldName="CesiumGeoreference.InaccurateTransformEcefToLongitudeLatitudeHeight",NewName="TransformEcefToLongitudeLatitudeHeight") ++FunctionRedirects=(OldName="CesiumGeoreference.InaccurateTransformLongitudeLatitudeHeightToUnreal",NewName="TransformLongitudeLatitudeHeightToUnreal") ++FunctionRedirects=(OldName="CesiumGeoreference.InaccurateTransformUnrealToLongitudeLatitudeHeight",NewName="TransformUnrealToLongitudeLatitudeHeight") ++FunctionRedirects=(OldName="CesiumGeoreference.InaccurateTransformEcefToUnreal",NewName="TransformEcefToUnreal") ++FunctionRedirects=(OldName="CesiumGeoreference.InaccurateTransformUnrealToEcef",NewName="TransformUnrealToEcef") ++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="GetECEF") ++FunctionRedirects=(OldName="CesiumGlobeAnchorComponent.InaccurateMoveToECEF",NewName="MoveToECEF") ++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") diff --git a/Plugins/CesiumForUnreal/Config/FilterPlugin.ini b/Plugins/CesiumForUnreal/Config/FilterPlugin.ini new file mode 100644 index 0000000000000000000000000000000000000000..c1dcb777dcd104020996df4a5159f0711cc03dca --- /dev/null +++ b/Plugins/CesiumForUnreal/Config/FilterPlugin.ini @@ -0,0 +1,7 @@ +[FilterPlugin] +/Config/FilterPlugin.ini +/Config/Engine.ini +/LICENSE +/README.md +/ThirdParty.json +/CHANGES.md diff --git a/Plugins/CesiumForUnreal/Content/FontAwesome/attribution.txt b/Plugins/CesiumForUnreal/Content/FontAwesome/attribution.txt new file mode 100644 index 0000000000000000000000000000000000000000..6c9fdeca7cb378d1625b93957104719360182ccc --- /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.svg b/Plugins/CesiumForUnreal/Content/FontAwesome/book-reader-solid.svg new file mode 100644 index 0000000000000000000000000000000000000000..00e2d0bac2d9ad145d03a4da4ce0ddc46ecfba43 --- /dev/null +++ b/Plugins/CesiumForUnreal/Content/FontAwesome/book-reader-solid.svg @@ -0,0 +1 @@ +<svg aria-hidden="true" focusable="false" data-prefix="fas" data-icon="book-reader" class="svg-inline--fa fa-book-reader fa-w-16" role="img" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"><path fill="#cccccc" d="M352 96c0-53.02-42.98-96-96-96s-96 42.98-96 96 42.98 96 96 96 96-42.98 96-96zM233.59 241.1c-59.33-36.32-155.43-46.3-203.79-49.05C13.55 191.13 0 203.51 0 219.14v222.8c0 14.33 11.59 26.28 26.49 27.05 43.66 2.29 131.99 10.68 193.04 41.43 9.37 4.72 20.48-1.71 20.48-11.87V252.56c-.01-4.67-2.32-8.95-6.42-11.46zm248.61-49.05c-48.35 2.74-144.46 12.73-203.78 49.05-4.1 2.51-6.41 6.96-6.41 11.63v245.79c0 10.19 11.14 16.63 20.54 11.9 61.04-30.72 149.32-39.11 192.97-41.4 14.9-.78 26.49-12.73 26.49-27.06V219.14c-.01-15.63-13.56-28.01-29.81-27.09z"></path></svg> \ No newline at end of file diff --git a/Plugins/CesiumForUnreal/Content/FontAwesome/check-solid.svg b/Plugins/CesiumForUnreal/Content/FontAwesome/check-solid.svg new file mode 100644 index 0000000000000000000000000000000000000000..218a840f0a02e22310bf75afe0238cda573877b3 --- /dev/null +++ b/Plugins/CesiumForUnreal/Content/FontAwesome/check-solid.svg @@ -0,0 +1 @@ +<svg aria-hidden="true" focusable="false" data-prefix="fas" data-icon="check" class="svg-inline--fa fa-check fa-w-16" role="img" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"><path fill="#00ff00" d="M173.898 439.404l-166.4-166.4c-9.997-9.997-9.997-26.206 0-36.204l36.203-36.204c9.997-9.998 26.207-9.998 36.204 0L192 312.69 432.095 72.596c9.997-9.997 26.207-9.997 36.204 0l36.203 36.204c9.997 9.997 9.997 26.206 0 36.204l-294.4 294.401c-9.998 9.997-26.207 9.997-36.204-.001z"></path></svg> 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 0000000000000000000000000000000000000000..68b748b891dc2df2f489579555ca23a4e0d23c8d --- /dev/null +++ b/Plugins/CesiumForUnreal/Content/FontAwesome/cloud-upload-alt-solid.svg @@ -0,0 +1 @@ +<svg aria-hidden="true" focusable="false" data-prefix="fas" data-icon="cloud-upload-alt" class="svg-inline--fa fa-cloud-upload-alt fa-w-20" role="img" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 640 512"><path fill="#cccccc" d="M537.6 226.6c4.1-10.7 6.4-22.4 6.4-34.6 0-53-43-96-96-96-19.7 0-38.1 6-53.3 16.2C367 64.2 315.3 32 256 32c-88.4 0-160 71.6-160 160 0 2.7.1 5.4.2 8.1C40.2 219.8 0 273.2 0 336c0 79.5 64.5 144 144 144h368c70.7 0 128-57.3 128-128 0-61.9-44-113.6-102.4-125.4zM393.4 288H328v112c0 8.8-7.2 16-16 16h-48c-8.8 0-16-7.2-16-16V288h-65.4c-14.3 0-21.4-17.2-11.3-27.3l105.4-105.4c6.2-6.2 16.4-6.2 22.6 0l105.4 105.4c10.1 10.1 2.9 27.3-11.3 27.3z"></path></svg> \ No newline at end of file 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 0000000000000000000000000000000000000000..a03a4805163b863da536637c4ef43e4adc8ddd78 --- /dev/null +++ b/Plugins/CesiumForUnreal/Content/FontAwesome/hands-helping-solid.svg @@ -0,0 +1 @@ +<svg aria-hidden="true" focusable="false" data-prefix="fas" data-icon="hands-helping" class="svg-inline--fa fa-hands-helping fa-w-20" role="img" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 640 512"><path fill="#cccccc" d="M488 192H336v56c0 39.7-32.3 72-72 72s-72-32.3-72-72V126.4l-64.9 39C107.8 176.9 96 197.8 96 220.2v47.3l-80 46.2C.7 322.5-4.6 342.1 4.3 357.4l80 138.6c8.8 15.3 28.4 20.5 43.7 11.7L231.4 448H368c35.3 0 64-28.7 64-64h16c17.7 0 32-14.3 32-32v-64h8c13.3 0 24-10.7 24-24v-48c0-13.3-10.7-24-24-24zm147.7-37.4L555.7 16C546.9.7 527.3-4.5 512 4.3L408.6 64H306.4c-12 0-23.7 3.4-33.9 9.7L239 94.6c-9.4 5.8-15 16.1-15 27.1V248c0 22.1 17.9 40 40 40s40-17.9 40-40v-88h184c30.9 0 56 25.1 56 56v28.5l80-46.2c15.3-8.9 20.5-28.4 11.7-43.7z"></path></svg> \ No newline at end of file diff --git a/Plugins/CesiumForUnreal/Content/FontAwesome/key-solid.svg b/Plugins/CesiumForUnreal/Content/FontAwesome/key-solid.svg new file mode 100644 index 0000000000000000000000000000000000000000..9137288d431d25beefa861fa7ac6b9f256ee3dcb --- /dev/null +++ b/Plugins/CesiumForUnreal/Content/FontAwesome/key-solid.svg @@ -0,0 +1 @@ +<svg aria-hidden="true" focusable="false" data-prefix="fas" data-icon="key" class="svg-inline--fa fa-key fa-w-16" role="img" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"><path fill="#cccccc" d="M512 176.001C512 273.203 433.202 352 336 352c-11.22 0-22.19-1.062-32.827-3.069l-24.012 27.014A23.999 23.999 0 0 1 261.223 384H224v40c0 13.255-10.745 24-24 24h-40v40c0 13.255-10.745 24-24 24H24c-13.255 0-24-10.745-24-24v-78.059c0-6.365 2.529-12.47 7.029-16.971l161.802-161.802C163.108 213.814 160 195.271 160 176 160 78.798 238.797.001 335.999 0 433.488-.001 512 78.511 512 176.001zM336 128c0 26.51 21.49 48 48 48s48-21.49 48-48-21.49-48-48-48-48 21.49-48 48z"></path></svg> diff --git a/Plugins/CesiumForUnreal/Content/FontAwesome/plus-solid.svg b/Plugins/CesiumForUnreal/Content/FontAwesome/plus-solid.svg new file mode 100644 index 0000000000000000000000000000000000000000..0a32ed82fc6eaa66e36c59623c68b938e54c9857 --- /dev/null +++ b/Plugins/CesiumForUnreal/Content/FontAwesome/plus-solid.svg @@ -0,0 +1 @@ +<svg aria-hidden="true" focusable="false" data-prefix="fas" data-icon="plus" class="svg-inline--fa fa-plus fa-w-14" role="img" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 448 512"><path fill="#cccccc" d="M416 208H272V64c0-17.67-14.33-32-32-32h-32c-17.67 0-32 14.33-32 32v144H32c-17.67 0-32 14.33-32 32v32c0 17.67 14.33 32 32 32h144v144c0 17.67 14.33 32 32 32h32c17.67 0 32-14.33 32-32V304h144c17.67 0 32-14.33 32-32v-32c0-17.67-14.33-32-32-32z"></path></svg> \ No newline at end of file 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 0000000000000000000000000000000000000000..42c488e2960fb450bf90a784109f9888483d994e --- /dev/null +++ b/Plugins/CesiumForUnreal/Content/FontAwesome/sign-out-alt-solid.svg @@ -0,0 +1 @@ +<svg aria-hidden="true" focusable="false" data-prefix="fas" data-icon="sign-out-alt" class="svg-inline--fa fa-sign-out-alt fa-w-16" role="img" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"><path fill="#cccccc" d="M497 273L329 441c-15 15-41 4.5-41-17v-96H152c-13.3 0-24-10.7-24-24v-96c0-13.3 10.7-24 24-24h136V88c0-21.4 25.9-32 41-17l168 168c9.3 9.4 9.3 24.6 0 34zM192 436v-40c0-6.6-5.4-12-12-12H96c-17.7 0-32-14.3-32-32V160c0-17.7 14.3-32 32-32h84c6.6 0 12-5.4 12-12V76c0-6.6-5.4-12-12-12H96c-53 0-96 43-96 96v192c0 53 43 96 96 96h84c6.6 0 12-5.4 12-12z"></path></svg> \ No newline at end of file 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 0000000000000000000000000000000000000000..d6eefea5a18bcc6f73ac564a5581f65b6a40235e --- /dev/null +++ b/Plugins/CesiumForUnreal/Content/FontAwesome/sync-alt-solid.svg @@ -0,0 +1 @@ +<svg aria-hidden="true" focusable="false" data-prefix="fas" data-icon="sync-alt" class="svg-inline--fa fa-sync-alt fa-w-16" role="img" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"><path fill="#ffffff" d="M370.72 133.28C339.458 104.008 298.888 87.962 255.848 88c-77.458.068-144.328 53.178-162.791 126.85-1.344 5.363-6.122 9.15-11.651 9.15H24.103c-7.498 0-13.194-6.807-11.807-14.176C33.933 94.924 134.813 8 256 8c66.448 0 126.791 26.136 171.315 68.685L463.03 40.97C478.149 25.851 504 36.559 504 57.941V192c0 13.255-10.745 24-24 24H345.941c-21.382 0-32.09-25.851-16.971-40.971l41.75-41.749zM32 296h134.059c21.382 0 32.09 25.851 16.971 40.971l-41.75 41.75c31.262 29.273 71.835 45.319 114.876 45.28 77.418-.07 144.315-53.144 162.787-126.849 1.344-5.363 6.122-9.15 11.651-9.15h57.304c7.498 0 13.194 6.807 11.807 14.176C478.067 417.076 377.187 504 256 504c-66.448 0-126.791-26.136-171.315-68.685L48.97 471.03C33.851 486.149 8 475.441 8 454.059V320c0-13.255 10.745-24 24-24z"></path></svg> \ No newline at end of file diff --git a/Plugins/CesiumForUnreal/Content/FontAwesome/times-solid.svg b/Plugins/CesiumForUnreal/Content/FontAwesome/times-solid.svg new file mode 100644 index 0000000000000000000000000000000000000000..d6e94a3cdf9023178220827d7714bff49feeef7c --- /dev/null +++ b/Plugins/CesiumForUnreal/Content/FontAwesome/times-solid.svg @@ -0,0 +1 @@ +<svg aria-hidden="true" focusable="false" data-prefix="fas" data-icon="times" class="svg-inline--fa fa-times fa-w-11" role="img" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 352 512"><path fill="#ff0000" d="M242.72 256l100.07-100.07c12.28-12.28 12.28-32.19 0-44.48l-22.24-22.24c-12.28-12.28-32.19-12.28-44.48 0L176 189.28 75.93 89.21c-12.28-12.28-32.19-12.28-44.48 0L9.21 111.45c-12.28 12.28-12.28 32.19 0 44.48L109.28 256 9.21 356.07c-12.28 12.28-12.28 32.19 0 44.48l22.24 22.24c12.28 12.28 32.2 12.28 44.48 0L176 322.72l100.07 100.07c12.28 12.28 32.2 12.28 44.48 0l22.24-22.24c12.28-12.28 12.28-32.19 0-44.48L242.72 256z"></path></svg> diff --git a/Plugins/CesiumForUnreal/LICENSE b/Plugins/CesiumForUnreal/LICENSE new file mode 100644 index 0000000000000000000000000000000000000000..66a27ec5ff940d3a9652d2948746ebac4c9d0188 --- /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 0000000000000000000000000000000000000000..d5df598d04e6ca36b1032d0811c3c6898fae1927 --- /dev/null +++ b/Plugins/CesiumForUnreal/README.md @@ -0,0 +1,87 @@ +[](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) + +### :rocket: 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). + +### :clap: Featured Demos + +<p> +<a href="https://github.com/CesiumGS/cesium-unreal-samples"><img src="https://images.prismic.io/cesium/bfa9f768-26eb-4a6f-a427-8e9cecbe16b1_melbourne.jpg" width="48%" /></a> +<a href="https://cesium.com/blog/2020/11/30/project-anywhere/"><img src="https://images.prismic.io/cesium/2020-11-30-Project-Anywhere-3.jpg" width="48%" /></a> +<br/> +<br/> +</p> + +### :house_with_garden: 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. + +[](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: + +### :chains: 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. + +### :green_book: 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. + +### :package: Accessing Packaged Plugin + +The easiest way to access Cesium for Unreal is by downloading officially released versions from the [Unreal Engine Marketplace](https://cesium.com/unreal-marketplace?utm_source=cesium-unreal&utm_medium=github&utm_campaign=unreal). + +If you would like to access pre-release, development versions of the plugin, Cesium for Unreal has Travis CI integration that prepares packages with each CI build. To access these packages, click the âœ”ï¸ icon on the GitHub branch or commit and click the `Details` next to `plugin-package-combined`. You can extract the downloaded plugin package into your Unreal project's `Plugins` directory. + +### :computer: 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. + +<!-- #### :hammer_and_wrench: Compiling Cesium for Unreal + +The following steps detail how to build the plugin and use it as part of your projects. You can also compile Cesium for Unreal as part of the [`cesium-unreal-samples`](https://github.com/CesiumGS/cesium-unreal-samples.git). + +Cesium for Unreal depends on Cesium's high-precision geospatial C++ library - [Cesium Native](https://github.com/CesiumGS/cesium-native), which is included as a submodule. + +1. Clone the repository using `git clone --recursive git@github.com:CesiumGS/cesium-unreal.git`. +2. From the `cesium-unreal/extern` directory, run the following commands to build `cesium-native`. + + * CMake configuration and build on Windows platform: + + ```cmd + cmake -B build -S . -G "Visual Studio 15 2017 Win64" # Optionally use "Visual Studio 16 2019" + cmake --build build --config Release --target install # Can optionally compile with --config RelWithDebInfo or MinSizeRel. + cmake --build build --config Debug --target install # Optional, recommended for debugging + ``` + + * CMake configuration and build on Linux platform: + + ```cmd + export UNREAL_ENGINE_DIR=<path_to_unreal_engine> + export UNREAL_ENGINE_COMPILER_DIR=$UNREAL_ENGINE_DIR/Engine/Extras/ThirdPartyNotUE/SDKs/HostLinux/Linux_x64/v17_clang-10.0.1-centos7/x86_64-unknown-linux-gnu + export UNREAL_ENGINE_LIBCXX_DIR=$UNREAL_ENGINE_DIR/Engine/Source/ThirdParty/Linux/LibCxx + + # Release build + cmake -B build -S . -DCMAKE_TOOLCHAIN_FILE="unreal-linux-toolchain.cmake" -DCMAKE_POSITION_INDEPENDENT_CODE=ON -DCMAKE_BUILD_TYPE=Release + cmake --build build --target install + + # Debug build + cmake -B build -S . -DCMAKE_TOOLCHAIN_FILE="unreal-linux-toolchain.cmake" -DCMAKE_POSITION_INDEPENDENT_CODE=ON -DCMAKE_BUILD_TYPE=Debug + cmake --build build --target install + ``` + +3. Point your Unreal Engine Project to the `CesiumForUnreal.uplugin` file to load the plugin into Unreal Engine. --> diff --git a/Plugins/CesiumForUnreal/Source/CesiumEditor/CesiumEditor.Build.cs b/Plugins/CesiumForUnreal/Source/CesiumEditor/CesiumEditor.Build.cs new file mode 100644 index 0000000000000000000000000000000000000000..32ecacb9f5b333dd6b61632654b1e2ad12690c6f --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/CesiumEditor/CesiumEditor.Build.cs @@ -0,0 +1,143 @@ +// Copyright 2020-2021 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) + { + PCHUsage = ModuleRules.PCHUsageMode.UseExplicitOrSharedPCHs; + + PublicIncludePaths.AddRange( + new string[] { + // ... add public include paths required here ... + } + ); + + + PrivateIncludePaths.AddRange( + new string[] { + Path.Combine(ModuleDirectory, "../ThirdParty/include") + } + ); + + string libPrefix; + string libPostfix; + string platform; + if (Target.Platform == UnrealTargetPlatform.Win64) { + platform = "Windows-x64"; + libPostfix = ".lib"; + libPrefix = ""; + } + else if (Target.Platform == UnrealTargetPlatform.Mac) { + platform = "Darwin-x64"; + libPostfix = ".a"; + libPrefix = "lib"; + } + else if(Target.Platform == UnrealTargetPlatform.Android) { + platform = "Android-xaarch64"; + libPostfix = ".a"; + libPrefix = "lib"; + } + else if(Target.Platform == UnrealTargetPlatform.Linux) { + platform = "Linux-x64"; + libPostfix = ".a"; + libPrefix = "lib"; + } + else if(Target.Platform == UnrealTargetPlatform.IOS) { + platform = "iOS-xarm64"; + libPostfix = ".a"; + libPrefix = "lib"; + } + else { + platform = "Unknown"; + libPostfix = ".Unknown"; + libPrefix = "Unknown"; + } + + string libPath = Path.Combine(ModuleDirectory, "../ThirdParty/lib/" + platform); + + string releasePostfix = ""; + string debugPostfix = "d"; + + bool preferDebug = (Target.Configuration == UnrealTargetConfiguration.Debug || Target.Configuration == UnrealTargetConfiguration.DebugGame); + string postfix = preferDebug ? debugPostfix : releasePostfix; + + string[] libs = new string[] + { + "CesiumIonClient", + "csprng" + }; + + if (preferDebug) + { + // We prefer Debug, but might still use Release if that's all that's available. + foreach (string lib in libs) + { + string debugPath = Path.Combine(libPath, libPrefix + lib + debugPostfix + libPostfix); + if (!File.Exists(debugPath)) + { + Console.WriteLine("Using release build of cesium-native because a debug build is not available."); + preferDebug = false; + postfix = releasePostfix; + break; + } + } + } + + PublicAdditionalLibraries.AddRange(libs.Select(lib => Path.Combine(libPath, libPrefix + lib + postfix + libPostfix))); + + PublicDependencyModuleNames.AddRange( + new string[] + { + "Core", + "UnrealEd", + "CesiumRuntime" + } + ); + + 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 ... + } + ); + + PCHUsage = PCHUsageMode.UseExplicitOrSharedPCHs; + PrivatePCHHeaderFile = "Private/PCH.h"; + CppStandard = CppStandardVersion.Cpp17; + } +} diff --git a/Plugins/CesiumForUnreal/Source/CesiumEditor/Private/CesiumCommands.cpp b/Plugins/CesiumForUnreal/Source/CesiumEditor/Private/CesiumCommands.cpp new file mode 100644 index 0000000000000000000000000000000000000000..e1968aaca7f1bdeb88b06baf88761958e7ef2f0d --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/CesiumEditor/Private/CesiumCommands.cpp @@ -0,0 +1,61 @@ +// Copyright 2020-2021 CesiumGS, Inc. and Contributors + +#include "CesiumCommands.h" +#include "CesiumEditor.h" + +#define LOCTEXT_NAMESPACE "CesiumCommands" + +FCesiumCommands::FCesiumCommands() + : TCommands<FCesiumCommands>( + "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", + 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 0000000000000000000000000000000000000000..bd34aaeb897eeacc219cdf0442ded0816d18bfc1 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/CesiumEditor/Private/CesiumCommands.h @@ -0,0 +1,22 @@ +// Copyright 2020-2021 CesiumGS, Inc. and Contributors + +#pragma once + +#include "CoreMinimal.h" +#include "Framework/Commands/Commands.h" + +class FCesiumCommands : public TCommands<FCesiumCommands> { +public: + FCesiumCommands(); + + TSharedPtr<FUICommandInfo> AddFromIon; + TSharedPtr<FUICommandInfo> UploadToIon; + TSharedPtr<FUICommandInfo> SignOut; + TSharedPtr<FUICommandInfo> OpenDocumentation; + TSharedPtr<FUICommandInfo> OpenSupport; + TSharedPtr<FUICommandInfo> OpenTokenSelector; + + TSharedPtr<FUICommandInfo> OpenCesiumPanel; + + virtual void RegisterCommands() override; +}; diff --git a/Plugins/CesiumForUnreal/Source/CesiumEditor/Private/CesiumEditor.cpp b/Plugins/CesiumForUnreal/Source/CesiumEditor/Private/CesiumEditor.cpp new file mode 100644 index 0000000000000000000000000000000000000000..ae2e5d2aab28dc9a1307106f36535140f7143d1b --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/CesiumEditor/Private/CesiumEditor.cpp @@ -0,0 +1,647 @@ +// Copyright 2020-2021 CesiumGS, Inc. and Contributors + +#include "CesiumEditor.h" +#include "Cesium3DTilesSelection/Tileset.h" +#include "Cesium3DTileset.h" +#include "CesiumCommands.h" +#include "CesiumIonPanel.h" +#include "CesiumIonRasterOverlay.h" +#include "CesiumIonTokenTroubleshooting.h" +#include "CesiumPanel.h" +#include "CesiumRuntime.h" +#include "CesiumSunSky.h" +#include "ClassIconFinder.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 "Styling/SlateStyle.h" +#include "Styling/SlateStyleRegistry.h" +#include "UnrealAssetAccessor.h" +#include "UnrealTaskProcessor.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<FSlateStyleSet> FCesiumEditorModule::StyleSet = nullptr; +FCesiumEditorModule* FCesiumEditorModule::_pModule = nullptr; + +namespace { +/** + * 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<FSlateStyleSet>& 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 + +void FCesiumEditorModule::StartupModule() { + _pModule = this; + + IModuleInterface::StartupModule(); + + this->_pIonSession = + std::make_shared<CesiumIonSession>(getAsyncSystem(), getAssetAccessor()); + this->_pIonSession->resume(); + + // Only register style once + if (!StyleSet.IsValid()) { + const FVector2D Icon16x16(16.0f, 16.0f); + const FVector2D Icon40x40(40.0f, 40.0f); + const FVector2D Icon64x64(64.0f, 64.0f); + + StyleSet = MakeShareable(new FSlateStyleSet("CesiumStyleSet")); + 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); + + 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<FLevelEditorModule>( + 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<FUICommandList> toolbarCommandList = + MakeShared<FUICommandList>(); + + toolbarCommandList->MapAction( + FCesiumCommands::Get().OpenCesiumPanel, + FExecuteAction::CreateLambda([]() { + FLevelEditorModule* pLevelEditorModule = + FModuleManager::GetModulePtr<FLevelEditorModule>( + FName(TEXT("LevelEditor"))); + TSharedPtr<FTabManager> pTabManager = + pLevelEditorModule + ? pLevelEditorModule->GetLevelEditorTabManager() + : FGlobalTabmanager::Get(); + pTabManager->TryInvokeTab(FTabId(TEXT("Cesium"))); + })); + + TSharedPtr<FExtender> pToolbarExtender = MakeShared<FExtender>(); + 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(); + + _pModule = nullptr; +} + +TSharedRef<SDockTab> +FCesiumEditorModule::SpawnCesiumTab(const FSpawnTabArgs& TabSpawnArgs) { + TSharedRef<SDockTab> SpawnedTab = + SNew(SDockTab).TabRole(ETabRole::NomadTab)[SNew(CesiumPanel)]; + + return SpawnedTab; +} + +TSharedRef<SDockTab> FCesiumEditorModule::SpawnCesiumIonAssetBrowserTab( + const FSpawnTabArgs& TabSpawnArgs) { + TSharedRef<SDockTab> 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<FLevelEditorModule>( + 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<FLevelEditorModule>( + 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<FSlateStyleSet> 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<ACesium3DTileset> 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<ACesium3DTileset> it(pCurrentWorld); !pTilesetActor && it; + ++it) { + 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) { + UWorld* pCurrentWorld = GEditor->GetEditorWorldContext().World(); + ULevel* pCurrentLevel = pCurrentWorld->GetCurrentLevel(); + + AActor* pNewActor = GEditor->AddActor( + pCurrentLevel, + ACesium3DTileset::StaticClass(), + FTransform(), + false, + RF_Public | RF_Transactional); + ACesium3DTileset* pTilesetActor = Cast<ACesium3DTileset>(pNewActor); + 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<UObject*>( + FindObjectWithOuter(pTilesetActor, nullptr, newName)); + if (pExisting) { + UCesiumRasterOverlay* pCesiumOverlay = + Cast<UCesiumRasterOverlay>(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<UCesiumRasterOverlay*> rasterOverlays; + pTilesetActor->GetComponents<UCesiumRasterOverlay>(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<UCesiumIonRasterOverlay>( + pTilesetActor, + FName(name.c_str()), + RF_Public | 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<UCesiumRasterOverlay*> rasterOverlays; + pTilesetActor->GetComponents<UCesiumRasterOverlay>(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<AActor> it(pCurrentWorld); it; ++it) { + if (it->GetClass() == pActorClass) { + 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(); + AActor* pNewActor = pCurrentWorld->SpawnActor<AActor>(actorClass); + return pNewActor; +} +} // 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(); +} + +UClass* FCesiumEditorModule::GetDynamicPawnBlueprintClass() { + static UClass* pResult = nullptr; + + if (!pResult) { + pResult = LoadClass<AActor>( + 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 0000000000000000000000000000000000000000..a24477ea0183dfbdcbce4b76726ebafcc90dc6f6 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/CesiumEditor/Private/CesiumEditor.h @@ -0,0 +1,118 @@ +// Copyright 2020-2021 CesiumGS, Inc. and Contributors + +#pragma once + +#include "CesiumIonSession.h" +#include "CoreMinimal.h" +#include "Modules/ModuleManager.h" +#include "Styling/SlateStyle.h" +#include "Widgets/Docking/SDockTab.h" +#include <optional> + +class FSpawnTabArgs; +class ACesium3DTileset; +class UCesiumRasterOverlay; +class UCesiumIonRasterOverlay; +struct FCesium3DTilesetLoadFailureDetails; +struct FCesiumRasterOverlayLoadFailureDetails; + +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<FSlateStyleSet> GetStyle(); + static const FName& GetStyleSetName(); + + static FCesiumEditorModule* get() { return _pModule; } + + static CesiumIonSession& ion() { + assert(_pModule); + return *_pModule->_pIonSession; + } + + 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(); + +private: + TSharedRef<SDockTab> SpawnCesiumTab(const FSpawnTabArgs& TabSpawnArgs); + TSharedRef<SDockTab> + SpawnCesiumIonAssetBrowserTab(const FSpawnTabArgs& TabSpawnArgs); + + void OnTilesetLoadFailure(const FCesium3DTilesetLoadFailureDetails& details); + void OnRasterOverlayLoadFailure( + const FCesiumRasterOverlayLoadFailureDetails& details); + void OnTilesetIonTroubleshooting(ACesium3DTileset* pTileset); + void OnRasterOverlayIonTroubleshooting(UCesiumRasterOverlay* pOverlay); + + std::shared_ptr<CesiumIonSession> _pIonSession; + FDelegateHandle _tilesetLoadFailureSubscription; + FDelegateHandle _rasterOverlayLoadFailureSubscription; + FDelegateHandle _tilesetIonTroubleshootingSubscription; + FDelegateHandle _rasterOverlayIonTroubleshootingSubscription; + + static TSharedPtr<FSlateStyleSet> 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/CesiumEditorSettings.cpp b/Plugins/CesiumForUnreal/Source/CesiumEditor/Private/CesiumEditorSettings.cpp new file mode 100644 index 0000000000000000000000000000000000000000..ae26042131bddffd6b7496482ba4e0cc7c0b0bc4 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/CesiumEditor/Private/CesiumEditorSettings.cpp @@ -0,0 +1,7 @@ +// Copyright 2020-2021 CesiumGS, Inc. and Contributors + +#include "CesiumEditorSettings.h" + +UCesiumEditorSettings::UCesiumEditorSettings( + const FObjectInitializer& ObjectInitializer) + : Super(ObjectInitializer) {} diff --git a/Plugins/CesiumForUnreal/Source/CesiumEditor/Private/CesiumEditorSettings.h b/Plugins/CesiumForUnreal/Source/CesiumEditor/Private/CesiumEditorSettings.h new file mode 100644 index 0000000000000000000000000000000000000000..d98e2761edfee33627f9807f216803b0a176271a --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/CesiumEditor/Private/CesiumEditorSettings.h @@ -0,0 +1,29 @@ +// Copyright 2020-2021 CesiumGS, Inc. and Contributors + +#pragma once + +#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: + /** + * The token representing the signed-in user to Cesium ion. If this is blank + * or invalid, the Cesium panel will prompt you to log in to Cesium ion with + * OAuth2. This is set automatically by logging in with the UI; it is not + * usually necessary to set it directly. + */ + UPROPERTY( + Config, + EditAnywhere, + Category = "Cesium ion", + meta = (DisplayName = "User Access Token")) + FString UserAccessToken; +}; diff --git a/Plugins/CesiumForUnreal/Source/CesiumEditor/Private/CesiumIonPanel.cpp b/Plugins/CesiumForUnreal/Source/CesiumEditor/Private/CesiumIonPanel.cpp new file mode 100644 index 0000000000000000000000000000000000000000..af89a57226c886707e8cc697ac463caecd42f943 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/CesiumEditor/Private/CesiumIonPanel.cpp @@ -0,0 +1,590 @@ +// Copyright 2020-2021 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 "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() + : _connectionUpdatedDelegateHandle(), + _assetsUpdatedDelegateHandle(), + _pListView(nullptr), + _assets(), + _pSelection(nullptr) { + this->_connectionUpdatedDelegateHandle = + FCesiumEditorModule::ion().ConnectionUpdated.AddRaw( + this, + &CesiumIonPanel::Refresh); + this->_assetsUpdatedDelegateHandle = + FCesiumEditorModule::ion().AssetsUpdated.AddRaw( + this, + &CesiumIonPanel::Refresh); + this->_sortColumnName = ColumnName_DateAdded; + this->_sortMode = EColumnSortMode::Type::Descending; +} + +CesiumIonPanel::~CesiumIonPanel() { + FCesiumEditorModule::ion().AssetsUpdated.Remove( + this->_assetsUpdatedDelegateHandle); + FCesiumEditorModule::ion().ConnectionUpdated.Remove( + this->_connectionUpdatedDelegateHandle); +} + +void CesiumIonPanel::Construct(const FArguments& InArgs) { + // 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<TSharedPtr<Asset>>) + .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<SWidget> 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) + + // 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::ion().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::ion().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<Asset>& pAsset) { + return pAsset && (pAsset->type == "3DTILES" || pAsset->type == "TERRAIN"); +} + +static bool isSupportedImagery(const TSharedPtr<Asset>& pAsset) { + return pAsset && pAsset->type == "IMAGERY"; +} + +TSharedRef<SWidget> 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<bool(const TSharedPtr<Asset>&, const TSharedPtr<Asset>&)> +comparatorFor(const FName& columnName) { + if (columnName == ColumnName_Type) { + return [](const TSharedPtr<Asset>& a0, const TSharedPtr<Asset>& a1) { + return a0->type < a1->type; + }; + } + if (columnName == ColumnName_DateAdded) { + return [](const TSharedPtr<Asset>& a0, const TSharedPtr<Asset>& a1) { + return a0->dateAdded < a1->dateAdded; + }; + } + return [](const TSharedPtr<Asset>& a0, const TSharedPtr<Asset>& 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>& 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<Asset>& a0, + const TSharedPtr<Asset>& a1) { return baseComparator(a1, a0); }); + } +} + +void CesiumIonPanel::Refresh() { + const Assets& assets = FCesiumEditorModule::ion().getAssets(); + + this->_assets.SetNum(assets.items.size()); + + for (size_t i = 0; i < assets.items.size(); ++i) { + this->_assets[i] = MakeShared<Asset>(assets.items[i]); + } + ApplyFilter(); + ApplySorting(); + this->_pListView->RequestListRefresh(); +} + +void CesiumIonPanel::Tick( + const FGeometry& AllottedGeometry, + const double InCurrentTime, + const float InDeltaTime) { + FCesiumEditorModule::ion().getAsyncSystem().dispatchMainThreadTasks(); + SCompoundWidget::Tick(AllottedGeometry, InCurrentTime, InDeltaTime); +} + +void CesiumIonPanel::AssetSelected( + TSharedPtr<CesiumIonClient::Asset> item, + ESelectInfo::Type selectionType) { + this->_pSelection = item; +} + +void CesiumIonPanel::AddAsset(TSharedPtr<CesiumIonClient::Asset> 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"), + item->type.c_str()); + } +} + +void CesiumIonPanel::AddAssetToLevel(TSharedPtr<CesiumIonClient::Asset> item) { + SelectCesiumIonToken::SelectAndAuthorizeToken({item->id}) + .thenInMainThread([item](const std::optional<Token>& /*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<CesiumIonClient::Asset> item, + bool useAsBaseLayer) { + SelectCesiumIonToken::SelectAndAuthorizeToken({item->id}) + .thenInMainThread([useAsBaseLayer, item](const std::optional<Token>&) { + 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<std::string, std::string> 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"), + assetDate.c_str()); + return UTF8_TO_TCHAR(assetDate.c_str()); + } + return dateTime.ToString(TEXT("%Y-%m-%d")); +} + +class AssetsTableRow : public SMultiColumnTableRow<TSharedPtr<Asset>> { +public: + void Construct( + const FArguments& InArgs, + const TSharedRef<STableViewBase>& InOwnerTableView, + const TSharedPtr<Asset>& pItem) { + this->_pItem = pItem; + SMultiColumnTableRow<TSharedPtr<Asset>>::Construct( + InArgs, + InOwnerTableView); + } + + virtual TSharedRef<SWidget> + 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<Asset> _pItem; +}; + +} // namespace + +TSharedRef<ITableRow> CesiumIonPanel::CreateAssetRow( + TSharedPtr<Asset> item, + const TSharedRef<STableViewBase>& 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 0000000000000000000000000000000000000000..78aaf4381fac30f10492bdd4a5318af1e5dfc101 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/CesiumEditor/Private/CesiumIonPanel.h @@ -0,0 +1,104 @@ +// Copyright 2020-2021 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; + +template <typename ItemType> 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<SWidget> AssetDetails(); + TSharedRef<ITableRow> CreateAssetRow( + TSharedPtr<CesiumIonClient::Asset> item, + const TSharedRef<STableViewBase>& list); + void AddAssetToLevel(TSharedPtr<CesiumIonClient::Asset> item); + void AddOverlayToTerrain( + TSharedPtr<CesiumIonClient::Asset> item, + bool useAsBaseLayer); + void AddAsset(TSharedPtr<CesiumIonClient::Asset> item); + void AssetSelected( + TSharedPtr<CesiumIonClient::Asset> item, + ESelectInfo::Type selectionType); + + /** + * 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 _connectionUpdatedDelegateHandle; + FDelegateHandle _assetsUpdatedDelegateHandle; + TSharedPtr<SListView<TSharedPtr<CesiumIonClient::Asset>>> _pListView; + TArray<TSharedPtr<CesiumIonClient::Asset>> _assets; + TSharedPtr<CesiumIonClient::Asset> _pSelection; + + /** + * 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<SSearchBox> 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/CesiumIonSession.cpp b/Plugins/CesiumForUnreal/Source/CesiumEditor/Private/CesiumIonSession.cpp new file mode 100644 index 0000000000000000000000000000000000000000..8bd188a03ebde0edc7cc686058760bda25ad3bdd --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/CesiumEditor/Private/CesiumIonSession.cpp @@ -0,0 +1,348 @@ +// Copyright 2020-2021 CesiumGS, Inc. and Contributors + +#include "CesiumIonSession.h" +#include "CesiumEditorSettings.h" +#include "CesiumRuntimeSettings.h" +#include "CesiumSourceControl.h" +#include "HAL/PlatformProcess.h" +#include "Misc/App.h" + +using namespace CesiumAsync; +using namespace CesiumIonClient; + +CesiumIonSession::CesiumIonSession( + CesiumAsync::AsyncSystem& asyncSystem, + const std::shared_ptr<CesiumAsync::IAssetAccessor>& pAssetAccessor) + : _asyncSystem(asyncSystem), + _pAssetAccessor(pAssetAccessor), + _connection(std::nullopt), + _profile(std::nullopt), + _assets(std::nullopt), + _tokens(std::nullopt), + _isConnecting(false), + _isResuming(false), + _isLoadingProfile(false), + _isLoadingAssets(false), + _isLoadingTokens(false), + _loadProfileQueued(false), + _loadAssetsQueued(false), + _loadTokensQueued(false), + _authorizeUrl() {} + +void CesiumIonSession::connect() { + if (this->isConnecting() || this->isConnected() || this->isResuming()) { + return; + } + + this->_isConnecting = true; + + Connection::authorize( + this->_asyncSystem, + this->_pAssetAccessor, + "Cesium for Unreal", + 190, + "/cesium-for-unreal/oauth2/callback", + {"assets:list", + "assets:read", + "profile:read", + "tokens:read", + "tokens:write", + "geocode"}, + [this](const std::string& url) { + this->_authorizeUrl = url; + FPlatformProcess::LaunchURL( + UTF8_TO_TCHAR(this->_authorizeUrl.c_str()), + NULL, + NULL); + }) + .thenInMainThread([this](CesiumIonClient::Connection&& connection) { + this->_isConnecting = false; + this->_connection = std::move(connection); + + UCesiumEditorSettings* pSettings = + GetMutableDefault<UCesiumEditorSettings>(); + pSettings->UserAccessToken = + UTF8_TO_TCHAR(this->_connection.value().getAccessToken().c_str()); + + CesiumSourceControl::PromptToCheckoutConfigFile( + pSettings->GetClass()->GetConfigName()); + + pSettings->SaveConfig(); + + this->ConnectionUpdated.Broadcast(); + }) + .catchInMainThread([this](std::exception&& e) { + this->_isConnecting = false; + this->_connection = std::nullopt; + this->ConnectionUpdated.Broadcast(); + }); +} + +void CesiumIonSession::resume() { + if (this->isConnecting() || this->isConnected() || this->isResuming()) { + return; + } + + const UCesiumEditorSettings* pSettings = GetDefault<UCesiumEditorSettings>(); + if (pSettings->UserAccessToken.IsEmpty()) { + // No existing session to resume. + return; + } + + this->_isResuming = true; + + this->_connection = Connection( + this->_asyncSystem, + this->_pAssetAccessor, + TCHAR_TO_UTF8(*GetDefault<UCesiumEditorSettings>()->UserAccessToken)); + + // Verify that the connection actually works. + this->_connection.value() + .me() + .thenInMainThread([this](Response<Profile>&& response) { + if (!response.value.has_value()) { + this->_connection.reset(); + } + this->_isResuming = false; + this->ConnectionUpdated.Broadcast(); + }) + .catchInMainThread([this](std::exception&& e) { + this->_isResuming = false; + this->_connection.reset(); + }); +} + +void CesiumIonSession::disconnect() { + this->_connection.reset(); + this->_profile.reset(); + this->_assets.reset(); + this->_tokens.reset(); + + UCesiumEditorSettings* pSettings = GetMutableDefault<UCesiumEditorSettings>(); + pSettings->UserAccessToken.Empty(); + + CesiumSourceControl::PromptToCheckoutConfigFile( + pSettings->GetClass()->GetConfigName()); + pSettings->SaveConfig(); + + this->ConnectionUpdated.Broadcast(); + this->ProfileUpdated.Broadcast(); + this->AssetsUpdated.Broadcast(); + this->TokensUpdated.Broadcast(); +} + +void CesiumIonSession::refreshProfile() { + if (!this->_connection || this->_isLoadingProfile) { + this->_loadProfileQueued = true; + return; + } + + this->_isLoadingProfile = true; + this->_loadProfileQueued = false; + + this->_connection->me() + .thenInMainThread([this](Response<Profile>&& profile) { + this->_isLoadingProfile = false; + this->_profile = std::move(profile.value); + this->ProfileUpdated.Broadcast(); + this->refreshProfileIfNeeded(); + }) + .catchInMainThread([this](std::exception&& e) { + this->_isLoadingProfile = false; + this->_profile = std::nullopt; + this->ProfileUpdated.Broadcast(); + this->refreshProfileIfNeeded(); + }); +} + +void CesiumIonSession::refreshAssets() { + if (!this->_connection || this->_isLoadingAssets) { + return; + } + + this->_isLoadingAssets = true; + this->_loadAssetsQueued = false; + + this->_connection->assets() + .thenInMainThread([this](Response<Assets>&& assets) { + this->_isLoadingAssets = false; + this->_assets = std::move(assets.value); + this->AssetsUpdated.Broadcast(); + this->refreshAssetsIfNeeded(); + }) + .catchInMainThread([this](std::exception&& e) { + this->_isLoadingAssets = false; + this->_assets = std::nullopt; + this->AssetsUpdated.Broadcast(); + this->refreshAssetsIfNeeded(); + }); +} + +void CesiumIonSession::refreshTokens() { + if (!this->_connection || this->_isLoadingTokens) { + return; + } + + this->_isLoadingTokens = true; + this->_loadTokensQueued = false; + + this->_connection->tokens() + .thenInMainThread([this](Response<TokenList>&& tokens) { + this->_isLoadingTokens = false; + this->_tokens = tokens.value + ? std::make_optional(std::move(tokens.value->items)) + : std::nullopt; + this->TokensUpdated.Broadcast(); + this->refreshTokensIfNeeded(); + }) + .catchInMainThread([this](std::exception&& e) { + this->_isLoadingTokens = false; + this->_tokens = std::nullopt; + this->TokensUpdated.Broadcast(); + this->refreshTokensIfNeeded(); + }); +} + +const std::optional<CesiumIonClient::Connection>& +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<CesiumIonClient::Token>& CesiumIonSession::getTokens() { + static const std::vector<CesiumIonClient::Token> empty; + if (this->_tokens) { + return *this->_tokens; + } else { + this->refreshTokens(); + 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(); +} + +Future<Response<Token>> +CesiumIonSession::findToken(const FString& token) const { + if (!this->_connection) { + return this->getAsyncSystem().createResolvedFuture( + Response<Token>(0, "NOTCONNECTED", "Not connected to Cesium ion.")); + } + + std::string tokenString = TCHAR_TO_UTF8(*token); + std::optional<std::string> maybeTokenID = + Connection::getIdFromToken(tokenString); + + if (!maybeTokenID) { + return this->getAsyncSystem().createResolvedFuture( + Response<Token>(0, "INVALIDTOKEN", "The token is not valid.")); + } + + return this->_connection->token(*maybeTokenID); +} + +namespace { + +Token tokenFromSettings() { + Token result; + result.token = TCHAR_TO_UTF8( + *GetDefault<UCesiumRuntimeSettings>()->DefaultIonAccessToken); + return result; +} + +Future<Token> getTokenFuture(const CesiumIonSession& session) { + if (!GetDefault<UCesiumRuntimeSettings>() + ->DefaultIonAccessTokenId.IsEmpty()) { + return session.getConnection() + ->token(TCHAR_TO_UTF8( + *GetDefault<UCesiumRuntimeSettings>()->DefaultIonAccessTokenId)) + .thenImmediately([](Response<Token>&& tokenResponse) { + if (tokenResponse.value) { + return *tokenResponse.value; + } else { + return tokenFromSettings(); + } + }); + } else if (!GetDefault<UCesiumRuntimeSettings>() + ->DefaultIonAccessToken.IsEmpty()) { + return session + .findToken(GetDefault<UCesiumRuntimeSettings>()->DefaultIonAccessToken) + .thenImmediately([](Response<Token>&& response) { + if (response.value) { + return *response.value; + } else { + return tokenFromSettings(); + } + }); + } else { + return session.getAsyncSystem().createResolvedFuture(tokenFromSettings()); + } +} + +} // namespace + +SharedFuture<Token> 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( + *GetDefault<UCesiumRuntimeSettings>()->DefaultIonAccessToken)) { + this->_projectDefaultTokenDetailsFuture.reset(); + } else { + return *this->_projectDefaultTokenDetailsFuture; + } + } + + if (!this->isConnected()) { + return this->getAsyncSystem() + .createResolvedFuture(tokenFromSettings()) + .share(); + } + + this->_projectDefaultTokenDetailsFuture = getTokenFuture(*this).share(); + return *this->_projectDefaultTokenDetailsFuture; +} + +void CesiumIonSession::invalidateProjectDefaultTokenDetails() { + this->_projectDefaultTokenDetailsFuture.reset(); +} diff --git a/Plugins/CesiumForUnreal/Source/CesiumEditor/Private/CesiumIonSession.h b/Plugins/CesiumForUnreal/Source/CesiumEditor/Private/CesiumIonSession.h new file mode 100644 index 0000000000000000000000000000000000000000..eb4e2373e4a557e9d85d0927a706f320ace5c728 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/CesiumEditor/Private/CesiumIonSession.h @@ -0,0 +1,118 @@ +// Copyright 2020-2021 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 <memory> + +DECLARE_MULTICAST_DELEGATE(FIonUpdated); + +class CesiumIonSession { +public: + CesiumIonSession( + CesiumAsync::AsyncSystem& asyncSystem, + const std::shared_ptr<CesiumAsync::IAssetAccessor>& pAssetAccessor); + + const std::shared_ptr<CesiumAsync::IAssetAccessor>& getAssetAccessor() const { + return this->_pAssetAccessor; + } + const CesiumAsync::AsyncSystem& getAsyncSystem() const { + return this->_asyncSystem; + } + CesiumAsync::AsyncSystem& getAsyncSystem() { return this->_asyncSystem; } + + 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; } + + void connect(); + void resume(); + void disconnect(); + + void refreshProfile(); + void refreshAssets(); + void refreshTokens(); + + FIonUpdated ConnectionUpdated; + FIonUpdated ProfileUpdated; + FIonUpdated AssetsUpdated; + FIonUpdated TokensUpdated; + + const std::optional<CesiumIonClient::Connection>& getConnection() const; + const CesiumIonClient::Profile& getProfile(); + const CesiumIonClient::Assets& getAssets(); + const std::vector<CesiumIonClient::Token>& getTokens(); + + const std::string& getAuthorizeUrl() const { return this->_authorizeUrl; } + + bool refreshProfileIfNeeded(); + bool refreshAssetsIfNeeded(); + bool refreshTokensIfNeeded(); + + /** + * 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<CesiumIonClient::Response<CesiumIonClient::Token>> + 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<CesiumIonClient::Token> + getProjectDefaultTokenDetails(); + + void invalidateProjectDefaultTokenDetails(); + +private: + CesiumAsync::AsyncSystem _asyncSystem; + std::shared_ptr<CesiumAsync::IAssetAccessor> _pAssetAccessor; + + std::optional<CesiumIonClient::Connection> _connection; + std::optional<CesiumIonClient::Profile> _profile; + std::optional<CesiumIonClient::Assets> _assets; + std::optional<std::vector<CesiumIonClient::Token>> _tokens; + + std::optional<CesiumAsync::SharedFuture<CesiumIonClient::Token>> + _projectDefaultTokenDetailsFuture; + + bool _isConnecting; + bool _isResuming; + bool _isLoadingProfile; + bool _isLoadingAssets; + bool _isLoadingTokens; + + bool _loadProfileQueued; + bool _loadAssetsQueued; + bool _loadTokensQueued; + + std::string _authorizeUrl; +}; diff --git a/Plugins/CesiumForUnreal/Source/CesiumEditor/Private/CesiumIonTokenTroubleshooting.cpp b/Plugins/CesiumForUnreal/Source/CesiumEditor/Private/CesiumIonTokenTroubleshooting.cpp new file mode 100644 index 0000000000000000000000000000000000000000..9c3f903de882f3fc83e641e7c6407f0588aba716 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/CesiumEditor/Private/CesiumIonTokenTroubleshooting.cpp @@ -0,0 +1,790 @@ +// Copyright 2020-2021 CesiumGS, Inc. and Contributors + +#include "CesiumIonTokenTroubleshooting.h" +#include "Cesium3DTileset.h" +#include "CesiumEditor.h" +#include "CesiumIonClient/Connection.h" +#include "CesiumIonRasterOverlay.h" +#include "CesiumRuntimeSettings.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::ExistingPanel> + 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<CesiumIonTokenTroubleshooting> 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. + ACesium3DTileset** ppTileset = std::get_if<ACesium3DTileset*>(&ionObject); + if (ppTileset && *ppTileset) { + TArray<UCesiumRasterOverlay*> rasterOverlays; + (*ppTileset)->GetComponents<UCesiumRasterOverlay>(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<CesiumIonTokenTroubleshooting> 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. + UCesiumRasterOverlay** ppRasterOverlay = + std::get_if<UCesiumRasterOverlay*>(&ionObject); + if (ppRasterOverlay && *ppRasterOverlay) { + ACesium3DTileset* pOwner = + Cast<ACesium3DTileset>((*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<CesiumIonTokenTroubleshooting> Troubleshooting = + SNew(CesiumIonTokenTroubleshooting) + .IonObject(ionObject) + .TriggeredByError(triggeredByError); + + Troubleshooting->GetOnWindowClosedEvent().AddLambda( + [panelMatch](const TSharedRef<SWindow>& 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<SWidget> +addTokenCheck(const FString& label, std::optional<bool>& 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 std::visit([](auto p) { return p == nullptr; }, o); +} + +FString getLabel(const CesiumIonObject& o) { + struct Operation { + FString operator()(ACesium3DTileset* pTileset) { + return pTileset ? pTileset->GetActorLabel() : TEXT("Unknown"); + } + + FString operator()(UCesiumRasterOverlay* pRasterOverlay) { + return pRasterOverlay ? pRasterOverlay->GetName() : TEXT("Unknown"); + } + }; + + return std::visit(Operation(), o); +} + +FString getName(const CesiumIonObject& o) { + return std::visit([](auto p) { return p->GetName(); }, o); +} + +int64 getIonAssetID(const CesiumIonObject& o) { + struct Operation { + int64 operator()(ACesium3DTileset* pTileset) { + if (pTileset->GetTilesetSource() != ETilesetSource::FromCesiumIon) { + return 0; + } else { + return pTileset->GetIonAssetID(); + } + } + + int64 operator()(UCesiumRasterOverlay* pRasterOverlay) { + UCesiumIonRasterOverlay* pIon = + Cast<UCesiumIonRasterOverlay>(pRasterOverlay); + if (!pIon) { + return 0; + } else { + return pIon->IonAssetID; + } + } + }; + + return std::visit(Operation(), o); +} + +FString getIonAccessToken(const CesiumIonObject& o) { + struct Operation { + FString operator()(ACesium3DTileset* pTileset) { + if (pTileset->GetTilesetSource() != ETilesetSource::FromCesiumIon) { + return FString(); + } else { + return pTileset->GetIonAccessToken(); + } + } + + FString operator()(UCesiumRasterOverlay* pRasterOverlay) { + UCesiumIonRasterOverlay* pIon = + Cast<UCesiumIonRasterOverlay>(pRasterOverlay); + if (!pIon) { + return FString(); + } else { + return pIon->IonAccessToken; + } + } + }; + + return std::visit(Operation(), o); +} + +void setIonAccessToken(const CesiumIonObject& o, const FString& newToken) { + struct Operation { + const FString& newToken; + + void operator()(ACesium3DTileset* pTileset) { + if (pTileset->GetIonAccessToken() != newToken) { + pTileset->Modify(); + pTileset->SetIonAccessToken(newToken); + } else { + pTileset->RefreshTileset(); + } + } + + void operator()(UCesiumRasterOverlay* pRasterOverlay) { + UCesiumIonRasterOverlay* pIon = + Cast<UCesiumIonRasterOverlay>(pRasterOverlay); + if (!pIon) { + return; + } + + if (pIon->IonAccessToken != newToken) { + pIon->Modify(); + pIon->IonAccessToken = newToken; + } + pIon->Refresh(); + } + }; + + return std::visit(Operation{newToken}, o); +} + +FString getObjectType(const CesiumIonObject& o) { + struct Operation { + FString operator()(ACesium3DTileset* pTileset) { return TEXT("Tileset"); } + + FString operator()(UCesiumRasterOverlay* pRasterOverlay) { + return TEXT("Raster Overlay"); + } + }; + + return std::visit(Operation(), o); +} + +UObject* asUObject(const CesiumIonObject& o) { + return std::visit([](auto p) -> UObject* { return p; }, o); +} + +bool isUsingCesiumIon(const CesiumIonObject& o) { + struct Operation { + bool operator()(ACesium3DTileset* pTileset) { + return pTileset->GetTilesetSource() == ETilesetSource::FromCesiumIon; + } + + bool operator()(UCesiumRasterOverlay* pRasterOverlay) { + UCesiumIonRasterOverlay* pIon = + Cast<UCesiumIonRasterOverlay>(pRasterOverlay); + return pIon != nullptr; + } + }; + + return std::visit(Operation(), o); +} + +} // namespace + +void CesiumIonTokenTroubleshooting::Construct(const FArguments& InArgs) { + TSharedRef<SVerticalBox> 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(FEditorStyle::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))]; + } + + TSharedRef<SHorizontalBox> 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 = + GetDefault<UCesiumRuntimeSettings>()->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 (FCesiumEditorModule::ion().isConnected()) { + // Don't let this panel be destroyed while the async operations below are in + // progress. + TSharedRef<CesiumIonTokenTroubleshooting> pPanel = + StaticCastSharedRef<CesiumIonTokenTroubleshooting>(this->AsShared()); + + FCesiumEditorModule::ion() + .getConnection() + ->asset(getIonAssetID(pIonObject)) + .thenInMainThread([pPanel](Response<Asset>&& 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(FEditorStyle::GetBrush("Menu.Background")) + .Padding( + FMargin(10.0f, 10.0f, 10.0f, 10.0f))[pMainVerticalBox]]); +} + +TSharedRef<SWidget> CesiumIonTokenTroubleshooting::createDiagnosticPanel( + const FString& name, + const TArray<TSharedRef<SWidget>>& diagnostics) { + TSharedRef<SVerticalBox> 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<SWidget>& diagnostic : diagnostics) { + pRows->AddSlot().Padding(0.0f, 5.0f, 0.0f, 5.0f)[diagnostic]; + } + + return pRows; +} + +TSharedRef<SWidget> CesiumIonTokenTroubleshooting::createTokenPanel( + const CesiumIonObject& pIonObject, + TokenState& state) { + CesiumIonSession& ionSession = FCesiumEditorModule::ion(); + + int64 assetID = getIonAssetID(pIonObject); + + auto pConnection = std::make_shared<Connection>( + ionSession.getAsyncSystem(), + ionSession.getAssetAccessor(), + TCHAR_TO_UTF8(*state.token)); + + // Don't let this panel be destroyed while the async operations below are in + // progress. + TSharedRef<CesiumIonTokenTroubleshooting> pPanel = + StaticCastSharedRef<CesiumIonTokenTroubleshooting>(this->AsShared()); + + pConnection->me() + .thenInMainThread( + [pPanel, pConnection, assetID, &state](Response<Profile>&& profile) { + state.isValid = profile.value.has_value(); + if (pPanel->IsVisible()) { + return pConnection->asset(assetID); + } else { + return pConnection->getAsyncSystem().createResolvedFuture( + Response<Asset>{}); + } + }) + .thenInMainThread([pPanel, pConnection, &state](Response<Asset>&& 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 = FCesiumEditorModule::ion(); + ionSession.resume(); + + const std::optional<Connection>& userConnection = + ionSession.getConnection(); + if (!userConnection) { + Response<TokenList> result{}; + return ionSession.getAsyncSystem().createResolvedFuture( + std::move(result)); + } + return userConnection->tokens(); + } else { + return pConnection->getAsyncSystem().createResolvedFuture( + Response<TokenList>{}); + } + }) + .thenInMainThread( + [pPanel, pConnection, &state](Response<TokenList>&& 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<SVerticalBox>& 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 !FCesiumEditorModule::ion().isConnected(); +} + +void CesiumIonTokenTroubleshooting::connectToCesiumIon() { + // Pop up the Cesium panel to show the status. + FLevelEditorModule* pLevelEditorModule = + FModuleManager::GetModulePtr<FLevelEditorModule>( + FName(TEXT("LevelEditor"))); + TSharedPtr<FTabManager> pTabManager = + pLevelEditorModule ? pLevelEditorModule->GetLevelEditorTabManager() + : FGlobalTabmanager::Get(); + pTabManager->TryInvokeTab(FTabId(TEXT("Cesium"))); + + // Pop up a browser window to sign in to ion. + FCesiumEditorModule::ion().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() { + this->authorizeToken( + GetDefault<UCesiumRuntimeSettings>()->DefaultIonAccessToken, + true); +} + +bool CesiumIonTokenTroubleshooting::canSelectNewProjectDefaultToken() const { + if (this->_assetExistsInUserAccount == false) { + return false; + } + + const TokenState& state = this->_projectDefaultTokenState; + return FCesiumEditorModule::ion().isConnected() && + (state.isValid == false || (state.allowsAccessToAsset == false && + state.associatedWithUserAccount == false)); +} + +void CesiumIonTokenTroubleshooting::selectNewProjectDefaultToken() { + if (isNull(this->_pIonObject)) { + return; + } + + CesiumIonSession& session = FCesiumEditorModule::ion(); + const std::optional<Connection>& 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<CesiumIonTokenTroubleshooting> pPanel = + StaticCastSharedRef<CesiumIonTokenTroubleshooting>(this->AsShared()); + + SelectCesiumIonToken::SelectNewToken().thenInMainThread( + [pPanel](const std::optional<Token>& newToken) { + if (!newToken) { + return; + } + + pPanel->useProjectDefaultToken(); + }); +} + +bool CesiumIonTokenTroubleshooting::canOpenCesiumIon() const { + return FCesiumEditorModule::ion().isConnected(); +} + +void CesiumIonTokenTroubleshooting::openCesiumIon() { + FPlatformProcess::LaunchURL( + TEXT("https://cesium.com/ion/tokens"), + NULL, + NULL); +} + +void CesiumIonTokenTroubleshooting::authorizeToken( + const FString& token, + bool removeObjectToken) { + if (isNull(this->_pIonObject)) { + return; + } + + CesiumIonSession& session = FCesiumEditorModule::ion(); + const std::optional<Connection>& 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<UObject> pStillAlive = asUObject(this->_pIonObject); + + session.findToken(token).thenInMainThread([pStillAlive, + removeObjectToken, + pIonObject = this->_pIonObject, + ionAssetID = getIonAssetID( + this->_pIonObject), + connection = *maybeConnection]( + Response<Token>&& 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<NoValue>&& 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 0000000000000000000000000000000000000000..da49aadf0235fdabce006f61cb4088245320b335 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/CesiumEditor/Private/CesiumIonTokenTroubleshooting.h @@ -0,0 +1,84 @@ +// Copyright 2020-2021 CesiumGS, Inc. and Contributors + +#pragma once + +#include "Widgets/SWindow.h" +#include <optional> +#include <variant> +#include <vector> + +class ACesium3DTileset; +class UCesiumRasterOverlay; + +using CesiumIonObject = std::variant<ACesium3DTileset*, UCesiumRasterOverlay*>; + +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<CesiumIonTokenTroubleshooting> pPanel; + }; + + static std::vector<ExistingPanel> _existingPanels; + + struct TokenState { + FString name; + FString token; + std::optional<bool> isValid; + std::optional<bool> allowsAccessToAsset; + std::optional<bool> associatedWithUserAccount; + }; + + CesiumIonObject _pIonObject{}; + TokenState _assetTokenState{}; + TokenState _projectDefaultTokenState{}; + std::optional<bool> _assetExistsInUserAccount; + + TSharedRef<SWidget> createDiagnosticPanel( + const FString& name, + const TArray<TSharedRef<SWidget>>& diagnostics); + + TSharedRef<SWidget> + createTokenPanel(const CesiumIonObject& pIonObject, TokenState& state); + + void addRemedyButton( + const TSharedRef<SVerticalBox>& 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 0000000000000000000000000000000000000000..e5fd600afcefc4e39238193f6ca926f7a7c8f77f --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/CesiumEditor/Private/CesiumPanel.cpp @@ -0,0 +1,245 @@ +// Copyright 2020-2021 CesiumGS, Inc. and Contributors + +#include "CesiumPanel.h" +#include "Cesium3DTileset.h" +#include "CesiumCommands.h" +#include "CesiumEditor.h" +#include "CesiumIonPanel.h" +#include "Editor.h" +#include "Framework/MultiBox/MultiBoxBuilder.h" +#include "IonLoginPanel.h" +#include "IonQuickAddPanel.h" +#include "LevelEditor.h" +#include "SelectCesiumIonToken.h" +#include "Styling/SlateStyleRegistry.h" +#include "Widgets/Input/SHyperlink.h" +#include "Widgets/Layout/SScrollBox.h" + +void CesiumPanel::Construct(const FArguments& InArgs) { + ChildSlot + [SNew(SVerticalBox) + 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)[ConnectionStatus()]]; +} + +void CesiumPanel::Tick( + const FGeometry& AllottedGeometry, + const double InCurrentTime, + const float InDeltaTime) { + FCesiumEditorModule::ion().getAsyncSystem().dispatchMainThreadTasks(); + SCompoundWidget::Tick(AllottedGeometry, InCurrentTime, InDeltaTime); +} + +static bool isSignedIn() { return FCesiumEditorModule::ion().isConnected(); } + +TSharedRef<SWidget> CesiumPanel::Toolbar() { + TSharedRef<FUICommandList> commandList = MakeShared<FUICommandList>(); + + 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)); + 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<SWidget> CesiumPanel::LoginPanel() { + return SNew(IonLoginPanel).Visibility_Lambda([]() { + return isSignedIn() ? EVisibility::Collapsed : EVisibility::Visible; + }); +} + +TSharedRef<SWidget> CesiumPanel::MainIonQuickAddPanel() { + TSharedPtr<IonQuickAddPanel> quickAddPanel = + SNew(IonQuickAddPanel) + .Title(FText::FromString("Quick Add Cesium ion Assets")) + .Visibility_Lambda([]() { + return isSignedIn() ? EVisibility::Visible : EVisibility::Collapsed; + }); + quickAddPanel->AddItem( + {QuickAddItemType::TILESET, + "Cesium World Terrain + Bing Maps Aerial imagery", + "High-resolution global terrain tileset curated from several data sources, textured with Bing Maps satellite imagery.", + "Cesium World Terrain", + 1, + "Bing Maps Aerial", + 2}); + quickAddPanel->AddItem( + {QuickAddItemType::TILESET, + "Cesium World Terrain + Bing Maps Aerial with Labels imagery", + "High-resolution global terrain tileset curated from several data sources, textured with labeled Bing Maps satellite imagery.", + "Cesium World Terrain", + 1, + "Bing Maps Aerial with Labels", + 3}); + quickAddPanel->AddItem( + {QuickAddItemType::TILESET, + "Cesium World Terrain + Bing Maps Road imagery", + "High-resolution global terrain tileset curated from several data sources, textured with Bing Maps imagery.", + "Cesium World Terrain", + 1, + "Bing Maps Road", + 4}); + quickAddPanel->AddItem( + {QuickAddItemType::TILESET, + "Cesium World Terrain + Sentinel-2 imagery", + "High-resolution global terrain tileset curated from several data sources, textured with high-resolution satellite imagery from the Sentinel-2 project.", + "Cesium World Terrain", + 1, + "Sentinel-2 imagery", + 3954}); + quickAddPanel->AddItem( + {QuickAddItemType::TILESET, + "Cesium OSM Buildings", + "A 3D buildings layer derived from OpenStreetMap covering the entire world.", + "Cesium OSM Buildings", + 96188, + "", + -1}); + + return quickAddPanel.ToSharedRef(); +} + +TSharedRef<SWidget> CesiumPanel::BasicQuickAddPanel() { + TSharedPtr<IonQuickAddPanel> 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<SWidget> CesiumPanel::ConnectionStatus() { + + auto linkVisibility = []() { + FCesiumEditorModule::ion().refreshProfileIfNeeded(); + if (!FCesiumEditorModule::ion().isProfileLoaded()) { + return EVisibility::Collapsed; + } + if (!isSignedIn()) { + return EVisibility::Collapsed; + } + return EVisibility::Visible; + }; + auto linkText = []() { + auto& profile = FCesiumEditorModule::ion().getProfile(); + std::string s = "Connected to Cesium ion as " + profile.username; + return FText::FromString(UTF8_TO_TCHAR(s.c_str())); + }; + auto loadingMessageVisibility = []() { + return FCesiumEditorModule::ion().isLoadingProfile() + ? EVisibility::Visible + : EVisibility::Collapsed; + }; + return SNew(SVerticalBox) + + SVerticalBox::Slot() + [SNew(SHyperlink) + .Visibility_Lambda(linkVisibility) + .Text_Lambda(linkText) + .ToolTipText(FText::FromString( + TEXT("Open your Cesium ion account in your browser"))) + .OnNavigate(this, &CesiumPanel::visitIon)] + + SVerticalBox::Slot()[SNew(STextBlock) + .Visibility_Lambda(loadingMessageVisibility) + .Text(FText::FromString( + TEXT("Loading user information...")))]; +} + +void CesiumPanel::addFromIon() { + FLevelEditorModule* pLevelEditorModule = + FModuleManager::GetModulePtr<FLevelEditorModule>( + FName(TEXT("LevelEditor"))); + TSharedPtr<FTabManager> pTabManager = + pLevelEditorModule ? pLevelEditorModule->GetLevelEditorTabManager() + : FGlobalTabmanager::Get(); + pTabManager->TryInvokeTab(FTabId(TEXT("CesiumIon"))); +} + +void CesiumPanel::uploadToIon() { + FPlatformProcess::LaunchURL( + TEXT("https://cesium.com/ion/addasset"), + NULL, + NULL); +} + +void CesiumPanel::visitIon() { + FPlatformProcess::LaunchURL(TEXT("https://cesium.com/ion"), NULL, NULL); +} + +void CesiumPanel::signOut() { FCesiumEditorModule::ion().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(); +} diff --git a/Plugins/CesiumForUnreal/Source/CesiumEditor/Private/CesiumPanel.h b/Plugins/CesiumForUnreal/Source/CesiumEditor/Private/CesiumPanel.h new file mode 100644 index 0000000000000000000000000000000000000000..03138998bb41e2b1b065eaf1a4c43997b28a2b6c --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/CesiumEditor/Private/CesiumPanel.h @@ -0,0 +1,34 @@ +// Copyright 2020-2021 CesiumGS, Inc. and Contributors + +#pragma once + +#include "Widgets/SCompoundWidget.h" + +class FArguments; + +class CesiumPanel : public SCompoundWidget { + SLATE_BEGIN_ARGS(CesiumPanel) {} + SLATE_END_ARGS() + + void Construct(const FArguments& InArgs); + + virtual void Tick( + const FGeometry& AllottedGeometry, + const double InCurrentTime, + const float InDeltaTime) override; + +private: + TSharedRef<SWidget> Toolbar(); + TSharedRef<SWidget> LoginPanel(); + TSharedRef<SWidget> MainIonQuickAddPanel(); + TSharedRef<SWidget> BasicQuickAddPanel(); + TSharedRef<SWidget> ConnectionStatus(); + + void addFromIon(); + void uploadToIon(); + void visitIon(); + void signOut(); + void openDocumentation(); + void openSupport(); + void openTokenSelector(); +}; diff --git a/Plugins/CesiumForUnreal/Source/CesiumEditor/Private/CesiumSourceControl.cpp b/Plugins/CesiumForUnreal/Source/CesiumEditor/Private/CesiumSourceControl.cpp new file mode 100644 index 0000000000000000000000000000000000000000..cf14eaac9367c6e786534a03c9fd428f91807a63 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/CesiumEditor/Private/CesiumSourceControl.cpp @@ -0,0 +1,55 @@ +#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<FString> 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<FCheckOut>(), + 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 0000000000000000000000000000000000000000..8371ea90ab39c86490256e5f7191ba476c05efe3 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/CesiumEditor/Private/CesiumSourceControl.h @@ -0,0 +1,10 @@ +// Copyright 2020-2022 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 0000000000000000000000000000000000000000..7283f17e412920930a094c7b4e1d50f873cb88a6 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/CesiumEditor/Private/IonLoginPanel.cpp @@ -0,0 +1,172 @@ +// Copyright 2020-2021 CesiumGS, Inc. and Contributors + +#include "IonLoginPanel.h" +#include "CesiumEditor.h" +#include "CesiumIonClient/Connection.h" +#include "CesiumIonClient/Token.h" +#include "HAL/PlatformApplicationMisc.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::ion().isConnecting() ? EVisibility::Visible + : EVisibility::Hidden; + }; + + auto visibleWhenResuming = [this]() { + return FCesiumEditorModule::ion().isResuming() ? EVisibility::Visible + : EVisibility::Hidden; + }; + + // TODO Format this, and disable clang format here + + TSharedPtr<SVerticalBox> 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::ion() + .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<SVerticalBox> connectionWidget = + SNew(SVerticalBox) + + SVerticalBox::Slot() + .VAlign(VAlign_Top) + .HAlign(HAlign_Center) + .Padding(5) + .AutoHeight() + [SNew(SButton) + .ButtonStyle(FCesiumEditorModule::GetStyle(), "CesiumButton") + .TextStyle( + FCesiumEditorModule::GetStyle(), + "CesiumButtonText") + .OnClicked(this, &IonLoginPanel::SignIn) + .Text(FText::FromString(TEXT("Connect to Cesium ion"))) + .IsEnabled_Lambda([this]() { + return !FCesiumEditorModule::ion().isConnecting() && + !FCesiumEditorModule::ion().isResuming(); + })] + + SVerticalBox::Slot() + .VAlign(VAlign_Top) + .Padding(10, 10, 10, 5) + .AutoHeight() + [SNew(STextBlock) + .AutoWrapText(true) + .TextStyle(FCesiumEditorModule::GetStyle(), "BodyBold") + .Text(FText::FromString(TEXT( + "You can now sign in with your Epic Games account!"))) + .IsEnabled_Lambda([this]() { + return !FCesiumEditorModule::ion().isConnecting() && + !FCesiumEditorModule::ion().isResuming(); + })] + + 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::ion().connect(); + return FReply::Handled(); +} + +FReply IonLoginPanel::CopyAuthorizeUrlToClipboard() { + FText url = FText::FromString( + UTF8_TO_TCHAR(FCesiumEditorModule::ion().getAuthorizeUrl().c_str())); + FPlatformApplicationMisc::ClipboardCopy(*url.ToString()); + return FReply::Handled(); +} + +void IonLoginPanel::LaunchBrowserAgain() { + FPlatformProcess::LaunchURL( + UTF8_TO_TCHAR(FCesiumEditorModule::ion().getAuthorizeUrl().c_str()), + NULL, + NULL); +} diff --git a/Plugins/CesiumForUnreal/Source/CesiumEditor/Private/IonLoginPanel.h b/Plugins/CesiumForUnreal/Source/CesiumEditor/Private/IonLoginPanel.h new file mode 100644 index 0000000000000000000000000000000000000000..138d700a9a802fa531ceea6e99eced27446cc824 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/CesiumEditor/Private/IonLoginPanel.h @@ -0,0 +1,20 @@ +// Copyright 2020-2021 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 CopyAuthorizeUrlToClipboard(); +}; diff --git a/Plugins/CesiumForUnreal/Source/CesiumEditor/Private/IonQuickAddPanel.cpp b/Plugins/CesiumForUnreal/Source/CesiumEditor/Private/IonQuickAddPanel.cpp new file mode 100644 index 0000000000000000000000000000000000000000..4b39b815f02279e957b111ac32d2bde7e4e01f9b --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/CesiumEditor/Private/IonQuickAddPanel.cpp @@ -0,0 +1,375 @@ +// Copyright 2020-2021 CesiumGS, Inc. and Contributors + +#include "IonQuickAddPanel.h" +#include "Cesium3DTileset.h" +#include "CesiumCartographicPolygon.h" +#include "CesiumEditor.h" +#include "CesiumIonClient/Connection.h" +#include "CesiumIonRasterOverlay.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) + .Padding(FMargin(5.0f, 0.0f, 5.0f, 20.0f))[this->QuickAddList()]]; +} + +void IonQuickAddPanel::AddItem(const QuickAddItem& item) { + _quickAddItems.Add(MakeShared<QuickAddItem>(item)); +} + +TSharedRef<SWidget> IonQuickAddPanel::QuickAddList() { + return SNew(SListView<TSharedRef<QuickAddItem>>) + .SelectionMode(ESelectionMode::None) + .ListItemsSource(&_quickAddItems) + .OnMouseButtonDoubleClick(this, &IonQuickAddPanel::AddItemToLevel) + .OnGenerateRow(this, &IonQuickAddPanel::CreateQuickAddItemRow); +} + +TSharedRef<ITableRow> IonQuickAddPanel::CreateQuickAddItemRow( + TSharedRef<QuickAddItem> item, + const TSharedRef<STableViewBase>& list) { + // clang-format off + return SNew(STableRow<TSharedRef<QuickAddItem>>, 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<bool>::Create([this, item]() { + return this->_itemsBeingAdded.find(item->name) == + this->_itemsBeingAdded.end(); + }) + ) + ] + ] + ]; + // clang-format on +} + +namespace { + +void showAssetDepotConfirmWindow( + const FString& itemName, + int64_t missingAsset) { + + // clang-format off + TSharedRef<SWindow> 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([missingAsset]() { + FPlatformProcess::LaunchURL( + UTF8_TO_TCHAR( + ("https://cesium.com/ion/assetdepot/" + + std::to_string(missingAsset)) + .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<QuickAddItem> item) { + const std::optional<CesiumIonClient::Connection>& connection = + FCesiumEditorModule::ion().getConnection(); + if (!connection) { + UE_LOG( + LogCesiumEditor, + Warning, + TEXT("Cannot add an ion asset without an active connection")); + return; + } + + std::vector<int64_t> assetIDs{item->tilesetID}; + if (item->overlayID > 0) { + assetIDs.push_back(item->overlayID); + } + + SelectCesiumIonToken::SelectAndAuthorizeToken(assetIDs) + .thenInMainThread([connection, tilesetID = item->tilesetID]( + const std::optional<Token>& /*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<Asset>&& response) { + if (!response.value.has_value()) { + return connection->getAsyncSystem().createResolvedFuture<int64_t>( + std::move(int64_t(item->tilesetID))); + } + + if (item->overlayID >= 0) { + return connection->asset(item->overlayID) + .thenInMainThread([item](Response<Asset>&& overlayResponse) { + return overlayResponse.value.has_value() + ? int64_t(-1) + : int64_t(item->overlayID); + }); + } else { + return connection->getAsyncSystem().createResolvedFuture<int64_t>(-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::ion().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); + } +} + +void IonQuickAddPanel::AddCartographicPolygonToLevel() { + UWorld* pCurrentWorld = GEditor->GetEditorWorldContext().World(); + ULevel* pCurrentLevel = pCurrentWorld->GetCurrentLevel(); + + GEditor->AddActor( + pCurrentLevel, + ACesiumCartographicPolygon::StaticClass(), + FTransform(), + false, + RF_Public | RF_Transactional); +} + +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<FByteProperty>(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<uint8>(EAutoReceiveInput::Type::Player0); + SetBytePropertyValue(pActor, "AutoPossessPlayer", autoPossessValue); + + GEditor->SelectNone(true, false); + GEditor->SelectActor(pActor, true, true, true, true); + } +} + +void IonQuickAddPanel::AddBlankTilesetToLevel() { + UWorld* pCurrentWorld = GEditor->GetEditorWorldContext().World(); + ULevel* pCurrentLevel = pCurrentWorld->GetCurrentLevel(); + + GEditor->AddActor( + pCurrentLevel, + ACesium3DTileset::StaticClass(), + FTransform(), + false, + RF_Public | RF_Transactional); +} + +void IonQuickAddPanel::AddItemToLevel(TSharedRef<QuickAddItem> 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) { + AddBlankTilesetToLevel(); + 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) { + AddCartographicPolygonToLevel(); + 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 0000000000000000000000000000000000000000..eb60936f30e7b3f699af32a1e8c7c3f66c027cbf --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/CesiumEditor/Private/IonQuickAddPanel.h @@ -0,0 +1,56 @@ +// Copyright 2020-2021 CesiumGS, Inc. and Contributors + +#pragma once + +#include "Widgets/SCompoundWidget.h" +#include "Widgets/Views/STableRow.h" +#include <string> +#include <unordered_set> + +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); + +private: + TSharedRef<SWidget> QuickAddList(); + TSharedRef<ITableRow> CreateQuickAddItemRow( + TSharedRef<QuickAddItem> item, + const TSharedRef<STableViewBase>& list); + + void AddItemToLevel(TSharedRef<QuickAddItem> item); + void AddBlankTilesetToLevel(); + void AddIonTilesetToLevel(TSharedRef<QuickAddItem> item); + void AddCesiumSunSkyToLevel(); + void AddDynamicPawnToLevel(); + void AddCartographicPolygonToLevel(); + + TArray<TSharedRef<QuickAddItem>> _quickAddItems; + std::unordered_set<std::string> _itemsBeingAdded; +}; diff --git a/Plugins/CesiumForUnreal/Source/CesiumEditor/Private/PCH.h b/Plugins/CesiumForUnreal/Source/CesiumEditor/Private/PCH.h new file mode 100644 index 0000000000000000000000000000000000000000..2829f03f5f4810e15ce6ecf977f2ad531542c059 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/CesiumEditor/Private/PCH.h @@ -0,0 +1,20 @@ +// Copyright 2020-2021 CesiumGS, Inc. and Contributors + +#pragma once + +#define _SILENCE_CXX17_CODECVT_HEADER_DEPRECATION_WARNING +#include "CoreMinimal.h" + +// Workaround for an unhelpful warning (that gets treated as an error) in +// VS2017. See https://github.com/akrzemi1/Optional/issues/57 and +// https://answers.unrealengine.com/questions/607946/anonymous-union-with-none-trivial-type.html +#ifdef _MSC_VER +#if _MSC_VER < 1920 +#pragma warning(push) +#pragma warning(disable : 4583) +#pragma warning(disable : 4582) +#include <optional> +#include <variant> +#pragma warning(pop) +#endif +#endif diff --git a/Plugins/CesiumForUnreal/Source/CesiumEditor/Private/SelectCesiumIonToken.cpp b/Plugins/CesiumForUnreal/Source/CesiumEditor/Private/SelectCesiumIonToken.cpp new file mode 100644 index 0000000000000000000000000000000000000000..c986b26c8d28da52e4845ba02b2cd21df28a4f12 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/CesiumEditor/Private/SelectCesiumIonToken.cpp @@ -0,0 +1,569 @@ +// Copyright 2020-2021 CesiumGS, Inc. and Contributors + +#include "SelectCesiumIonToken.h" +#include "Cesium3DTileset.h" +#include "CesiumEditor.h" +#include "CesiumIonRasterOverlay.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 "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> + SelectCesiumIonToken::_pExistingPanel{}; + +/*static*/ SharedFuture<std::optional<Token>> +SelectCesiumIonToken::SelectNewToken() { + if (SelectCesiumIonToken::_pExistingPanel.IsValid()) { + SelectCesiumIonToken::_pExistingPanel->BringToFront(); + } else { + TSharedRef<SelectCesiumIonToken> Panel = SNew(SelectCesiumIonToken); + SelectCesiumIonToken::_pExistingPanel = Panel; + + Panel->_promise = FCesiumEditorModule::ion() + .getAsyncSystem() + .createPromise<std::optional<Token>>(); + Panel->_future = Panel->_promise->getFuture().share(); + + Panel->GetOnWindowClosedEvent().AddLambda( + [Panel](const TSharedRef<SWindow>& 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<std::optional<Token>> SelectCesiumIonToken::SelectTokenIfNecessary() { + return FCesiumEditorModule::ion() + .getProjectDefaultTokenDetails() + .thenInMainThread([](const Token& token) { + if (token.token.empty()) { + return SelectCesiumIonToken::SelectNewToken().thenImmediately( + [](const std::optional<Token>& maybeToken) { + return maybeToken; + }); + } else { + return FCesiumEditorModule::ion() + .getAsyncSystem() + .createResolvedFuture(std::make_optional(token)); + } + }); +} + +namespace { + +std::vector<int64_t> findUnauthorizedAssets( + const std::vector<int64_t>& authorizedAssets, + const std::vector<int64_t>& requiredAssets) { + std::vector<int64_t> 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<std::optional<Token>> SelectCesiumIonToken::SelectAndAuthorizeToken( + const std::vector<int64_t>& assetIDs) { + return SelectTokenIfNecessary().thenInMainThread([assetIDs]( + const std::optional< + Token>& maybeToken) { + const std::optional<Connection>& maybeConnection = + FCesiumEditorModule::ion().getConnection(); + if (maybeConnection && maybeToken && !maybeToken->id.empty() && + maybeToken->assetIds) { + std::vector<int64_t> 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([maybeToken, + assetIDs](Response<Token>&& response) { + if (response.value) { + std::vector<int64_t> missingAssets = + findUnauthorizedAssets(*maybeToken->assetIds, assetIDs); + if (!missingAssets.empty()) { + std::vector<std::string> 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 FCesiumEditorModule::ion() + .getConnection() + ->modifyToken( + newToken.id, + newToken.name, + newToken.assetIds, + newToken.scopes, + newToken.allowedUrls) + .thenImmediately([maybeToken](Response<NoValue>&&) { + return maybeToken; + }); + } + } + + return FCesiumEditorModule::ion() + .getAsyncSystem() + .createResolvedFuture(std::optional<Token>(maybeToken)); + }); + } + } + + return FCesiumEditorModule::ion().getAsyncSystem().createResolvedFuture( + std::optional<Token>(maybeToken)); + }); +} + +SelectCesiumIonToken::SelectCesiumIonToken() { + this->_tokensUpdatedDelegateHandle = + FCesiumEditorModule::ion().TokensUpdated.AddRaw( + this, + &SelectCesiumIonToken::RefreshTokens); +} + +SelectCesiumIonToken::~SelectCesiumIonToken() { + FCesiumEditorModule::ion().TokensUpdated.Remove( + this->_tokensUpdatedDelegateHandle); +} + +void SelectCesiumIonToken::Construct(const FArguments& InArgs) { + TSharedRef<SVerticalBox> pLoaderOrContent = SNew(SVerticalBox); + + 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() + .Padding(0.0f, 10.0f, 0.0, 10.0f) + .AutoHeight() + [SNew(STextBlock) + .Visibility_Lambda([]() { + return FCesiumEditorModule::ion().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([]() { + return FCesiumEditorModule::ion().isLoadingTokenList() + ? EVisibility::Visible + : EVisibility::Collapsed; + })]; + + TSharedRef<SVerticalBox> pMainVerticalBox = + SNew(SVerticalBox).Visibility_Lambda([]() { + return FCesiumEditorModule::ion().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( + *GetDefault<UCesiumRuntimeSettings>()->DefaultIonAccessTokenId); + this->_useExistingToken.token.token = TCHAR_TO_UTF8( + *GetDefault<UCesiumRuntimeSettings>()->DefaultIonAccessToken); + this->_specifyToken.token = + GetDefault<UCesiumRuntimeSettings>()->DefaultIonAccessToken; + this->_tokenSource = + GetDefault<UCesiumRuntimeSettings>()->DefaultIonAccessToken.IsEmpty() + ? TokenSource::Create + : TokenSource::Specify; + + this->createRadioButton( + 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<TSharedPtr<Token>>) + .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( + 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( + 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) + .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) + .Text(FText::FromString( + TEXT("Create New Project Default Token")))]; + + SWindow::Construct( + SWindow::FArguments() + .Title(FText::FromString(TEXT("Select a Cesium ion Token"))) + .AutoCenter(EAutoCenter::PreferredWorkArea) + .SizingRule(ESizingRule::UserSized) + .ClientSize(FVector2D(635, 450)) + [SNew(SBorder) + .Visibility(EVisibility::Visible) + .BorderImage(FEditorStyle::GetBrush("Menu.Background")) + .Padding( + FMargin(10.0f, 10.0f, 10.0f, 10.0f))[pLoaderOrContent]]); + + FCesiumEditorModule::ion().refreshTokens(); +} + +void SelectCesiumIonToken::createRadioButton( + const TSharedRef<SVerticalBox>& pVertical, + TokenSource& tokenSource, + TokenSource thisValue, + const FString& label, + bool requiresIonConnection, + const TSharedRef<SWidget>& pWidget) { + auto visibility = [requiresIonConnection]() { + if (!requiresIonConnection) { + return EVisibility::Visible; + } else if (FCesiumEditorModule::ion().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(FCoreStyle::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() { + if (!this->_promise) { + return FReply::Handled(); + } + + Promise<std::optional<Token>> promise = std::move(*this->_promise); + this->_promise.reset(); + + TSharedRef<SelectCesiumIonToken> pPanel = + StaticCastSharedRef<SelectCesiumIonToken>(this->AsShared()); + + auto getToken = [this]() { + const AsyncSystem& asyncSystem = + FCesiumEditorModule::ion().getAsyncSystem(); + + if (this->_tokenSource == TokenSource::Create) { + if (this->_createNewToken.name.IsEmpty()) { + return asyncSystem.createResolvedFuture(Response<Token>()); + } + + // Create a new token, initially only with access to asset ID 1 (Cesium + // World Terrain). + return FCesiumEditorModule::ion().getConnection()->createToken( + TCHAR_TO_UTF8(*this->_createNewToken.name), + {"assets:read"}, + std::vector<int64_t>{1}, + std::nullopt); + } else if (this->_tokenSource == TokenSource::UseExisting) { + return asyncSystem.createResolvedFuture( + Response<Token>(Token(this->_useExistingToken.token), 200, "", "")); + } else if (this->_tokenSource == TokenSource::Specify) { + // Check if this is a known token, and use it if so. + return FCesiumEditorModule::ion() + .findToken(this->_specifyToken.token) + .thenInMainThread([this](Response<Token>&& response) { + if (response.value) { + return std::move(response); + } else { + Token t; + t.token = TCHAR_TO_UTF8(*this->_specifyToken.token); + return Response(std::move(t), 200, "", ""); + } + }); + } else { + return asyncSystem.createResolvedFuture( + Response<Token>(0, "UNKNOWNSOURCE", "The token source is unknown.")); + } + }; + + getToken().thenInMainThread( + [pPanel, promise = std::move(promise)](Response<Token>&& response) { + if (response.value) { + FCesiumEditorModule::ion().invalidateProjectDefaultTokenDetails(); + + UCesiumRuntimeSettings* pSettings = + GetMutableDefault<UCesiumRuntimeSettings>(); + CesiumSourceControl::PromptToCheckoutConfigFile( + pSettings->GetDefaultConfigFilename()); + + FScopedTransaction transaction( + FText::FromString("Set Project Default Token")); + pSettings->DefaultIonAccessTokenId = + UTF8_TO_TCHAR(response.value->id.c_str()); + pSettings->DefaultIonAccessToken = + UTF8_TO_TCHAR(response.value->token.c_str()); + pSettings->Modify(); + +#if ENGINE_MAJOR_VERSION >= 5 + pSettings->TryUpdateDefaultConfigFile(); +#else + pSettings->UpdateDefaultConfigFile(); +#endif + + // Refresh all tilesets and overlays that are using the project + // default token. + UWorld* pWorld = GEditor->GetEditorWorldContext().World(); + for (auto it = TActorIterator<ACesium3DTileset>(pWorld); it; ++it) { + if (it->GetTilesetSource() == ETilesetSource::FromCesiumIon && + it->GetIonAccessToken().IsEmpty()) { + it->RefreshTileset(); + } else { + // Tileset itself does not need to be refreshed, but maybe some + // overlays do. + TArray<UCesiumIonRasterOverlay*> rasterOverlays; + it->GetComponents<UCesiumIonRasterOverlay>(rasterOverlays); + + for (UCesiumIonRasterOverlay* pOverlay : rasterOverlays) { + if (pOverlay->IonAccessToken.IsEmpty()) { + 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(); + }); + + return FReply::Handled(); +} + +void SelectCesiumIonToken::RefreshTokens() { + const std::vector<Token>& tokens = FCesiumEditorModule::ion().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<Token>(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<SWidget> SelectCesiumIonToken::OnGenerateTokenComboBoxEntry( + TSharedPtr<CesiumIonClient::Token> 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<CesiumIonClient::Token> 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 0000000000000000000000000000000000000000..bcdf553752e22094256a1fc2c5bd590ba158ef00 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/CesiumEditor/Private/SelectCesiumIonToken.h @@ -0,0 +1,109 @@ +// Copyright 2020-2021 CesiumGS, Inc. and Contributors + +#pragma once + +#include "CesiumAsync/AsyncSystem.h" +#include "CesiumIonClient/Token.h" +#include "Widgets/Input/SComboBox.h" +#include "Widgets/SWindow.h" +#include <optional> +#include <string> +#include <variant> + +class SelectCesiumIonToken : public SWindow { + SLATE_BEGIN_ARGS(SelectCesiumIonToken) {} + 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<std::optional<CesiumIonClient::Token>> + SelectNewToken(); + + /** + * 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<std::optional<CesiumIonClient::Token>> + SelectTokenIfNecessary(); + + /** + * 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<std::optional<CesiumIonClient::Token>> + SelectAndAuthorizeToken(const std::vector<int64_t>& assetIDs); + + SelectCesiumIonToken(); + virtual ~SelectCesiumIonToken(); + 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 TSharedRef<SVerticalBox>& pVertical, + TokenSource& tokenSource, + TokenSource thisValue, + const FString& label, + bool requiresIonConnection, + const TSharedRef<SWidget>& pWidget); + FReply UseOrCreate(); + void RefreshTokens(); + TSharedRef<SWidget> + OnGenerateTokenComboBoxEntry(TSharedPtr<CesiumIonClient::Token> pToken); + FText GetNewTokenName() const; + void SetNewTokenName(const FText& text); + void OnSelectExistingToken( + TSharedPtr<CesiumIonClient::Token> pToken, + ESelectInfo::Type type); + FText GetSpecifiedToken() const; + void SetSpecifiedToken(const FText& text); + + static TSharedPtr<SelectCesiumIonToken> _pExistingPanel; + + std::optional<CesiumAsync::Promise<std::optional<CesiumIonClient::Token>>> + _promise; + std::optional< + CesiumAsync::SharedFuture<std::optional<CesiumIonClient::Token>>> + _future; + + TokenSource _tokenSource = TokenSource::Create; + CreateNewToken _createNewToken; + UseExistingToken _useExistingToken; + SpecifyToken _specifyToken; + FDelegateHandle _tokensUpdatedDelegateHandle; + TArray<TSharedPtr<CesiumIonClient::Token>> _tokens; + TSharedPtr<SComboBox<TSharedPtr<CesiumIonClient::Token>>> _pTokensCombo; +}; diff --git a/Plugins/CesiumForUnreal/Source/CesiumRuntime/CesiumRuntime.Build.cs b/Plugins/CesiumForUnreal/Source/CesiumRuntime/CesiumRuntime.Build.cs new file mode 100644 index 0000000000000000000000000000000000000000..983e1be03a1c0962aaf534dd7aa5cfbf9f029f55 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/CesiumRuntime/CesiumRuntime.Build.cs @@ -0,0 +1,222 @@ +// Copyright 2020-2021 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) + { + PCHUsage = ModuleRules.PCHUsageMode.UseExplicitOrSharedPCHs; + + PublicIncludePaths.AddRange( + new string[] { + Path.Combine(ModuleDirectory, "../ThirdParty/include") + } + ); + + PrivateIncludePaths.AddRange( + new string[] { + // ... add other private include paths required here ... +#if UE_5_1_OR_LATER + // In UE5.1, we need to explicit add the renderer's private directory to the include + // paths in order to be able to include ScenePrivate.h. GetModuleDirectory makes this + // easy, but it isn't available in UE5.0 and earlier. + Path.Combine(GetModuleDirectory("Renderer"), "Private") +#endif + } + ); + + string libPrefix; + string libPostfix; + string platform; + if (Target.Platform == UnrealTargetPlatform.Win64) + { + platform = "Windows-x64"; + libPostfix = ".lib"; + libPrefix = ""; + } + else if (Target.Platform == UnrealTargetPlatform.Mac) + { + platform = "Darwin-x64"; + libPostfix = ".a"; + libPrefix = "lib"; + } + else if (Target.Platform == UnrealTargetPlatform.Android) + { + platform = "Android-xaarch64"; + libPostfix = ".a"; + libPrefix = "lib"; + } + else if (Target.Platform == UnrealTargetPlatform.Linux) + { + platform = "Linux-x64"; + libPostfix = ".a"; + libPrefix = "lib"; + } + else if(Target.Platform == UnrealTargetPlatform.IOS) + { + platform = "iOS-xarm64"; + libPostfix = ".a"; + libPrefix = "lib"; + } + else { + platform = "Unknown"; + libPostfix = ".Unknown"; + libPrefix = "Unknown"; + } + + string libPath = Path.Combine(ModuleDirectory, "../ThirdParty/lib/" + platform); + + string releasePostfix = ""; + string debugPostfix = "d"; + + bool preferDebug = (Target.Configuration == UnrealTargetConfiguration.Debug || Target.Configuration == UnrealTargetConfiguration.DebugGame); + string postfix = preferDebug ? debugPostfix : releasePostfix; + + string[] libs = new string[] + { + "async++", + "Cesium3DTilesSelection", + "CesiumAsync", + "CesiumGeometry", + "CesiumGeospatial", + "CesiumGltfReader", + "CesiumGltf", + "CesiumJsonReader", + "CesiumUtility", + "draco", + "ktx_read", + //"MikkTSpace", + "modp_b64", + "s2geometry", + "spdlog", + "sqlite3", + "tinyxml2", + "uriparser", + "webpdecoder", + "ktx_read", + }; + + // Use our own copy of MikkTSpace on Android. + if (Target.Platform == UnrealTargetPlatform.Android || Target.Platform == UnrealTargetPlatform.IOS) + { + libs = libs.Concat(new string[] { "MikkTSpace" }).ToArray(); + PrivateIncludePaths.Add(Path.Combine(ModuleDirectory, "../ThirdParty/include/mikktspace")); + } + + if (Target.Platform == UnrealTargetPlatform.Win64) + { + libs = libs.Concat(new string[] { "tidy_static" }).ToArray(); + } + else + { + libs = libs.Concat(new string[] { "tidy" }).ToArray(); + } + + if (preferDebug) + { + // We prefer Debug, but might still use Release if that's all that's available. + foreach (string lib in libs) + { + string debugPath = Path.Combine(libPath, libPrefix + lib + debugPostfix + libPostfix); + if (!File.Exists(debugPath)) + { + Console.WriteLine("Using release build of cesium-native because a debug build is not available."); + preferDebug = false; + postfix = releasePostfix; + break; + } + } + } + + PublicAdditionalLibraries.AddRange(libs.Select(lib => Path.Combine(libPath, libPrefix + lib + postfix + libPostfix))); + + PublicDependencyModuleNames.AddRange( + new string[] + { + "Core", + // ... add other public dependencies that you statically link with here ... + } + ); + + + PrivateDependencyModuleNames.AddRange( + new string[] + { + "RHI", + "CoreUObject", + "Engine", + "MeshDescription", + "StaticMeshDescription", + "HTTP", + "LevelSequence", + "Projects", + "RenderCore", + "SunPosition", + "DeveloperSettings", + "UMG", + "Renderer" + } + ); + + // Use UE's MikkTSpace on non-Android + if (Target.Platform != UnrealTargetPlatform.Android) + { + PrivateDependencyModuleNames.Add("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" + } + ); + + if (Target.bCompilePhysX && !Target.bUseChaos) + { + PrivateDependencyModuleNames.Add("PhysXCooking"); + PrivateDependencyModuleNames.Add("PhysicsCore"); + } + else + { + 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 ... + } + ); + + PCHUsage = PCHUsageMode.UseExplicitOrSharedPCHs; + PrivatePCHHeaderFile = "Private/PCH.h"; + CppStandard = CppStandardVersion.Cpp17; + 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 0000000000000000000000000000000000000000..758d32a829e813fafd279c73b24f6516fb685053 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/CesiumRuntime/Private/CalcBounds.cpp @@ -0,0 +1,78 @@ +// Copyright 2020-2021 CesiumGS, Inc. and Contributors + +#include "CalcBounds.h" +#include "VecMath.h" +#include <glm/gtc/matrix_inverse.hpp> +#include <glm/vec3.hpp> + +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 0000000000000000000000000000000000000000..e87232caa7de41135c29130c27fe0e9af3d397d6 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/CesiumRuntime/Private/CalcBounds.h @@ -0,0 +1,48 @@ +// Copyright 2020-2021 CesiumGS, Inc. and Contributors + +#pragma once + +#include "Math/BoxSphereBounds.h" +#include "Math/TransformNonVectorized.h" +#include <Cesium3DTilesSelection/BoundingVolume.h> +#include <glm/mat3x3.hpp> +#include <glm/mat4x4.hpp> + +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 0000000000000000000000000000000000000000..20592d9166acbdab3c06a1aa5f11e042660c77d0 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/CesiumRuntime/Private/Cesium3DTileset.cpp @@ -0,0 +1,2116 @@ +// Copyright 2020-2021 CesiumGS, Inc. and Contributors + +#include "Cesium3DTileset.h" +#include "Async/Async.h" +#include "Camera/CameraTypes.h" +#include "Camera/PlayerCameraManager.h" +#include "Cesium3DTilesSelection/BingMapsRasterOverlay.h" +#include "Cesium3DTilesSelection/BoundingVolume.h" +#include "Cesium3DTilesSelection/CreditSystem.h" +#include "Cesium3DTilesSelection/IPrepareRendererResources.h" +#include "Cesium3DTilesSelection/TilesetLoadFailureDetails.h" +#include "Cesium3DTilesSelection/TilesetOptions.h" +#include "Cesium3DTilesetLoadFailureDetails.h" +#include "Cesium3DTilesetRoot.h" +#include "CesiumAsync/IAssetResponse.h" +#include "CesiumBoundingVolumeComponent.h" +#include "CesiumCamera.h" +#include "CesiumCameraManager.h" +#include "CesiumCommon.h" +#include "CesiumCustomVersion.h" +#include "CesiumGeospatial/Cartographic.h" +#include "CesiumGeospatial/Ellipsoid.h" +#include "CesiumGeospatial/Transforms.h" +#include "CesiumGltf/ImageCesium.h" +#include "CesiumGltf/Ktx2TranscodeTargets.h" +#include "CesiumGltfComponent.h" +#include "CesiumGltfPrimitiveComponent.h" +#include "CesiumLifetime.h" +#include "CesiumRasterOverlay.h" +#include "CesiumRuntime.h" +#include "CesiumRuntimeSettings.h" +#include "CesiumTextureUtility.h" +#include "CesiumTransforms.h" +#include "CesiumViewExtension.h" +#include "Components/SceneCaptureComponent2D.h" +#include "CreateGltfOptions.h" +#include "Engine/Engine.h" +#include "Engine/GameViewportClient.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 "GameFramework/Controller.h" +#include "GameFramework/PlayerController.h" +#include "Kismet/GameplayStatics.h" +#include "LevelSequenceActor.h" +#include "LevelSequencePlayer.h" +#include "Math/UnrealMathUtility.h" +#include "Misc/EnumRange.h" +#include "PhysicsPublicCore.h" +#include "PixelFormat.h" +#include "SceneTypes.h" +#include "StereoRendering.h" +#include <glm/ext/matrix_transform.hpp> +#include <glm/gtc/matrix_inverse.hpp> +#include <glm/trigonometric.hpp> +#include <memory> +#include <spdlog/spdlog.h> + +FCesium3DTilesetLoadFailure OnCesium3DTilesetLoadFailure{}; + +#if WITH_EDITOR +#include "Editor.h" +#include "EditorViewportClient.h" +#include "LevelEditorViewport.h" +#endif + +// Sets default values +ACesium3DTileset::ACesium3DTileset() + : Georeference(nullptr), + ResolvedGeoreference(nullptr), + CreditSystem(nullptr), + + _pTileset(nullptr), + + _lastTilesRendered(0), + _lastTilesLoadingLowPriority(0), + _lastTilesLoadingMediumPriority(0), + _lastTilesLoadingHighPriority(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; + + this->SetActorEnableCollision(true); + + this->RootComponent = + CreateDefaultSubobject<UCesium3DTilesetRoot>(TEXT("Tileset")); + + PlatformName = UGameplayStatics::GetPlatformName(); +} + +ACesium3DTileset::~ACesium3DTileset() { this->DestroyTileset(); } + +ACesiumGeoreference* ACesium3DTileset::GetGeoreference() const { + return this->Georeference; +} + +void ACesium3DTileset::SetMobility(EComponentMobility::Type NewMobility) { + if (NewMobility != this->Mobility) { + this->Mobility = NewMobility; + DestroyTileset(); + } +} + +void ACesium3DTileset::SetGeoreference(ACesiumGeoreference* NewGeoreference) { + this->Georeference = NewGeoreference; + this->InvalidateResolvedGeoreference(); + this->ResolveGeoreference(); +} + +ACesiumGeoreference* ACesium3DTileset::ResolveGeoreference() { + if (IsValid(this->ResolvedGeoreference)) { + return this->ResolvedGeoreference; + } + + if (IsValid(this->Georeference)) { + this->ResolvedGeoreference = this->Georeference; + } else { + this->ResolvedGeoreference = + ACesiumGeoreference::GetDefaultGeoreference(this); + } + + UCesium3DTilesetRoot* pRoot = Cast<UCesium3DTilesetRoot>(this->RootComponent); + if (pRoot) { + this->ResolvedGeoreference->OnGeoreferenceUpdated.AddUniqueDynamic( + pRoot, + &UCesium3DTilesetRoot::HandleGeoreferenceUpdated); + + // 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; +} + +ACesiumCreditSystem* ACesium3DTileset::GetCreditSystem() const { + return this->CreditSystem; +} + +void ACesium3DTileset::SetCreditSystem(ACesiumCreditSystem* NewCreditSystem) { + this->CreditSystem = NewCreditSystem; + this->InvalidateResolvedCreditSystem(); + this->ResolveCreditSystem(); +} + +ACesiumCreditSystem* ACesium3DTileset::ResolveCreditSystem() { + if (IsValid(this->ResolvedCreditSystem)) { + return this->ResolvedCreditSystem; + } + + if (IsValid(this->CreditSystem)) { + this->ResolvedCreditSystem = this->CreditSystem; + } 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(); +} + +void ACesium3DTileset::RefreshTileset() { this->DestroyTileset(); } + +void ACesium3DTileset::TroubleshootToken() { + OnCesium3DTilesetIonTroubleshooting.Broadcast(this); +} + +void ACesium3DTileset::AddFocusViewportDelegate() { +#if WITH_EDITOR + FEditorDelegates::OnFocusViewportOnActors.AddLambda( + [this](const TArray<AActor*>& 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<UCesiumRuntimeSettings>(); + 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::SetIonAssetEndpointUrl( + const FString& InIonAssetEndpointUrl) { + if (this->IonAssetEndpointUrl != InIonAssetEndpointUrl) { + if (this->TilesetSource == ETilesetSource::FromCesiumIon) { + this->DestroyTileset(); + } + this->IonAssetEndpointUrl = InIonAssetEndpointUrl; + } +} + +bool ACesium3DTileset::GetEnableOcclusionCulling() const { + return GetDefault<UCesiumRuntimeSettings>() + ->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::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::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::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 GeoTransforms& localGeoTransforms; + + glm::dvec3 operator()(const CesiumGeometry::BoundingSphere& sphere) { + const glm::dvec3& center = sphere.getCenter(); + glm::dmat4 ENU = + glm::dmat4(localGeoTransforms.ComputeEastNorthUpToEcef(center)); + 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 = + glm::dmat4(localGeoTransforms.ComputeEastNorthUpToEcef(center)); + 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(); + + // calculate unreal camera position + const glm::dmat4& transform = + this->GetCesiumTilesetToUnrealRelativeWorldTransform(); + glm::dvec3 ecefCameraPosition = std::visit( + CalculateECEFCameraPosition{ + this->ResolveGeoreference()->GetGeoTransforms()}, + boundingVolume); + glm::dvec3 unrealCameraPosition = + glm::dvec3(transform * glm::dvec4(ecefCameraPosition, 1.0)); + + // calculate unreal camera orientation + glm::dvec3 ecefCenter = + Cesium3DTilesSelection::getBoundingVolumeCenter(boundingVolume); + glm::dvec3 unrealCenter = glm::dvec3(transform * glm::dvec4(ecefCenter, 1.0)); + glm::dvec3 unrealCameraFront = + glm::normalize(unrealCenter - unrealCameraPosition); + glm::dvec3 unrealCameraRight = + glm::normalize(glm::cross(glm::dvec3(0.0, 0.0, 1.0), unrealCameraFront)); + glm::dvec3 unrealCameraUp = + glm::normalize(glm::cross(unrealCameraFront, unrealCameraRight)); + FRotator cameraRotator = + FMatrix( + FVector( + unrealCameraFront.x, + unrealCameraFront.y, + unrealCameraFront.z), + FVector( + unrealCameraRight.x, + unrealCameraRight.y, + unrealCameraRight.z), + FVector(unrealCameraUp.x, unrealCameraUp.y, unrealCameraUp.z), + FVector(0.0f, 0.0f, 0.0f)) + .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(FVector( + unrealCameraPosition.x, + unrealCameraPosition.y, + unrealCameraPosition.z)); + LinkedViewportClient->Invalidate(); + } + } +} +#endif + +const glm::dmat4& +ACesium3DTileset::GetCesiumTilesetToUnrealRelativeWorldTransform() const { + return Cast<UCesium3DTilesetRoot>(this->RootComponent) + ->GetCesiumTilesetToUnrealRelativeWorldTransform(); +} + +void ACesium3DTileset::UpdateTransformFromCesium() { + + const glm::dmat4& CesiumToUnreal = + this->GetCesiumTilesetToUnrealRelativeWorldTransform(); + TArray<UCesiumGltfComponent*> gltfComponents; + this->GetComponents<UCesiumGltfComponent>(gltfComponents); + + for (UCesiumGltfComponent* pGltf : gltfComponents) { + pGltf->UpdateTransformFromCesium(CesiumToUnreal); + } + + if (this->BoundingVolumePoolComponent) { + this->BoundingVolumePoolComponent->UpdateTransformFromCesium( + CesiumToUnreal); + } +} + +// Called when the game starts or when spawned +void ACesium3DTileset::BeginPlay() { + Super::BeginPlay(); + + this->LoadTileset(); + + // Search for level sequence. + for (auto sequenceActorIt = TActorIterator<ALevelSequenceActor>(GetWorld()); + sequenceActorIt; + ++sequenceActorIt) { + ALevelSequenceActor* sequenceActor = *sequenceActorIt; + + 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->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<UCesiumGltfComponent*> gltfComponents; + this->GetComponents<UCesiumGltfComponent>(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 { + CesiumGltf::Model* pModel = + std::get_if<CesiumGltf::Model>(&tileLoadResult.contentKind); + if (!pModel) + return asyncSystem.createResolvedFuture( + Cesium3DTilesSelection::TileLoadResultAndRenderResources{ + std::move(tileLoadResult), + nullptr}); + + CreateGltfOptions::CreateModelOptions options; + options.pModel = pModel; + options.alwaysIncludeTangents = this->_pActor->GetAlwaysIncludeTangents(); + options.createPhysicsMeshes = this->_pActor->GetCreatePhysicsMeshes(); + + options.pEncodedMetadataDescription = + &this->_pActor->_encodedMetadataDescription; + + TUniquePtr<UCesiumGltfComponent::HalfConstructed> pHalf = + UCesiumGltfComponent::CreateOffGameThread(transform, options); + return asyncSystem.createResolvedFuture( + Cesium3DTilesSelection::TileLoadResultAndRenderResources{ + std::move(tileLoadResult), + pHalf.Release()}); + } + + virtual void* prepareInMainThread( + Cesium3DTilesSelection::Tile& tile, + void* pLoadThreadResult) override { + const Cesium3DTilesSelection::TileContent& content = tile.getContent(); + if (content.isRenderContent()) { + TUniquePtr<UCesiumGltfComponent::HalfConstructed> pHalf( + reinterpret_cast<UCesiumGltfComponent::HalfConstructed*>( + pLoadThreadResult)); + const 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.getContentBoundingVolume().value_or(tile.getBoundingVolume())); + } + // 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<UCesiumGltfComponent::HalfConstructed*>( + pLoadThreadResult); + delete pHalf; + } else if (pMainThreadResult) { + UCesiumGltfComponent* pGltf = + reinterpret_cast<UCesiumGltfComponent*>(pMainThreadResult); + CesiumLifetime::destroyComponentRecursively(pGltf); + } + } + + virtual void* prepareRasterInLoadThread( + CesiumGltf::ImageCesium& image, + const std::any& rendererOptions) override { + auto ppOptions = + std::any_cast<FRasterOverlayRendererOptions*>(&rendererOptions); + check(ppOptions != nullptr && *ppOptions != nullptr); + if (ppOptions == nullptr || *ppOptions == nullptr) { + return nullptr; + } + + auto pOptions = *ppOptions; + + auto texture = CesiumTextureUtility::loadTextureAnyThreadPart( + CesiumTextureUtility::GltfImagePtr{&image}, + TextureAddress::TA_Clamp, + TextureAddress::TA_Clamp, + pOptions->filter, + pOptions->group, + pOptions->useMipmaps, + true); // TODO: sRGB should probably be configurable on the raster + // overlay + return texture.Release(); + } + + virtual void* prepareRasterInMainThread( + Cesium3DTilesSelection::RasterOverlayTile& rasterTile, + void* pLoadThreadResult) override { + + TUniquePtr<CesiumTextureUtility::LoadedTextureResult> pLoadedTexture{ + static_cast<CesiumTextureUtility::LoadedTextureResult*>( + pLoadThreadResult)}; + + if (!pLoadedTexture) { + return nullptr; + } + + // The image source pointer during loading may have been invalidated, + // so replace it. + CesiumTextureUtility::GltfImagePtr* pImageSource = + std::get_if<CesiumTextureUtility::GltfImagePtr>( + &pLoadedTexture->textureSource); + if (pImageSource) { + pImageSource->pImage = &rasterTile.getImage(); + } + + UTexture2D* pTexture = + CesiumTextureUtility::loadTextureGameThreadPart(pLoadedTexture.Get()); + if (!pTexture) { + return nullptr; + } + + pTexture->AddToRoot(); + return pTexture; + } + + virtual void freeRaster( + const Cesium3DTilesSelection::RasterOverlayTile& rasterTile, + void* pLoadThreadResult, + void* pMainThreadResult) noexcept override { + if (pLoadThreadResult) { + CesiumTextureUtility::LoadedTextureResult* pLoadedTexture = + static_cast<CesiumTextureUtility::LoadedTextureResult*>( + pLoadThreadResult); + CesiumTextureUtility::destroyHalfLoadedTexture(*pLoadedTexture); + delete pLoadedTexture; + } + + if (pMainThreadResult) { + UTexture* pTexture = static_cast<UTexture*>(pMainThreadResult); + pTexture->RemoveFromRoot(); + CesiumTextureUtility::destroyTexture(pTexture); + } + } + + virtual void attachRasterInMainThread( + const Cesium3DTilesSelection::Tile& tile, + int32_t overlayTextureCoordinateID, + const Cesium3DTilesSelection::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 (pRenderContent) { + UCesiumGltfComponent* pGltfContent = + reinterpret_cast<UCesiumGltfComponent*>( + pRenderContent->getRenderResources()); + if (pGltfContent) { + pGltfContent->AttachRasterTile( + tile, + rasterTile, + static_cast<UTexture2D*>(pMainThreadRendererResources), + translation, + scale, + overlayTextureCoordinateID); + } + } + } + + virtual void detachRasterInMainThread( + const Cesium3DTilesSelection::Tile& tile, + int32_t overlayTextureCoordinateID, + const Cesium3DTilesSelection::RasterOverlayTile& rasterTile, + void* pMainThreadRendererResources) noexcept override { + const Cesium3DTilesSelection::TileContent& content = tile.getContent(); + const Cesium3DTilesSelection::TileRenderContent* pRenderContent = + content.getRenderContent(); + if (pRenderContent) { + UCesiumGltfComponent* pGltfContent = + reinterpret_cast<UCesiumGltfComponent*>( + pRenderContent->getRenderResources()); + if (pGltfContent) { + pGltfContent->DetachRasterTile( + tile, + rasterTile, + static_cast<UTexture2D*>(pMainThreadRendererResources)); + } + } + } + +private: + ACesium3DTileset* _pActor; +}; + +void ACesium3DTileset::UpdateLoadStatus() { + TRACE_CPUPROFILER_EVENT_SCOPE(Cesium::UpdateLoadStatus) + + this->LoadProgress = this->_pTileset->computeLoadProgress(); + + if (this->LoadProgress < 100 || + this->_lastTilesWaitingForOcclusionResults > 0) { + this->_activeLoading = true; + } else if (this->_activeLoading && this->LoadProgress == 100) { + + // 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. + if (this->_lastTilesWaitingForOcclusionResults == 0) { + TRACE_CPUPROFILER_EVENT_SCOPE(Cesium::BroadcastOnTilesetLoaded) + + // Tileset just finished loading, we broadcast the update + UE_LOG(LogCesium, Verbose, TEXT("Broadcasting OnTileLoaded")); + OnTilesetLoaded.Broadcast(); + + // Tileset remains 100% loaded if we don't have to reload it + // so we don't want to keep on sending finished loading updates + this->_activeLoading = false; + } + } +} + +namespace { + +const TSharedRef<CesiumViewExtension, ESPMode::ThreadSafe>& +getCesiumViewExtension() { + static TSharedRef<CesiumViewExtension, ESPMode::ThreadSafe> + cesiumViewExtension = + GEngine->ViewExtensions->NewExtension<CesiumViewExtension>(); + return cesiumViewExtension; +} + +} // namespace + +void ACesium3DTileset::LoadTileset() { + TRACE_CPUPROFILER_EVENT_SCOPE(Cesium::LoadTileset) + + this->RootComponent->SetMobility(Mobility); + + if (this->_pTileset) { + // Tileset already loaded, do nothing. + return; + } + + UWorld* pWorld = this->GetWorld(); + if (!pWorld) { + return; + } + +#if ENGINE_MAJOR_VERSION == 5 && ENGINE_MINOR_VERSION == 0 + AWorldSettings* pWorldSettings = pWorld->GetWorldSettings(); + if (pWorldSettings && !pWorldSettings->bEnableLargeWorlds) { + pWorldSettings->bEnableLargeWorlds = true; + UE_LOG( + LogCesium, + Warning, + TEXT( + "Cesium for Unreal has enabled the \"Enable Large Worlds\" option in this world's settings, as it is required in order to avoid serious culling problems with Cesium3DTilesets in Unreal Engine 5."), + *this->Url); + } +#endif + + const TSharedRef<CesiumViewExtension, ESPMode::ThreadSafe>& + cesiumViewExtension = getCesiumViewExtension(); + const std::shared_ptr<CesiumAsync::IAssetAccessor>& 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<UCesiumRuntimeSettings>() + ->EnableExperimentalOcclusionCullingFeature); + + TArray<UCesiumRasterOverlay*> rasterOverlays; + this->GetComponents<UCesiumRasterOverlay>(rasterOverlays); + + const UCesiumEncodedMetadataComponent* pEncodedMetadataDescriptionComponent = + this->FindComponentByClass<UCesiumEncodedMetadataComponent>(); + if (pEncodedMetadataDescriptionComponent) { + this->_encodedMetadataDescription = { + pEncodedMetadataDescriptionComponent->FeatureTables, + pEncodedMetadataDescriptionComponent->FeatureTextures}; + } else { + this->_encodedMetadataDescription = {}; + } + + ACesiumCreditSystem* pCreditSystem = this->ResolveCreditSystem(); + + this->_cesiumViewExtension = cesiumViewExtension; + + if (GetDefault<UCesiumRuntimeSettings>() + ->EnableExperimentalOcclusionCullingFeature && + this->EnableOcclusionCulling && !this->BoundingVolumePoolComponent) { + const glm::dmat4& cesiumToUnreal = + GetCesiumTilesetToUnrealRelativeWorldTransform(); + this->BoundingVolumePoolComponent = + NewObject<UCesiumBoundingVolumePoolComponent>(this); + this->BoundingVolumePoolComponent->SetUsingAbsoluteLocation(true); + this->BoundingVolumePoolComponent->SetFlags( + RF_Transient | RF_DuplicateTransient | RF_TextExportTransient); + this->BoundingVolumePoolComponent->RegisterComponent(); + this->BoundingVolumePoolComponent->UpdateTransformFromCesium( + cesiumToUnreal); + } + + if (this->BoundingVolumePoolComponent) { + this->BoundingVolumePoolComponent->initPool(this->OcclusionPoolSize); + } + + Cesium3DTilesSelection::TilesetExternals externals{ + pAssetAccessor, + std::make_shared<UnrealResourcePreparer>(this), + asyncSystem, + pCreditSystem ? pCreditSystem->GetExternalCreditSystem() : nullptr, + spdlog::default_logger(), + (GetDefault<UCesiumRuntimeSettings>() + ->EnableExperimentalOcclusionCullingFeature && + this->EnableOcclusionCulling && this->BoundingVolumePoolComponent) + ? this->BoundingVolumePoolComponent->getPool() + : nullptr}; + + this->_startTime = std::chrono::high_resolution_clock::now(); + + Cesium3DTilesSelection::TilesetOptions options; + + options.enableOcclusionCulling = + GetDefault<UCesiumRuntimeSettings>() + ->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); + + switch (this->TilesetSource) { + case ETilesetSource::FromUrl: + UE_LOG(LogCesium, Log, TEXT("Loading tileset from URL %s"), *this->Url); + this->_pTileset = MakeUnique<Cesium3DTilesSelection::Tileset>( + 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() + ? GetDefault<UCesiumRuntimeSettings>()->DefaultIonAccessToken + : this->IonAccessToken; + if (!IonAssetEndpointUrl.IsEmpty()) { + this->_pTileset = MakeUnique<Cesium3DTilesSelection::Tileset>( + externals, + static_cast<uint32_t>(this->IonAssetID), + TCHAR_TO_UTF8(*token), + options, + TCHAR_TO_UTF8(*IonAssetEndpointUrl)); + } else { + this->_pTileset = MakeUnique<Cesium3DTilesSelection::Tileset>( + externals, + static_cast<uint32_t>(this->IonAssetID), + TCHAR_TO_UTF8(*token), + options); + } + break; + } + + for (UCesiumRasterOverlay* pOverlay : rasterOverlays) { + if (pOverlay->IsActive()) { + pOverlay->AddToTileset(); + } + } + + switch (this->TilesetSource) { + 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<UCesiumRuntimeSettings>()->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::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<UCesiumRasterOverlay*> rasterOverlays; + this->GetComponents<UCesiumRasterOverlay>(rasterOverlays); + for (UCesiumRasterOverlay* pOverlay : rasterOverlays) { + if (pOverlay->IsActive()) { + pOverlay->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::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<FCesiumCamera> ACesium3DTileset::GetCameras() const { + TRACE_CPUPROFILER_EVENT_SCOPE(Cesium::CollectCameras) + std::vector<FCesiumCamera> cameras = this->GetPlayerCameras(); + + std::vector<FCesiumCamera> sceneCaptures = this->GetSceneCaptures(); + cameras.insert( + cameras.end(), + std::make_move_iterator(sceneCaptures.begin()), + std::make_move_iterator(sceneCaptures.end())); + +#if WITH_EDITOR + std::vector<FCesiumCamera> editorCameras = this->GetEditorCameras(); + cameras.insert( + cameras.end(), + std::make_move_iterator(editorCameras.begin()), + std::make_move_iterator(editorCameras.end())); +#endif + + ACesiumCameraManager* pCameraManager = + ACesiumCameraManager::GetDefaultCameraManager(this->GetWorld()); + if (pCameraManager) { + const TMap<int32, FCesiumCamera>& extraCameras = + pCameraManager->GetCameras(); + cameras.reserve(cameras.size() + extraCameras.Num()); + for (auto cameraIt : extraCameras) { + cameras.push_back(cameraIt.Value); + } + } + + return cameras; +} + +std::vector<FCesiumCamera> ACesium3DTileset::GetPlayerCameras() const { + UWorld* pWorld = this->GetWorld(); + if (!pWorld) { + return {}; + } + + double worldToMeters = 100.0; + AWorldSettings* pWorldSettings = pWorld->GetWorldSettings(); + if (pWorldSettings) { + worldToMeters = pWorldSettings->WorldToMeters; + } + + TSharedPtr<IStereoRendering, ESPMode::ThreadSafe> pStereoRendering = nullptr; + if (GEngine) { + pStereoRendering = GEngine->StereoRenderingDevice; + } + + bool useStereoRendering = false; + if (pStereoRendering && pStereoRendering->IsStereoEnabled()) { + useStereoRendering = true; + } + + std::vector<FCesiumCamera> cameras; + cameras.reserve(pWorld->GetNumPlayerControllers()); + + for (auto playerControllerIt = pWorld->GetPlayerControllerIterator(); + playerControllerIt; + playerControllerIt++) { + + const TWeakObjectPtr<APlayerController> 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); + if (sizeX < 1 || sizeY < 1) { + continue; + } + + float dpiScalingFactor = 1.0f; + if (this->_scaleUsingDPI) { + ULocalPlayer* LocPlayer = Cast<ULocalPlayer>(pPlayerController->Player); + if (LocPlayer && LocPlayer->ViewportClient) { + dpiScalingFactor = LocPlayer->ViewportClient->GetDPIScale(); + } + } + + if (useStereoRendering) { +#if ENGINE_MAJOR_VERSION >= 5 + const auto leftEye = EStereoscopicEye::eSSE_LEFT_EYE; + const auto rightEye = EStereoscopicEye::eSSE_RIGHT_EYE; +#else + const auto leftEye = EStereoscopicPass::eSSP_LEFT_EYE; + const auto rightEye = EStereoscopicPass::eSSP_RIGHT_EYE; +#endif + + uint32 stereoLeftSizeX = static_cast<uint32>(sizeX); + uint32 stereoLeftSizeY = static_cast<uint32>(sizeY); + uint32 stereoRightSizeX = static_cast<uint32>(sizeX); + uint32 stereoRightSizeY = static_cast<uint32>(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 + CesiumReal one_over_tan_half_hfov = projection.M[0][0]; + + CesiumReal 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); + + CesiumReal one_over_tan_half_hfov = projection.M[0][0]; + + CesiumReal 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<FCesiumCamera> 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<AActor*> sceneCaptures; + static TSubclassOf<ASceneCapture2D> SceneCapture2D = + ASceneCapture2D::StaticClass(); + UGameplayStatics::GetAllActorsOfClass(this, SceneCapture2D, sceneCaptures); + + std::vector<FCesiumCamera> cameras; + cameras.reserve(sceneCaptures.Num()); + + for (AActor* pActor : sceneCaptures) { + ASceneCapture2D* pSceneCapture = static_cast<ASceneCapture2D*>(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) { + + 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); +} + +#if WITH_EDITOR +std::vector<FCesiumCamera> 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<FEditorViewportClient*>& viewportClients = + GEditor->GetAllViewportClients(); + + std::vector<FCesiumCamera> 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<float>(size.X) / dpiScalingFactor; + size.Y = static_cast<float>(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 { + +PRAGMA_DISABLE_DEPRECATION_WARNINGS + +/** + * @brief Check if the given tile is contained in one of the given exclusion + * zones. + * + * TODO Add details here what that means + * Old comment: + * Consider Exclusion zone to drop this tile... Ideally, should be + * considered in Cesium3DTilesSelection::ViewState to avoid loading the tile + * first... + * + * @param exclusionZones The exclusion zones + * @param tile The tile + * @return The result of the test + */ +bool isInExclusionZone( + const TArray<FCesiumExclusionZone>& exclusionZones, + Cesium3DTilesSelection::Tile const* tile) { + if (exclusionZones.Num() == 0) { + return false; + } + // Apparently, only tiles with bounding REGIONS are + // checked for the exclusion... + const CesiumGeospatial::BoundingRegion* pRegion = + std::get_if<CesiumGeospatial::BoundingRegion>(&tile->getBoundingVolume()); + if (!pRegion) { + return false; + } + for (FCesiumExclusionZone ExclusionZone : exclusionZones) { + CesiumGeospatial::GlobeRectangle cgExclusionZone = + CesiumGeospatial::GlobeRectangle::fromDegrees( + ExclusionZone.West, + ExclusionZone.South, + ExclusionZone.East, + ExclusionZone.North); + if (cgExclusionZone.computeIntersection(pRegion->getRectangle())) { + return true; + } + } + return false; +} + +PRAGMA_ENABLE_DEPRECATION_WARNINGS + +void removeVisibleTilesFromList( + std::vector<Cesium3DTilesSelection::Tile*>& list, + const std::vector<Cesium3DTilesSelection::Tile*>& 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<Cesium3DTilesSelection::Tile*>& tiles) { + TRACE_CPUPROFILER_EVENT_SCOPE(Cesium::HideTiles) + for (Cesium3DTilesSelection::Tile* pTile : tiles) { + if (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<UCesiumGltfComponent*>( + pRenderContent->getRenderResources()); + if (Gltf && Gltf->IsVisible()) { + TRACE_CPUPROFILER_EVENT_SCOPE(Cesium::SetVisibilityFalse) + Gltf->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<Cesium3DTilesSelection::Tile*>& tiles) { + TRACE_CPUPROFILER_EVENT_SCOPE(Cesium::RemoveCollisionForTiles) + for (Cesium3DTilesSelection::Tile* pTile : tiles) { + if (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<UCesiumGltfComponent*>( + pRenderContent->getRenderResources()); + if (Gltf) { + TRACE_CPUPROFILER_EVENT_SCOPE(Cesium::SetCollisionDisabled) + Gltf->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<USceneComponent*>& ChildrenComponents = + Gltf->GetAttachChildren(); + + for (USceneComponent* ChildComponent : ChildrenComponents) { + UCesiumGltfPrimitiveComponent* PrimitiveComponent = + Cast<UCesiumGltfPrimitiveComponent>(ChildComponent); + if (PrimitiveComponent != nullptr) { + if (PrimitiveComponent->GetCollisionObjectType() != + BodyInstance.GetObjectType()) { + PrimitiveComponent->SetCollisionObjectType( + BodyInstance.GetObjectType()); + } + const UEnum* ChannelEnum = StaticEnum<ECollisionChannel>(); + if (ChannelEnum) { + FCollisionResponseContainer responseContainer = + BodyInstance.GetResponseToChannels(); + PrimitiveComponent->SetCollisionResponseToChannels(responseContainer); + } + } + } +} +} // namespace + +void ACesium3DTileset::updateTilesetOptionsFromProperties() { + Cesium3DTilesSelection::TilesetOptions& options = + this->_pTileset->getOptions(); + options.maximumScreenSpaceError = + static_cast<double>(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<UCesiumRuntimeSettings>() + ->EnableExperimentalOcclusionCullingFeature && + this->EnableOcclusionCulling; + + options.delayRefinementForOcclusion = this->DelayRefinementForOcclusion; + options.enableFogCulling = this->EnableFogCulling; + options.enforceCulledScreenSpaceError = this->EnforceCulledScreenSpaceError; + options.culledScreenSpaceError = + static_cast<double>(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->LogSelectionStats) { + return; + } + + if (result.tilesToRenderThisFrame.size() != this->_lastTilesRendered || + result.tilesLoadingLowPriority != this->_lastTilesLoadingLowPriority || + result.tilesLoadingMediumPriority != + this->_lastTilesLoadingMediumPriority || + result.tilesLoadingHighPriority != this->_lastTilesLoadingHighPriority || + 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->_lastTilesLoadingLowPriority = result.tilesLoadingLowPriority; + this->_lastTilesLoadingMediumPriority = result.tilesLoadingMediumPriority; + this->_lastTilesLoadingHighPriority = result.tilesLoadingHighPriority; + + this->_lastTilesVisited = result.tilesVisited; + this->_lastCulledTilesVisited = result.culledTilesVisited; + this->_lastTilesCulled = result.tilesCulled; + this->_lastTilesOccluded = result.tilesOccluded; + this->_lastTilesWaitingForOcclusionResults = + result.tilesWaitingForOcclusionResults; + this->_lastMaxDepthVisited = result.maxDepthVisited; + + UE_LOG( + LogCesium, + Display, + TEXT( + "%s: %d ms, Visited %d, Culled Visited %d, Rendered %d, Culled %d, Occluded %d, Waiting For Occlusion Results %d, Max Depth Visited: %d, Loading-Low %d, Loading-Medium %d, Loading-High %d, Loaded tiles %g%%"), + *this->GetName(), + (std::chrono::high_resolution_clock::now() - this->_startTime).count() / + 1000000, + result.tilesVisited, + result.culledTilesVisited, + result.tilesToRenderThisFrame.size(), + result.tilesCulled, + result.tilesOccluded, + result.tilesWaitingForOcclusionResults, + result.maxDepthVisited, + result.tilesLoadingLowPriority, + result.tilesLoadingMediumPriority, + result.tilesLoadingHighPriority, + this->LoadProgress); + } +} + +void ACesium3DTileset::showTilesToRender( + const std::vector<Cesium3DTilesSelection::Tile*>& tiles) { + TRACE_CPUPROFILER_EVENT_SCOPE(Cesium::ShowTilesToRender) + + for (Cesium3DTilesSelection::Tile* pTile : tiles) { + if (pTile->getState() != Cesium3DTilesSelection::TileLoadState::Done) { + continue; + } + + PRAGMA_DISABLE_DEPRECATION_WARNINGS + if (isInExclusionZone(ExclusionZones_DEPRECATED, pTile)) { + continue; + } + PRAGMA_ENABLE_DEPRECATION_WARNINGS + + // That looks like some reeeally entertaining debug session...: + // const Cesium3DTilesSelection::TileID& id = pTile->getTileID(); + // const CesiumGeometry::QuadtreeTileID* pQuadtreeID = + // std::get_if<CesiumGeometry::QuadtreeTileID>(&id); if (!pQuadtreeID || + // pQuadtreeID->level != 14 || pQuadtreeID->x != 5503 || pQuadtreeID->y != + // 11626) { continue; + //} + + const Cesium3DTilesSelection::TileContent& content = pTile->getContent(); + const Cesium3DTilesSelection::TileRenderContent* pRenderContent = + content.getRenderContent(); + if (!pRenderContent) { + continue; + } + + UCesiumGltfComponent* Gltf = static_cast<UCesiumGltfComponent*>( + 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; + } + + applyActorCollisionSettings(BodyInstance, Gltf); + + if (Gltf->GetAttachParent() == nullptr) { + + // The AttachToComponent method is ridiculously complex, + // so print a warning if attaching fails for some reason + bool attached = Gltf->AttachToComponent( + this->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 (!Gltf->IsVisible()) { + TRACE_CPUPROFILER_EVENT_SCOPE(Cesium::SetVisibilityTrue) + Gltf->SetVisibility(true, true); + } + + { + TRACE_CPUPROFILER_EVENT_SCOPE(Cesium::SetCollisionEnabled) + Gltf->SetCollisionEnabled(ECollisionEnabled::QueryAndPhysics); + } + } +} + +static void updateTileFade(Cesium3DTilesSelection::Tile* pTile, bool fadingIn) { + if (!pTile || !pTile->getContent().isRenderContent()) { + return; + } + + if (pTile->getState() != Cesium3DTilesSelection::TileLoadState::Done) { + return; + } + + const Cesium3DTilesSelection::TileContent& content = pTile->getContent(); + const Cesium3DTilesSelection::TileRenderContent* pRenderContent = + content.getRenderContent(); + if (!pRenderContent) { + return; + } + + UCesiumGltfComponent* pGltf = reinterpret_cast<UCesiumGltfComponent*>( + pRenderContent->getRenderResources()); + if (!pGltf) { + return; + } + + 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); + + UCesium3DTilesetRoot* pRoot = Cast<UCesium3DTilesetRoot>(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<USceneComponent*>& children = + this->BoundingVolumePoolComponent->GetAttachChildren(); + for (USceneComponent* pChild : children) { + UCesiumBoundingVolumeComponent* pBoundingVolume = + Cast<UCesiumBoundingVolumeComponent>(pChild); + + if (!pBoundingVolume) { + continue; + } + + pBoundingVolume->UpdateOcclusion(*this->_cesiumViewExtension.Get()); + } + } + + updateTilesetOptionsFromProperties(); + + std::vector<FCesiumCamera> cameras = this->GetCameras(); + if (cameras.empty()) { + return; + } + + glm::dmat4 unrealWorldToTileset = glm::affineInverse( + this->GetCesiumTilesetToUnrealRelativeWorldTransform()); + + std::vector<Cesium3DTilesSelection::ViewState> frustums; + for (const FCesiumCamera& camera : cameras) { + frustums.push_back( + CreateViewStateFromViewParameters(camera, unrealWorldToTileset)); + } + + const Cesium3DTilesSelection::ViewUpdateResult& result = + this->_captureMovieMode + ? this->_pTileset->updateViewOffline(frustums) + : this->_pTileset->updateView(frustums, DeltaTime); + updateLastViewUpdateResultState(result); + this->UpdateLoadStatus(); + + removeCollisionForTiles(result.tilesFadingOut); + + removeVisibleTilesFromList( + _tilesToHideNextFrame, + result.tilesToRenderThisFrame); + hideTiles(_tilesToHideNextFrame); + + _tilesToHideNextFrame.clear(); + for (Cesium3DTilesSelection::Tile* pTile : result.tilesFadingOut) { + Cesium3DTilesSelection::TileRenderContent* pRenderContent = + pTile->getContent().getRenderContent(); + if (!this->UseLodTransitions || + (pRenderContent && + pRenderContent->getLodTransitionFadePercentage() >= 1.0f)) { + _tilesToHideNextFrame.push_back(pTile); + } + } + + showTilesToRender(result.tilesToRenderThisFrame); + + if (this->UseLodTransitions) { + TRACE_CPUPROFILER_EVENT_SCOPE(Cesium::UpdateTileFades) + + for (Cesium3DTilesSelection::Tile* pTile : result.tilesToRenderThisFrame) { + updateTileFade(pTile, true); + } + + for (Cesium3DTilesSelection::Tile* pTile : result.tilesFadingOut) { + updateTileFade(pTile, false); + } + } +} + +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(); +} + +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 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, IonAssetEndpointUrl) || + PropName == + GET_MEMBER_NAME_CHECKED(ACesium3DTileset, CreatePhysicsMeshes) || + 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, 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, Mobility) || + // 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<UCesiumRasterOverlay*> rasterOverlays; + this->GetComponents<UCesiumRasterOverlay>(rasterOverlays); + + for (UCesiumRasterOverlay* pOverlay : rasterOverlays) { + pOverlay->Refresh(); + } + } +} + +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<UCesiumRuntimeSettings>() + ->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 0000000000000000000000000000000000000000..ca40c201de6a6e031565d201bd13d0cdfb4faa94 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/CesiumRuntime/Private/Cesium3DTilesetRoot.cpp @@ -0,0 +1,102 @@ +// Copyright 2020-2021 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() + : _worldOriginLocation(0.0), + _absoluteLocation(0.0, 0.0, 0.0), + _tilesetToUnrealRelativeWorld(1.0) { + PrimaryComponentTick.bCanEverTick = false; +} + +void UCesium3DTilesetRoot::ApplyWorldOffset( + const FVector& InOffset, + bool bWorldShift) { + USceneComponent::ApplyWorldOffset(InOffset, bWorldShift); + + const FIntVector& oldOrigin = this->GetWorld()->OriginLocation; + this->_worldOriginLocation = VecMath::subtract3D(oldOrigin, InOffset); + + // Do _not_ call _updateAbsoluteLocation. The absolute position doesn't change + // with an origin rebase, and we'll lose precision if we update the absolute + // location here. + + this->_updateTilesetToUnrealRelativeWorldTransform(); +} + +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(); + const FIntVector& originLocation = this->GetWorld()->OriginLocation; + this->_absoluteLocation = VecMath::add3D(originLocation, newLocation); + this->_worldOriginLocation = VecMath::createVector3D(originLocation); +} + +void UCesium3DTilesetRoot::_updateTilesetToUnrealRelativeWorldTransform() { + ACesium3DTileset* pTileset = this->GetOwner<ACesium3DTileset>(); + + const glm::dmat4& ellipsoidCenteredToUnrealWorld = + pTileset->ResolveGeoreference() + ->GetGeoTransforms() + .GetEllipsoidCenteredToAbsoluteUnrealWorldTransform(); + + glm::dvec3 relativeLocation = + this->_absoluteLocation - this->_worldOriginLocation; + + FMatrix tilesetActorToUeLocal = + this->GetComponentToWorld().ToMatrixWithScale(); + glm::dmat4 ueAbsoluteToUeLocal = + VecMath::createMatrix4D(tilesetActorToUeLocal, relativeLocation); + + this->_tilesetToUnrealRelativeWorld = + ueAbsoluteToUeLocal * ellipsoidCenteredToUnrealWorld; + + 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 0000000000000000000000000000000000000000..13848a702c9cc9c7eea53d4a27f367d31478f1de --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/CesiumRuntime/Private/Cesium3DTilesetRoot.h @@ -0,0 +1,61 @@ +// Copyright 2020-2021 CesiumGS, Inc. and Contributors + +#pragma once + +#include "Components/SceneComponent.h" +#include "CoreMinimal.h" +#include <glm/mat4x4.hpp> +#include <glm/vec3.hpp> +#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; + + virtual void + ApplyWorldOffset(const FVector& InOffset, bool bWorldShift) override; + + 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 _worldOriginLocation; + 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 0000000000000000000000000000000000000000..c8c212478c4f7dc9628d5934ebd49b8b645b3d95 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/CesiumRuntime/Private/CesiumActors.cpp @@ -0,0 +1,25 @@ +// Copyright 2020-2021 CesiumGS, Inc. and Contributors + +#include "CesiumActors.h" +#include "CesiumRuntime.h" +#include "Engine/World.h" + +#include <glm/glm.hpp> + +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); +} diff --git a/Plugins/CesiumForUnreal/Source/CesiumRuntime/Private/CesiumActors.h b/Plugins/CesiumForUnreal/Source/CesiumRuntime/Private/CesiumActors.h new file mode 100644 index 0000000000000000000000000000000000000000..c9fa2fb63164acdc2796f9d65d30344de893e165 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/CesiumRuntime/Private/CesiumActors.h @@ -0,0 +1,24 @@ +// Copyright 2020-2021 CesiumGS, Inc. and Contributors + +#pragma once + +#include "GameFramework/Actor.h" +#include <glm/glm.hpp> + +/** + * @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); +}; diff --git a/Plugins/CesiumForUnreal/Source/CesiumRuntime/Private/CesiumBingMapsRasterOverlay.cpp b/Plugins/CesiumForUnreal/Source/CesiumRuntime/Private/CesiumBingMapsRasterOverlay.cpp new file mode 100644 index 0000000000000000000000000000000000000000..9d81657440894a989f9b6f34d36c7935d3f2f1cb --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/CesiumRuntime/Private/CesiumBingMapsRasterOverlay.cpp @@ -0,0 +1,48 @@ +// Copyright 2020-2021 CesiumGS, Inc. and Contributors + +#include "CesiumBingMapsRasterOverlay.h" +#include "Cesium3DTilesSelection/BingMapsRasterOverlay.h" +#include "Cesium3DTilesSelection/Tileset.h" + +std::unique_ptr<Cesium3DTilesSelection::RasterOverlay> +UCesiumBingMapsRasterOverlay::CreateOverlay( + const Cesium3DTilesSelection::RasterOverlayOptions& options) { + std::string mapStyle; + + switch (this->MapStyle) { + case EBingMapsStyle::Aerial: + mapStyle = Cesium3DTilesSelection::BingMapsStyle::AERIAL; + break; + case EBingMapsStyle::AerialWithLabelsOnDemand: + mapStyle = + Cesium3DTilesSelection::BingMapsStyle::AERIAL_WITH_LABELS_ON_DEMAND; + break; + case EBingMapsStyle::RoadOnDemand: + mapStyle = Cesium3DTilesSelection::BingMapsStyle::ROAD_ON_DEMAND; + break; + case EBingMapsStyle::CanvasDark: + mapStyle = Cesium3DTilesSelection::BingMapsStyle::CANVAS_DARK; + break; + case EBingMapsStyle::CanvasLight: + mapStyle = Cesium3DTilesSelection::BingMapsStyle::CANVAS_LIGHT; + break; + case EBingMapsStyle::CanvasGray: + mapStyle = Cesium3DTilesSelection::BingMapsStyle::CANVAS_GRAY; + break; + case EBingMapsStyle::OrdnanceSurvey: + mapStyle = Cesium3DTilesSelection::BingMapsStyle::ORDNANCE_SURVEY; + break; + case EBingMapsStyle::CollinsBart: + mapStyle = Cesium3DTilesSelection::BingMapsStyle::COLLINS_BART; + break; + } + + return std::make_unique<Cesium3DTilesSelection::BingMapsRasterOverlay>( + TCHAR_TO_UTF8(*this->MaterialLayerKey), + "https://dev.virtualearth.net", + TCHAR_TO_UTF8(*this->BingMapsKey), + mapStyle, + "", + CesiumGeospatial::Ellipsoid::WGS84, + options); +} diff --git a/Plugins/CesiumForUnreal/Source/CesiumRuntime/Private/CesiumBoundingVolumeComponent.cpp b/Plugins/CesiumForUnreal/Source/CesiumRuntime/Private/CesiumBoundingVolumeComponent.cpp new file mode 100644 index 0000000000000000000000000000000000000000..74e3829d098277e3e5201e18b01d754653fa5fc9 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/CesiumRuntime/Private/CesiumBoundingVolumeComponent.cpp @@ -0,0 +1,155 @@ +// Copyright 2020-2021 CesiumGS, Inc. and Contributors + +#include "CesiumBoundingVolumeComponent.h" +#include "CalcBounds.h" +#include "CesiumGeoreference.h" +#include "CesiumLifetime.h" +#include "UObject/UObjectGlobals.h" +#include "VecMath.h" +#include <optional> +#include <variant> + +using namespace Cesium3DTilesSelection; + +UCesiumBoundingVolumePoolComponent::UCesiumBoundingVolumePoolComponent() + : _cesiumToUnreal(1.0) { + SetMobility(EComponentMobility::Movable); +} + +void UCesiumBoundingVolumePoolComponent::initPool(int32 maxPoolSize) { + this->_pPool = std::make_shared<CesiumBoundingVolumePool>(this, maxPoolSize); +} + +TileOcclusionRendererProxy* UCesiumBoundingVolumePoolComponent::createProxy() { + UCesiumBoundingVolumeComponent* pBoundingVolume = + NewObject<UCesiumBoundingVolumeComponent>(this); + pBoundingVolume->SetVisibility(false); + pBoundingVolume->bUseAsOccluder = false; + pBoundingVolume->SetUsingAbsoluteLocation(true); + + 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<USceneComponent*>& children = this->GetAttachChildren(); + for (USceneComponent* pChild : children) { + UCesiumBoundingVolumeComponent* pBoundingVolume = + Cast<UCesiumBoundingVolumeComponent>(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<size_t>(&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; + } + + TileOcclusionState occlusionState = + cesiumViewExtension.getPrimitiveOcclusionState( + this->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() { + this->SetUsingAbsoluteLocation(true); + this->SetUsingAbsoluteRotation(true); + this->SetUsingAbsoluteScale(true); + + 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 0000000000000000000000000000000000000000..79cf69d019c445da0b8cf98ec09544398f0bf539 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/CesiumRuntime/Private/CesiumBoundingVolumeComponent.h @@ -0,0 +1,137 @@ +// Copyright 2020-2021 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 <Cesium3DTilesSelection/BoundingVolume.h> +#include <Cesium3DTilesSelection/TileOcclusionRendererProxy.h> +#include <glm/mat4x4.hpp> +#include <memory> +#include <optional> +#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<Cesium3DTilesSelection::TileOcclusionRendererProxyPool>& + 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<Cesium3DTilesSelection::TileOcclusionRendererProxyPool> + _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 0000000000000000000000000000000000000000..419ed836d580eb282faa932483b6aa442ba26e8b --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/CesiumRuntime/Private/CesiumCamera.cpp @@ -0,0 +1,35 @@ +// Copyright 2020-2021 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 0000000000000000000000000000000000000000..0da50560c7df40d0451b050cb900ef5c27736881 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/CesiumRuntime/Private/CesiumCameraManager.cpp @@ -0,0 +1,98 @@ +// Copyright 2020-2021 CesiumGS, Inc. and Contributors + +#include "CesiumCameraManager.h" +#include "CesiumRuntime.h" +#include "Engine/World.h" +#include "EngineUtils.h" +#include <string> +#include <vector> + +FName ACesiumCameraManager::DEFAULT_CAMERAMANAGER_TAG = + FName("DEFAULT_CAMERAMANAGER"); + +/*static*/ ACesiumCameraManager* ACesiumCameraManager::GetDefaultCameraManager( + const UObject* WorldContextObject) { + 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<AActor> actorIterator( + world, + ACesiumCameraManager::StaticClass(), + flags); + actorIterator; + ++actorIterator) { + AActor* actor = *actorIterator; + if (actor->ActorHasTag(DEFAULT_CAMERAMANAGER_TAG)) { + pCameraManager = Cast<ACesiumCameraManager>(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; + pCameraManager = world->SpawnActor<ACesiumCameraManager>(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; +} + +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::UpdateCamera( + int32 cameraId, + UPARAM(ref) const FCesiumCamera& camera) { + FCesiumCamera* pCurrentCamera = this->_cameras.Find(cameraId); + if (pCurrentCamera) { + *pCurrentCamera = camera; + return true; + } + + return false; +} + +const TMap<int32, FCesiumCamera>& 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 0000000000000000000000000000000000000000..356ad4dfd2e4b552c4093a25f50fd321147d2030 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/CesiumRuntime/Private/CesiumCartographicPolygon.cpp @@ -0,0 +1,71 @@ +// Copyright 2020-2021 CesiumGS, Inc. and Contributors + +#include "CesiumCartographicPolygon.h" +#include "CesiumUtility/Math.h" +#include "Components/SceneComponent.h" +#include "StaticMeshResources.h" +#include <glm/glm.hpp> + +using namespace CesiumGeospatial; + +ACesiumCartographicPolygon::ACesiumCartographicPolygon() { + PrimaryActorTick.bCanEverTick = false; + + this->Polygon = CreateDefaultSubobject<USplineComponent>(TEXT("Selection")); + this->SetRootComponent(this->Polygon); + this->Polygon->SetClosedLoop(true); + this->Polygon->SetMobility(EComponentMobility::Movable); + + this->Polygon->SetSplinePoints( + TArray<FVector>{ + 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(); + + this->GlobeAnchor = + CreateDefaultSubobject<UCesiumGlobeAnchorComponent>(TEXT("GlobeAnchor")); +} + +void ACesiumCartographicPolygon::OnConstruction(const FTransform& Transform) { + this->MakeLinear(); +} + +void ACesiumCartographicPolygon::BeginPlay() { this->MakeLinear(); } + +CesiumGeospatial::CartographicPolygon +ACesiumCartographicPolygon::CreateCartographicPolygon() const { + int32 splinePointsCount = this->Polygon->GetNumberOfSplinePoints(); + + if (splinePointsCount < 3) { + return CartographicPolygon({}); + } + + std::vector<glm::dvec2> polygon(splinePointsCount); + + for (size_t i = 0; i < splinePointsCount; ++i) { + const FVector& unrealPosition = this->Polygon->GetLocationAtSplinePoint( + i, + ESplineCoordinateSpace::World); + glm::dvec3 cartographic = + this->GlobeAnchor->ResolveGeoreference() + ->TransformUnrealToLongitudeLatitudeHeight(glm::dvec3( + unrealPosition.X, + unrealPosition.Y, + unrealPosition.Z)); + 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); + } +} diff --git a/Plugins/CesiumForUnreal/Source/CesiumRuntime/Private/CesiumCreditSystem.cpp b/Plugins/CesiumForUnreal/Source/CesiumRuntime/Private/CesiumCreditSystem.cpp new file mode 100644 index 0000000000000000000000000000000000000000..3470b6b927066779724f661338972fdb8e693fdb --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/CesiumRuntime/Private/CesiumCreditSystem.cpp @@ -0,0 +1,291 @@ +// Copyright 2020-2021 CesiumGS, Inc. and Contributors + +#include "CesiumCreditSystem.h" +#include "Cesium3DTilesSelection/CreditSystem.h" +#include "CesiumCreditSystemBPLoader.h" +#include "CesiumRuntime.h" +#include "Engine/World.h" +#include "EngineUtils.h" +#include "ScreenCreditsWidget.h" +#include <string> +#include <tidybuffio.h> +#include <vector> + +/*static*/ UClass* 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; + } + TArray<AActor*>& Actors = Level->Actors; + AActor** 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<ACesiumCreditSystem>(DefaultCreditSystem); +} +} // 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<UCesiumCreditSystemBPLoader>(); + CesiumCreditSystemBP = bpLoader->CesiumCreditSystemBP; + 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<AActor> actorIterator( + world, + ACesiumCreditSystem::StaticClass(), + flags); + actorIterator; + ++actorIterator) { + AActor* actor = *actorIterator; + if (actor->ActorHasTag(DEFAULT_CREDITSYSTEM_TAG)) { + pCreditSystem = Cast<ACesiumCreditSystem>(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; + pCreditSystem = world->SpawnActor<ACesiumCreditSystem>( + 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() + : _pCreditSystem(std::make_shared<Cesium3DTilesSelection::CreditSystem>()), + _lastCreditsCount(0) { + PrimaryActorTick.bCanEverTick = true; +} + +void ACesiumCreditSystem::BeginPlay() { + Super::BeginPlay(); + if (!CreditsWidget) { + CreditsWidget = + CreateWidget<UScreenCreditsWidget>(GetWorld(), CreditsWidgetClass); + } + if (IsValid(CreditsWidget) && !IsRunningDedicatedServer()) { + CreditsWidget->AddToViewport(); + } +} + +bool ACesiumCreditSystem::ShouldTickIfViewportsOnly() const { return true; } + +void ACesiumCreditSystem::Tick(float DeltaTime) { + Super::Tick(DeltaTime); + + if (!_pCreditSystem || !IsValid(CreditsWidget)) { + return; + } + + const std::vector<Cesium3DTilesSelection::Credit>& 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 first = true; + for (int i = 0; i < creditsToShowThisFrame.size(); i++) { + const Cesium3DTilesSelection::Credit& credit = creditsToShowThisFrame[i]; + if (i != 0) { + Credits += "\n"; + } + 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}); + } + Credits += CreditRtf; + if (_pCreditSystem->shouldBeShownOnScreen(credit)) { + if (first) { + first = false; + } else { + OnScreenCredits += TEXT(" \u2022 "); + } + OnScreenCredits += CreditRtf; + } + } + OnScreenCredits += "<credits url=\"popup\" text=\" Data attribution\"/>"; + 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<const char*>(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 += + "<credits url=\"" + parentUrl + "\"" + " text=\"" + text + "\"/>"; + } 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 += "<credits id=\"" + + CreditsWidget->LoadImage( + std::string(reinterpret_cast<const char*>(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<const char*>(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 = "<!DOCTYPE html><html><body>" + html + "</body></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 0000000000000000000000000000000000000000..4c3e481ac09829810a82c7ccfa380d0e1625c421 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/CesiumRuntime/Private/CesiumCreditSystemBPLoader.cpp @@ -0,0 +1,11 @@ +// Copyright 2020-2021 CesiumGS, Inc. and Contributors + +#include "CesiumCreditSystemBPLoader.h" +#include "UObject/ConstructorHelpers.h" + +UCesiumCreditSystemBPLoader::UCesiumCreditSystemBPLoader() + : CesiumCreditSystemBP( + ConstructorHelpers::FObjectFinder<UClass>( + TEXT( + "Class'/CesiumForUnreal/CesiumCreditSystemBP.CesiumCreditSystemBP_C'")) + .Object) {} diff --git a/Plugins/CesiumForUnreal/Source/CesiumRuntime/Private/CesiumCreditSystemBPLoader.h b/Plugins/CesiumForUnreal/Source/CesiumRuntime/Private/CesiumCreditSystemBPLoader.h new file mode 100644 index 0000000000000000000000000000000000000000..846649479ac9849e579bd5c4bb62db9d1d0e6051 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/CesiumRuntime/Private/CesiumCreditSystemBPLoader.h @@ -0,0 +1,16 @@ +// Copyright 2020-2021 CesiumGS, Inc. and Contributors + +#pragma once + +#include "CesiumCreditSystemBPLoader.generated.h" + +UCLASS() +class UCesiumCreditSystemBPLoader : public UObject { + GENERATED_BODY() + +public: + UCesiumCreditSystemBPLoader(); + + UPROPERTY() + UClass* CesiumCreditSystemBP; +}; diff --git a/Plugins/CesiumForUnreal/Source/CesiumRuntime/Private/CesiumCustomVersion.cpp b/Plugins/CesiumForUnreal/Source/CesiumRuntime/Private/CesiumCustomVersion.cpp new file mode 100644 index 0000000000000000000000000000000000000000..a4cb51d8ab74d01c2439e75712c4def8b0c00549 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/CesiumRuntime/Private/CesiumCustomVersion.cpp @@ -0,0 +1,13 @@ +// Copyright 2020-2021 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 0000000000000000000000000000000000000000..7ee4cf55a07c3bb7a8687c1718f100c5993b8d23 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/CesiumRuntime/Private/CesiumDebugColorizeTilesRasterOverlay.cpp @@ -0,0 +1,14 @@ +// Copyright 2020-2021 CesiumGS, Inc. and Contributors + +#include "CesiumDebugColorizeTilesRasterOverlay.h" +#include "Cesium3DTilesSelection/DebugColorizeTilesRasterOverlay.h" +#include "Cesium3DTilesSelection/Tileset.h" + +std::unique_ptr<Cesium3DTilesSelection::RasterOverlay> +UCesiumDebugColorizeTilesRasterOverlay::CreateOverlay( + const Cesium3DTilesSelection::RasterOverlayOptions& options) { + return std::make_unique< + Cesium3DTilesSelection::DebugColorizeTilesRasterOverlay>( + TCHAR_TO_UTF8(*this->MaterialLayerKey), + options); +} diff --git a/Plugins/CesiumForUnreal/Source/CesiumRuntime/Private/CesiumEncodedMetadataComponent.cpp b/Plugins/CesiumForUnreal/Source/CesiumRuntime/Private/CesiumEncodedMetadataComponent.cpp new file mode 100644 index 0000000000000000000000000000000000000000..b7db7328daf281453e2a61c98752a45a409b7b1c --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/CesiumRuntime/Private/CesiumEncodedMetadataComponent.cpp @@ -0,0 +1,900 @@ +// Copyright 2020-2021 CesiumGS, Inc. and Contributors + +#include "CesiumEncodedMetadataComponent.h" +#include "Cesium3DTileset.h" +#include "CesiumEncodedMetadataUtility.h" +#include "CesiumFeatureTextureProperty.h" +#include "CesiumGltfComponent.h" +#include "CesiumGltfPrimitiveComponent.h" +#include "CesiumMetadataConversions.h" +#include "CesiumMetadataModel.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/MaterialExpressionCustom.h" +#include "Materials/MaterialExpressionFunctionInput.h" +#include "Materials/MaterialExpressionFunctionOutput.h" +#include "Materials/MaterialExpressionMaterialFunctionCall.h" +#include "Materials/MaterialExpressionScalarParameter.h" +#include "Materials/MaterialExpressionSetMaterialAttributes.h" +#include "Materials/MaterialExpressionTextureCoordinate.h" +#include "Materials/MaterialExpressionTextureObjectParameter.h" +#include "Materials/MaterialExpressionTextureProperty.h" +#include "Misc/PackageName.h" +#include "Modules/ModuleManager.h" +#include "Subsystems/AssetEditorSubsystem.h" +#include "UObject/Package.h" + +extern UNREALED_API class UEditorEngine* GEditor; +#endif + +using namespace CesiumEncodedMetadataUtility; + +void UCesiumEncodedMetadataComponent::AutoFill() { + const ACesium3DTileset* pOwner = this->GetOwner<ACesium3DTileset>(); + if (!pOwner) { + return; + } + + for (const UActorComponent* pComponent : pOwner->GetComponents()) { + const UCesiumGltfComponent* pGltf = Cast<UCesiumGltfComponent>(pComponent); + if (!pGltf) { + continue; + } + + const FCesiumMetadataModel& model = pGltf->Metadata; + const TMap<FString, FCesiumFeatureTable>& featureTables = + UCesiumMetadataModelBlueprintLibrary::GetFeatureTables(model); + const TMap<FString, FCesiumFeatureTexture>& featureTextures = + UCesiumMetadataModelBlueprintLibrary::GetFeatureTextures(model); + + for (const auto& featureTableIt : featureTables) { + const TMap<FString, FCesiumMetadataProperty>& properties = + UCesiumFeatureTableBlueprintLibrary::GetProperties( + featureTableIt.Value); + + FFeatureTableDescription* pFeatureTable = + this->FeatureTables.FindByPredicate( + [&featureTableName = featureTableIt.Key]( + const FFeatureTableDescription& existingFeatureTable) { + return existingFeatureTable.Name == featureTableName; + }); + + if (!pFeatureTable) { + pFeatureTable = &this->FeatureTables.Emplace_GetRef(); + pFeatureTable->Name = featureTableIt.Key; + } + + for (const auto& propertyIt : properties) { + if (pFeatureTable->Properties.FindByPredicate( + [&propertyName = propertyIt.Key]( + const FPropertyDescription& existingProperty) { + return existingProperty.Name == propertyName; + })) { + // We have already filled this property. + continue; + } + + ECesiumMetadataTrueType type = + UCesiumMetadataPropertyBlueprintLibrary::GetTrueType( + propertyIt.Value); + ECesiumMetadataTrueType componentType = + UCesiumMetadataPropertyBlueprintLibrary::GetTrueComponentType( + propertyIt.Value); + int64 componentCount; + + ECesiumMetadataPackedGpuType gpuType = + ECesiumMetadataPackedGpuType::None; + if (type == ECesiumMetadataTrueType::Array) { + gpuType = CesiumMetadataTrueTypeToDefaultPackedGpuType(componentType); + componentCount = + UCesiumMetadataPropertyBlueprintLibrary::GetComponentCount( + propertyIt.Value); + } else { + gpuType = CesiumMetadataTrueTypeToDefaultPackedGpuType(type); + componentCount = 1; + } + + if (gpuType == ECesiumMetadataPackedGpuType::None) { + continue; + } + + FPropertyDescription& property = + pFeatureTable->Properties.Emplace_GetRef(); + property.Name = propertyIt.Key; + + switch (componentCount) { + case 2: + property.Type = ECesiumPropertyType::Vec2; + break; + case 3: + property.Type = ECesiumPropertyType::Vec3; + break; + case 4: + property.Type = ECesiumPropertyType::Vec4; + break; + default: + property.Type = ECesiumPropertyType::Scalar; + }; + + if (gpuType == ECesiumMetadataPackedGpuType::Uint8) { + property.ComponentType = ECesiumPropertyComponentType::Uint8; + } else /*if (gpuType == float)*/ { + property.ComponentType = ECesiumPropertyComponentType::Float; + } + + property.Normalized = + UCesiumMetadataPropertyBlueprintLibrary::IsNormalized( + propertyIt.Value); + } + } + + for (const auto& featureTextureIt : featureTextures) { + FFeatureTextureDescription* pFeatureTexture = + this->FeatureTextures.FindByPredicate( + [&featureTextureName = featureTextureIt.Key]( + const FFeatureTextureDescription& existingFeatureTexture) { + return existingFeatureTexture.Name == featureTextureName; + }); + + if (!pFeatureTexture) { + pFeatureTexture = &this->FeatureTextures.Emplace_GetRef(); + pFeatureTexture->Name = featureTextureIt.Key; + } + + const TArray<FString>& propertyNames = + UCesiumFeatureTextureBlueprintLibrary::GetPropertyKeys( + featureTextureIt.Value); + + for (const FString& propertyName : propertyNames) { + if (pFeatureTexture->Properties.FindByPredicate( + [&propertyName](const FFeatureTexturePropertyDescription& + existingProperty) { + return propertyName == existingProperty.Name; + })) { + // We have already filled this property. + continue; + } + + FCesiumFeatureTextureProperty property = + UCesiumFeatureTextureBlueprintLibrary::FindProperty( + featureTextureIt.Value, + propertyName); + FFeatureTexturePropertyDescription& propertyDescription = + pFeatureTexture->Properties.Emplace_GetRef(); + propertyDescription.Name = propertyName; + propertyDescription.Normalized = + UCesiumFeatureTexturePropertyBlueprintLibrary::IsNormalized( + property); + + switch ( + UCesiumFeatureTexturePropertyBlueprintLibrary::GetComponentCount( + property)) { + case 2: + propertyDescription.Type = ECesiumPropertyType::Vec2; + break; + case 3: + propertyDescription.Type = ECesiumPropertyType::Vec3; + break; + case 4: + propertyDescription.Type = ECesiumPropertyType::Vec4; + break; + // case 1: + default: + propertyDescription.Type = ECesiumPropertyType::Scalar; + } + + propertyDescription.Swizzle = + UCesiumFeatureTexturePropertyBlueprintLibrary::GetSwizzle(property); + } + } + } + + for (const UActorComponent* pComponent : pOwner->GetComponents()) { + const UCesiumGltfPrimitiveComponent* pGltfPrimitive = + Cast<UCesiumGltfPrimitiveComponent>(pComponent); + if (!pGltfPrimitive) { + continue; + } + + const FCesiumMetadataPrimitive& primitive = pGltfPrimitive->Metadata; + const TArray<FCesiumFeatureIdAttribute>& attributes = + UCesiumMetadataPrimitiveBlueprintLibrary::GetFeatureIdAttributes( + primitive); + const TArray<FCesiumFeatureIdTexture>& textures = + UCesiumMetadataPrimitiveBlueprintLibrary::GetFeatureIdTextures( + primitive); + + for (const FCesiumFeatureIdAttribute& attribute : attributes) { + const FString& featureTableName = + UCesiumFeatureIdAttributeBlueprintLibrary::GetFeatureTableName( + attribute); + for (FFeatureTableDescription& featureTable : this->FeatureTables) { + if (featureTableName == featureTable.Name) { + if (featureTable.AccessType == + ECesiumFeatureTableAccessType::Unknown) { + featureTable.AccessType = ECesiumFeatureTableAccessType::Attribute; + } + + break; + } + } + } + + for (const FCesiumFeatureIdTexture& texture : textures) { + const FString& featureTableName = + UCesiumFeatureIdTextureBlueprintLibrary::GetFeatureTableName(texture); + for (FFeatureTableDescription& featureTable : this->FeatureTables) { + if (featureTableName == featureTable.Name) { + if (featureTable.AccessType == + ECesiumFeatureTableAccessType::Unknown) { + featureTable.AccessType = ECesiumFeatureTableAccessType::Texture; + switch (texture.getFeatureIdTextureView().getChannel()) { + case 1: + featureTable.Channel = "g"; + break; + case 2: + featureTable.Channel = "b"; + break; + case 3: + featureTable.Channel = "a"; + break; + // case 0: + default: + featureTable.Channel = "r"; + } + } else if ( + featureTable.AccessType == + ECesiumFeatureTableAccessType::Attribute) { + featureTable.AccessType = ECesiumFeatureTableAccessType::Mixed; + } + + break; + } + } + } + } +} + +#if WITH_EDITOR +template <typename ObjClass> +static FORCEINLINE ObjClass* LoadObjFromPath(const FName& Path) { + if (Path == NAME_None) + return nullptr; + + return Cast<ObjClass>( + StaticLoadObject(ObjClass::StaticClass(), nullptr, *Path.ToString())); +} + +static FORCEINLINE UMaterialFunction* LoadMaterialFunction(const FName& Path) { + if (Path == NAME_None) + return nullptr; + + return LoadObjFromPath<UMaterialFunction>(Path); +} + +// Seperate nodes into auto-generated and user-added. Collect the property +// result nodes. +static void ClassifyNodes( + UMaterialFunctionMaterialLayer* Layer, + TArray<UMaterialExpression*>& AutoGeneratedNodes, + TArray<UMaterialExpression*>& UserAddedNodes, + TArray<UMaterialExpressionCustom*>& ResultNodes) { + +#if ENGINE_MAJOR_VERSION == 5 && ENGINE_MINOR_VERSION == 0 + for (UMaterialExpression* Node : Layer->FunctionExpressions) { +#else + for (const TObjectPtr<UMaterialExpression>& Node : + Layer->GetExpressionCollection().Expressions) { +#endif + // Check if this node is marked as autogenerated. + if (Node->Desc.StartsWith( + "AUTOGENERATED DO NOT EDIT", + ESearchCase::Type::CaseSensitive)) { + AutoGeneratedNodes.Add(Node); + + // The only auto-generated custom nodes are the property result nodes. + UMaterialExpressionCustom* CustomNode = + Cast<UMaterialExpressionCustom>(Node); + if (CustomNode) { + ResultNodes.Add(CustomNode); + } + } else { + UserAddedNodes.Add(Node); + } + } +} + +static void ClearAutoGeneratedNodes( + UMaterialFunctionMaterialLayer* Layer, + TMap<FString, TArray<FExpressionInput*>>& ConnectionRemap) { + + TArray<UMaterialExpression*> AutoGeneratedNodes; + TArray<UMaterialExpression*> UserAddedNodes; + TArray<UMaterialExpressionCustom*> ResultNodes; + ClassifyNodes(Layer, AutoGeneratedNodes, UserAddedNodes, ResultNodes); + + // Determine which user-added connections to remap when regenerating the + // auto-generated nodes. + for (const UMaterialExpressionCustom* ResultNode : ResultNodes) { + int32 OutputIndex = 0; + for (const FExpressionOutput& PropertyOutput : ResultNode->Outputs) { + FString Key = + ResultNode->Description + PropertyOutput.OutputName.ToString(); + + // Look for user-made connections to this property. + TArray<FExpressionInput*> Connections; + for (UMaterialExpression* UserNode : UserAddedNodes) { + for (FExpressionInput* Input : UserNode->GetInputs()) { + if (Input->Expression == ResultNode && + Input->OutputIndex == OutputIndex) { + Connections.Add(Input); + Input->Expression = nullptr; + } + } + } + + ConnectionRemap.Emplace(MoveTemp(Key), MoveTemp(Connections)); + ++OutputIndex; + } + } + + // Remove auto-generated nodes. + for (UMaterialExpression* AutoGeneratedNode : AutoGeneratedNodes) { +#if ENGINE_MAJOR_VERSION == 5 && ENGINE_MINOR_VERSION == 0 + Layer->FunctionExpressions.Remove(AutoGeneratedNode); +#else + Layer->GetExpressionCollection().RemoveExpression(AutoGeneratedNode); +#endif + } +} + +static void RemapUserConnections( + UMaterialFunctionMaterialLayer* Layer, + TMap<FString, TArray<FExpressionInput*>>& ConnectionRemap) { + + TArray<UMaterialExpression*> AutoGeneratedNodes; + TArray<UMaterialExpression*> UserAddedNodes; + TArray<UMaterialExpressionCustom*> ResultNodes; + ClassifyNodes(Layer, AutoGeneratedNodes, UserAddedNodes, ResultNodes); + + for (UMaterialExpressionCustom* ResultNode : ResultNodes) { + int32 OutputIndex = 0; + for (const FExpressionOutput& PropertyOutput : ResultNode->Outputs) { + FString Key = + ResultNode->Description + PropertyOutput.OutputName.ToString(); + + TArray<FExpressionInput*>* pConnections = ConnectionRemap.Find(Key); + if (pConnections) { + for (FExpressionInput* pConnection : *pConnections) { + pConnection->Expression = ResultNode; + pConnection->OutputIndex = OutputIndex; + } + } + + ++OutputIndex; + } + } +} + +void UCesiumEncodedMetadataComponent::GenerateMaterial() { + ACesium3DTileset* pTileset = Cast<ACesium3DTileset>(this->GetOwner()); + + if (!pTileset) { + return; + } + + FString MaterialName = "ML_" + pTileset->GetFName().ToString() + "_Metadata"; + FString PackageBaseName = "/Game/"; + FString PackageName = PackageBaseName + MaterialName; + + UMaterialFunction* SelectTexCoordsFunction = LoadMaterialFunction( + "/CesiumForUnreal/Materials/MaterialFunctions/CesiumSelectTexCoords.CesiumSelectTexCoords"); + if (!SelectTexCoordsFunction) { + return; + } + + bool Overwriting = false; + if (this->TargetMaterialLayer) { + // Overwriting an existing material layer. + Overwriting = true; + GEditor->GetEditorSubsystem<UAssetEditorSubsystem>() + ->CloseAllEditorsForAsset(this->TargetMaterialLayer); + } else { + UPackage* Package = CreatePackage(*PackageName); + + // Create an unreal material asset + UMaterialFunctionMaterialLayerFactory* MaterialFactory = + NewObject<UMaterialFunctionMaterialLayerFactory>(); + this->TargetMaterialLayer = + (UMaterialFunctionMaterialLayer*)MaterialFactory->FactoryCreateNew( + UMaterialFunctionMaterialLayer::StaticClass(), + Package, + *MaterialName, + RF_Standalone | RF_Public | RF_Transactional, + NULL, + GWarn); + FAssetRegistryModule::AssetCreated(this->TargetMaterialLayer); + Package->FullyLoad(); + Package->SetDirtyFlag(true); + } + + this->TargetMaterialLayer->PreEditChange(NULL); + + TMap<FString, TArray<FExpressionInput*>> ConnectionRemap; + ClearAutoGeneratedNodes(this->TargetMaterialLayer, ConnectionRemap); + + TArray<UMaterialExpression*> AutoGeneratedNodes; + TArray<UMaterialExpression*> OneTimeGeneratedNodes; + + const int32 IncrX = 400; + const int32 IncrY = 200; + int32 NodeX = 0; + int32 NodeY = 0; + + for (const FFeatureTableDescription& featureTable : this->FeatureTables) { + if (featureTable.AccessType == ECesiumFeatureTableAccessType::Unknown || + featureTable.AccessType == ECesiumFeatureTableAccessType::Mixed) { + continue; + } + + int32 SectionLeft = NodeX; + int32 SectionTop = NodeY; + + UMaterialExpressionCustom* FeatureTableLookup = + NewObject<UMaterialExpressionCustom>(this->TargetMaterialLayer); + FeatureTableLookup->Inputs.Reserve(featureTable.Properties.Num() + 2); + FeatureTableLookup->Outputs.Reset(featureTable.Properties.Num() + 1); + FeatureTableLookup->Outputs.Add(FExpressionOutput(TEXT("return"))); + FeatureTableLookup->bShowOutputNameOnPin = true; + FeatureTableLookup->Description = + "Resolve properties from " + featureTable.Name; + AutoGeneratedNodes.Add(FeatureTableLookup); + + if (featureTable.AccessType == ECesiumFeatureTableAccessType::Texture) { + UMaterialExpressionTextureObjectParameter* FeatureIdTexture = + NewObject<UMaterialExpressionTextureObjectParameter>( + this->TargetMaterialLayer); + FeatureIdTexture->ParameterName = + FName("FIT_" + featureTable.Name + "_TX"); + FeatureIdTexture->MaterialExpressionEditorX = NodeX; + FeatureIdTexture->MaterialExpressionEditorY = NodeY; + AutoGeneratedNodes.Add(FeatureIdTexture); + + FCustomInput& FeatureIdTextureInput = FeatureTableLookup->Inputs[0]; + FeatureIdTextureInput.InputName = "FeatureIdTexture"; + FeatureIdTextureInput.Input.Expression = FeatureIdTexture; + + NodeY += IncrY; + + UMaterialExpressionScalarParameter* TexCoordsIndex = + NewObject<UMaterialExpressionScalarParameter>( + this->TargetMaterialLayer); + TexCoordsIndex->ParameterName = FName("FIT_" + featureTable.Name + "_UV"); + TexCoordsIndex->DefaultValue = 0.0f; + TexCoordsIndex->MaterialExpressionEditorX = NodeX; + TexCoordsIndex->MaterialExpressionEditorY = NodeY; + AutoGeneratedNodes.Add(TexCoordsIndex); + + NodeX += IncrX; + + UMaterialExpressionMaterialFunctionCall* SelectTexCoords = + NewObject<UMaterialExpressionMaterialFunctionCall>( + this->TargetMaterialLayer); + SelectTexCoords->MaterialFunction = SelectTexCoordsFunction; + SelectTexCoords->MaterialExpressionEditorX = NodeX; + SelectTexCoords->MaterialExpressionEditorY = NodeY; + + SelectTexCoordsFunction->GetInputsAndOutputs( + SelectTexCoords->FunctionInputs, + SelectTexCoords->FunctionOutputs); + SelectTexCoords->FunctionInputs[0].Input.Expression = TexCoordsIndex; + AutoGeneratedNodes.Add(SelectTexCoords); + + FCustomInput& TexCoordsInput = + FeatureTableLookup->Inputs.Emplace_GetRef(); + TexCoordsInput.InputName = FName("TexCoords"); + TexCoordsInput.Input.Expression = SelectTexCoords; + + NodeX += IncrX; + + // TODO: Should the channel mask be determined dynamically instead of at + // editor-time like it is now? + FeatureTableLookup->Code = + "uint _czm_propertyIndex = asuint(FeatureIdTexture.Sample(FeatureIdTextureSampler, TexCoords)." + + featureTable.Channel + ");\n"; + + FeatureTableLookup->MaterialExpressionEditorX = NodeX; + FeatureTableLookup->MaterialExpressionEditorY = NodeY; + } else { + // Create material for vertex attributes + + UMaterialExpressionScalarParameter* AttributeIndex = + NewObject<UMaterialExpressionScalarParameter>( + this->TargetMaterialLayer); + AttributeIndex->ParameterName = FName("FA_" + featureTable.Name); + AttributeIndex->DefaultValue = 0.0f; + AttributeIndex->MaterialExpressionEditorX = NodeX; + AttributeIndex->MaterialExpressionEditorY = NodeY; + AutoGeneratedNodes.Add(AttributeIndex); + + NodeX += IncrX; + + UMaterialExpressionMaterialFunctionCall* SelectTexCoords = + NewObject<UMaterialExpressionMaterialFunctionCall>( + this->TargetMaterialLayer); + SelectTexCoords->MaterialFunction = SelectTexCoordsFunction; + SelectTexCoords->MaterialExpressionEditorX = NodeX; + SelectTexCoords->MaterialExpressionEditorY = NodeY; + + SelectTexCoordsFunction->GetInputsAndOutputs( + SelectTexCoords->FunctionInputs, + SelectTexCoords->FunctionOutputs); + SelectTexCoords->FunctionInputs[0].Input.Expression = AttributeIndex; + AutoGeneratedNodes.Add(SelectTexCoords); + + FCustomInput& TexCoordsInput = FeatureTableLookup->Inputs[0]; + TexCoordsInput.InputName = FName("PropertyIndexUV"); + TexCoordsInput.Input.Expression = SelectTexCoords; + + NodeX += IncrX; + + FeatureTableLookup->Code = + "uint _czm_propertyIndex = round(PropertyIndexUV.r);\n"; + + FeatureTableLookup->MaterialExpressionEditorX = NodeX; + FeatureTableLookup->MaterialExpressionEditorY = NodeY; + } + + // Get the pixel dimensions of the first property, all the properties will + // have the same dimensions since it is based on the feature count. + if (featureTable.Properties.Num()) { + const FPropertyDescription& property = featureTable.Properties[0]; + FString propertyArrayName = createHlslSafeName(property.Name) + "_array"; + + FeatureTableLookup->Code += "uint _czm_width;\nuint _czm_height;\n"; + FeatureTableLookup->Code += + propertyArrayName + ".GetDimensions(_czm_width, _czm_height);\n"; + FeatureTableLookup->Code += + "uint _czm_pixelX = _czm_propertyIndex % _czm_width;\n"; + FeatureTableLookup->Code += + "uint _czm_pixelY = _czm_propertyIndex / _czm_width;\n"; + } + + NodeX = SectionLeft; + NodeY += IncrY; + + FeatureTableLookup->AdditionalOutputs.Reserve( + featureTable.Properties.Num()); + for (const FPropertyDescription& property : featureTable.Properties) { + UMaterialExpressionTextureObjectParameter* PropertyArray = + NewObject<UMaterialExpressionTextureObjectParameter>( + this->TargetMaterialLayer); + PropertyArray->ParameterName = + FName("FTB_" + featureTable.Name + "_" + property.Name); + PropertyArray->MaterialExpressionEditorX = NodeX; + PropertyArray->MaterialExpressionEditorY = NodeY; + AutoGeneratedNodes.Add(PropertyArray); + + FString propertyName = createHlslSafeName(property.Name); + + FCustomInput& PropertyInput = FeatureTableLookup->Inputs.Emplace_GetRef(); + FString propertyArrayName = propertyName + "_array"; + PropertyInput.InputName = FName(propertyArrayName); + PropertyInput.Input.Expression = PropertyArray; + + FCustomOutput& PropertyOutput = + FeatureTableLookup->AdditionalOutputs.Emplace_GetRef(); + PropertyOutput.OutputName = FName(propertyName); + FeatureTableLookup->Outputs.Add( + FExpressionOutput(PropertyOutput.OutputName)); + + FString swizzle = ""; + switch (property.Type) { + case ECesiumPropertyType::Vec2: + PropertyOutput.OutputType = ECustomMaterialOutputType::CMOT_Float2; + swizzle = "rg"; + break; + case ECesiumPropertyType::Vec3: + PropertyOutput.OutputType = ECustomMaterialOutputType::CMOT_Float3; + swizzle = "rgb"; + break; + case ECesiumPropertyType::Vec4: + PropertyOutput.OutputType = ECustomMaterialOutputType::CMOT_Float4; + swizzle = "rgba"; + break; + // case ECesiumPropertyType::Scalar: + default: + PropertyOutput.OutputType = ECustomMaterialOutputType::CMOT_Float1; + swizzle = "r"; + }; + + FString componentTypeInterpretation = + property.ComponentType == ECesiumPropertyComponentType::Float + ? "asfloat" + : "asuint"; + + FeatureTableLookup->Code += + propertyName + " = " + componentTypeInterpretation + "(" + + propertyArrayName + ".Load(int3(_czm_pixelX, _czm_pixelY, 0))." + + swizzle + ");\n"; + + NodeY += IncrY; + } + + FeatureTableLookup->OutputType = ECustomMaterialOutputType::CMOT_Float1; + + FeatureTableLookup->Code += + "float _czm_propertyIndexF = _czm_propertyIndex;\n"; + FeatureTableLookup->Code += "return _czm_propertyIndexF;"; + + NodeX = SectionLeft; + } + + for (const FFeatureTextureDescription& featureTexture : + this->FeatureTextures) { + int32 SectionLeft = NodeX; + int32 SectionTop = NodeY; + + UMaterialExpressionCustom* FeatureTextureLookup = + NewObject<UMaterialExpressionCustom>(this->TargetMaterialLayer); + FeatureTextureLookup->Inputs.Reset(2 * featureTexture.Properties.Num()); + FeatureTextureLookup->Outputs.Reset(featureTexture.Properties.Num() + 1); + FeatureTextureLookup->Outputs.Add(FExpressionOutput(TEXT("return"))); + FeatureTextureLookup->bShowOutputNameOnPin = true; + FeatureTextureLookup->Code = ""; + FeatureTextureLookup->Description = + "Resolve properties from " + featureTexture.Name; + FeatureTextureLookup->MaterialExpressionEditorX = NodeX + 2 * IncrX; + FeatureTextureLookup->MaterialExpressionEditorY = NodeY; + AutoGeneratedNodes.Add(FeatureTextureLookup); + + for (const FFeatureTexturePropertyDescription& property : + featureTexture.Properties) { + UMaterialExpressionTextureObjectParameter* PropertyTexture = + NewObject<UMaterialExpressionTextureObjectParameter>( + this->TargetMaterialLayer); + PropertyTexture->ParameterName = + FName("FTX_" + featureTexture.Name + "_" + property.Name + "_TX"); + PropertyTexture->MaterialExpressionEditorX = NodeX; + PropertyTexture->MaterialExpressionEditorY = NodeY; + AutoGeneratedNodes.Add(PropertyTexture); + + FString propertyName = createHlslSafeName(property.Name); + + FCustomInput& PropertyTextureInput = + FeatureTextureLookup->Inputs.Emplace_GetRef(); + FString propertyTextureName = propertyName + "_TX"; + PropertyTextureInput.InputName = FName(propertyTextureName); + PropertyTextureInput.Input.Expression = PropertyTexture; + + NodeY += IncrY; + + UMaterialExpressionScalarParameter* TexCoordsIndex = + NewObject<UMaterialExpressionScalarParameter>( + this->TargetMaterialLayer); + TexCoordsIndex->ParameterName = + FName("FTX_" + featureTexture.Name + "_" + property.Name + "_UV"); + TexCoordsIndex->DefaultValue = 0.0f; + TexCoordsIndex->MaterialExpressionEditorX = NodeX; + TexCoordsIndex->MaterialExpressionEditorY = NodeY; + AutoGeneratedNodes.Add(TexCoordsIndex); + + NodeX += IncrX; + + UMaterialExpressionMaterialFunctionCall* SelectTexCoords = + NewObject<UMaterialExpressionMaterialFunctionCall>( + this->TargetMaterialLayer); + SelectTexCoords->MaterialFunction = SelectTexCoordsFunction; + SelectTexCoords->MaterialExpressionEditorX = NodeX; + SelectTexCoords->MaterialExpressionEditorY = NodeY; + + SelectTexCoordsFunction->GetInputsAndOutputs( + SelectTexCoords->FunctionInputs, + SelectTexCoords->FunctionOutputs); + SelectTexCoords->FunctionInputs[0].Input.Expression = TexCoordsIndex; + AutoGeneratedNodes.Add(SelectTexCoords); + + FCustomInput& TexCoordsInput = + FeatureTextureLookup->Inputs.Emplace_GetRef(); + FString propertyUvName = propertyName + "_UV"; + TexCoordsInput.InputName = FName(propertyUvName); + TexCoordsInput.Input.Expression = SelectTexCoords; + + FCustomOutput& PropertyOutput = + FeatureTextureLookup->AdditionalOutputs.Emplace_GetRef(); + PropertyOutput.OutputName = FName(propertyName); + FeatureTextureLookup->Outputs.Add( + FExpressionOutput(PropertyOutput.OutputName)); + + // Either the property is normalized or it is coerced into float. Either + // way, the outputs will be float type. + switch (property.Type) { + case ECesiumPropertyType::Vec2: + PropertyOutput.OutputType = ECustomMaterialOutputType::CMOT_Float2; + break; + case ECesiumPropertyType::Vec3: + PropertyOutput.OutputType = ECustomMaterialOutputType::CMOT_Float3; + break; + case ECesiumPropertyType::Vec4: + PropertyOutput.OutputType = ECustomMaterialOutputType::CMOT_Float4; + break; + // case ECesiumPropertyType::Scalar: + default: + PropertyOutput.OutputType = ECustomMaterialOutputType::CMOT_Float1; + }; + + // TODO: should dynamic channel offsets be used instead of swizzle string + // determined at editor time? E.g. can swizzles be different for the same + // property texture on different tiles? + FeatureTextureLookup->Code += + propertyName + " = " + + (property.Normalized ? "asfloat(" : "asuint(") + propertyTextureName + + ".Sample(" + propertyTextureName + "Sampler, " + propertyUvName + + ")." + property.Swizzle + ");\n"; + + NodeY += IncrY; + } + + FeatureTextureLookup->OutputType = ECustomMaterialOutputType::CMOT_Float1; + FeatureTextureLookup->Code += "return 0.0f;"; + + NodeX = SectionLeft; + } + + NodeY = -IncrY; + + UMaterialExpressionFunctionInput* InputMaterial = nullptr; +#if ENGINE_MAJOR_VERSION == 5 && ENGINE_MINOR_VERSION == 0 + for (UMaterialExpression* ExistingNode : + this->TargetMaterialLayer->FunctionExpressions) { +#else + for (const TObjectPtr<UMaterialExpression>& ExistingNode : + this->TargetMaterialLayer->GetExpressionCollection().Expressions) { +#endif + UMaterialExpressionFunctionInput* ExistingInputMaterial = + Cast<UMaterialExpressionFunctionInput>(ExistingNode); + if (ExistingInputMaterial) { + InputMaterial = ExistingInputMaterial; + break; + } + } + + if (!InputMaterial) { + InputMaterial = + NewObject<UMaterialExpressionFunctionInput>(this->TargetMaterialLayer); + InputMaterial->InputType = + EFunctionInputType::FunctionInput_MaterialAttributes; + InputMaterial->bUsePreviewValueAsDefault = true; + InputMaterial->MaterialExpressionEditorX = NodeX; + InputMaterial->MaterialExpressionEditorY = NodeY; + OneTimeGeneratedNodes.Add(InputMaterial); + } + + NodeX += 4 * IncrX; + + UMaterialExpressionSetMaterialAttributes* SetMaterialAttributes = nullptr; +#if ENGINE_MAJOR_VERSION == 5 && ENGINE_MINOR_VERSION == 0 + for (UMaterialExpression* ExistingNode : + this->TargetMaterialLayer->FunctionExpressions) { +#else + for (const TObjectPtr<UMaterialExpression>& ExistingNode : + this->TargetMaterialLayer->GetExpressionCollection().Expressions) { +#endif + UMaterialExpressionSetMaterialAttributes* ExistingSetAttributes = + Cast<UMaterialExpressionSetMaterialAttributes>(ExistingNode); + if (ExistingSetAttributes) { + SetMaterialAttributes = ExistingSetAttributes; + break; + } + } + + if (!SetMaterialAttributes) { + SetMaterialAttributes = NewObject<UMaterialExpressionSetMaterialAttributes>( + this->TargetMaterialLayer); + OneTimeGeneratedNodes.Add(SetMaterialAttributes); + } + + SetMaterialAttributes->Inputs[0].Expression = InputMaterial; + SetMaterialAttributes->MaterialExpressionEditorX = NodeX; + SetMaterialAttributes->MaterialExpressionEditorY = NodeY; + + NodeX += IncrX; + + UMaterialExpressionFunctionOutput* OutputMaterial = nullptr; +#if ENGINE_MAJOR_VERSION == 5 && ENGINE_MINOR_VERSION == 0 + for (UMaterialExpression* ExistingNode : + this->TargetMaterialLayer->FunctionExpressions) { +#else + for (const TObjectPtr<UMaterialExpression>& ExistingNode : + this->TargetMaterialLayer->GetExpressionCollection().Expressions) { +#endif + UMaterialExpressionFunctionOutput* ExistingOutputMaterial = + Cast<UMaterialExpressionFunctionOutput>(ExistingNode); + if (ExistingOutputMaterial) { + OutputMaterial = ExistingOutputMaterial; + break; + } + } + + if (!OutputMaterial) { + OutputMaterial = + NewObject<UMaterialExpressionFunctionOutput>(this->TargetMaterialLayer); + OneTimeGeneratedNodes.Add(OutputMaterial); + } + + OutputMaterial->MaterialExpressionEditorX = NodeX; + OutputMaterial->MaterialExpressionEditorY = NodeY; + OutputMaterial->A = FMaterialAttributesInput(); + OutputMaterial->A.Expression = SetMaterialAttributes; + + for (UMaterialExpression* AutoGeneratedNode : AutoGeneratedNodes) { +#if ENGINE_MAJOR_VERSION == 5 && ENGINE_MINOR_VERSION == 0 + this->TargetMaterialLayer->FunctionExpressions.Add(AutoGeneratedNode); +#else + this->TargetMaterialLayer->GetExpressionCollection().AddExpression( + AutoGeneratedNode); +#endif + // Mark as auto-generated. If the material is regenerated, we will look for + // this exact description to determine whether it was autogenerated. + // Completely open to suggestions of how else to mark custom information on + // these assets :) + AutoGeneratedNode->Desc = "AUTOGENERATED DO NOT EDIT"; + } + + for (UMaterialExpression* OneTimeGeneratedNode : OneTimeGeneratedNodes) { +#if ENGINE_MAJOR_VERSION == 5 && ENGINE_MINOR_VERSION == 0 + this->TargetMaterialLayer->FunctionExpressions.Add(OneTimeGeneratedNode); +#else + this->TargetMaterialLayer->GetExpressionCollection().AddExpression( + OneTimeGeneratedNode); +#endif + } + + RemapUserConnections(this->TargetMaterialLayer, ConnectionRemap); + + // 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<FContentBrowserModule>( + "ContentBrowser"); + if (pContentBrowserModule) { + TArray<UObject*> AssetsToHighlight; + AssetsToHighlight.Add(this->TargetMaterialLayer); + pContentBrowserModule->Get().SyncBrowserToAssets(AssetsToHighlight); + } + } + + // Open updated material in editor. + if (GEditor) { + UAssetEditorSubsystem* pAssetEditor = + GEditor->GetEditorSubsystem<UAssetEditorSubsystem>(); + if (pAssetEditor) { + pAssetEditor->OpenEditorForAsset(this->TargetMaterialLayer); + IMaterialEditor* pMaterialEditor = static_cast<IMaterialEditor*>( + pAssetEditor->FindEditorForAsset(this->TargetMaterialLayer, true)); + if (pMaterialEditor) { + pMaterialEditor->UpdateMaterialAfterGraphChange(); + } + } + } +} + +#endif // WITH_EDITOR diff --git a/Plugins/CesiumForUnreal/Source/CesiumRuntime/Private/CesiumEncodedMetadataUtility.cpp b/Plugins/CesiumForUnreal/Source/CesiumRuntime/Private/CesiumEncodedMetadataUtility.cpp new file mode 100644 index 0000000000000000000000000000000000000000..739e1ee8456899528662e904b8c4fc7344e19eb1 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/CesiumRuntime/Private/CesiumEncodedMetadataUtility.cpp @@ -0,0 +1,790 @@ +// Copyright 2020-2021 CesiumGS, Inc. and Contributors + +#include "CesiumEncodedMetadataUtility.h" +#include "CesiumEncodedMetadataComponent.h" +#include "CesiumFeatureIdAttribute.h" +#include "CesiumFeatureIdTexture.h" +#include "CesiumFeatureTable.h" +#include "CesiumFeatureTexture.h" +#include "CesiumLifetime.h" +#include "CesiumMetadataArray.h" +#include "CesiumMetadataConversions.h" +#include "CesiumMetadataModel.h" +#include "CesiumMetadataPrimitive.h" +#include "CesiumMetadataProperty.h" +#include "CesiumRuntime.h" +#include "Containers/Map.h" +#include "PixelFormat.h" +#include <CesiumGltf/FeatureIDTextureView.h> +#include <CesiumGltf/FeatureTexturePropertyView.h> +#include <CesiumGltf/FeatureTextureView.h> +#include <CesiumUtility/Tracing.h> +#include <glm/gtx/integer.hpp> +#include <unordered_map> + +using namespace CesiumTextureUtility; + +namespace CesiumEncodedMetadataUtility { + +namespace { + +struct EncodedPixelFormat { + EPixelFormat format; + size_t pixelSize; +}; + +// TODO: consider picking better pixel formats when they are available for the +// current platform. +EncodedPixelFormat getPixelFormat( + ECesiumMetadataPackedGpuType type, + int64 componentCount, + bool isNormalized) { + + switch (type) { + case ECesiumMetadataPackedGpuType::Uint8: + switch (componentCount) { + case 1: + return {isNormalized ? EPixelFormat::PF_R8 : EPixelFormat::PF_R8_UINT, 1}; + case 2: + case 3: + case 4: + return { + isNormalized ? EPixelFormat::PF_R8G8B8A8 + : EPixelFormat::PF_R8G8B8A8_UINT, + 4}; + default: + return {EPixelFormat::PF_Unknown, 0}; + } + case ECesiumMetadataPackedGpuType::Float: + switch (componentCount) { + case 1: + return {EPixelFormat::PF_R32_FLOAT, 4}; + case 2: + case 3: + case 4: + // Note this is ABGR + return {EPixelFormat::PF_A32B32G32R32F, 16}; + } + default: + return {EPixelFormat::PF_Unknown, 0}; + } +} +} // namespace + +EncodedMetadataFeatureTable encodeMetadataFeatureTableAnyThreadPart( + const FFeatureTableDescription& featureTableDescription, + const FCesiumFeatureTable& featureTable) { + + TRACE_CPUPROFILER_EVENT_SCOPE(Cesium::EncodeFeatureTable) + + EncodedMetadataFeatureTable encodedFeatureTable; + + int64 featureCount = + UCesiumFeatureTableBlueprintLibrary::GetNumberOfFeatures(featureTable); + + const TMap<FString, FCesiumMetadataProperty>& properties = + UCesiumFeatureTableBlueprintLibrary::GetProperties(featureTable); + + encodedFeatureTable.encodedProperties.Reserve(properties.Num()); + for (const auto& pair : properties) { + const FCesiumMetadataProperty& property = pair.Value; + + const FPropertyDescription* pExpectedProperty = + featureTableDescription.Properties.FindByPredicate( + [&key = pair.Key](const FPropertyDescription& expectedProperty) { + return key == expectedProperty.Name; + }); + + if (!pExpectedProperty) { + continue; + } + + ECesiumMetadataTrueType trueType = + UCesiumMetadataPropertyBlueprintLibrary::GetTrueType(property); + bool isArray = trueType == ECesiumMetadataTrueType::Array; + bool isNormalized = + UCesiumMetadataPropertyBlueprintLibrary::IsNormalized(property); + + int64 componentCount; + if (isArray) { + trueType = UCesiumMetadataPropertyBlueprintLibrary::GetTrueComponentType( + property); + componentCount = + UCesiumMetadataPropertyBlueprintLibrary::GetComponentCount(property); + } else { + componentCount = 1; + } + + int32 expectedComponentCount = 1; + switch (pExpectedProperty->Type) { + // case ECesiumPropertyType::Scalar: + // expectedComponentCount = 1; + // break; + case ECesiumPropertyType::Vec2: + expectedComponentCount = 2; + break; + case ECesiumPropertyType::Vec3: + expectedComponentCount = 3; + break; + case ECesiumPropertyType::Vec4: + 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 gpuType = ECesiumMetadataPackedGpuType::None; + if (pExpectedProperty->ComponentType == + ECesiumPropertyComponentType::Uint8) { + gpuType = ECesiumMetadataPackedGpuType::Uint8; + } else /*if (expected type is float)*/ { + gpuType = ECesiumMetadataPackedGpuType::Float; + } + + 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 != ECesiumMetadataTrueType::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); + encodedProperty.pTexture = MakeUnique<LoadedTextureResult>(); + // TODO: upgrade to new texture creation path. + encodedProperty.pTexture->textureSource = LegacyTextureSource{}; + encodedProperty.pTexture->pTextureData = createTexturePlatformData( + ceilSqrtFeatureCount, + ceilSqrtFeatureCount, + encodedFormat.format); + + encodedProperty.pTexture->addressX = TextureAddress::TA_Clamp; + encodedProperty.pTexture->addressY = TextureAddress::TA_Clamp; + encodedProperty.pTexture->filter = TextureFilter::TF_Nearest; + + if (!encodedProperty.pTexture->pTextureData) { + UE_LOG( + LogCesium, + Error, + TEXT( + "Error encoding a feature table property. Most likely could not allocate enough texture memory.")); + continue; + } + + FTexture2DMipMap* pMip = new FTexture2DMipMap(); + encodedProperty.pTexture->pTextureData->Mips.Add(pMip); + pMip->SizeX = ceilSqrtFeatureCount; + pMip->SizeY = ceilSqrtFeatureCount; + pMip->BulkData.Lock(LOCK_READ_WRITE); + + void* pTextureData = pMip->BulkData.Realloc( + ceilSqrtFeatureCount * ceilSqrtFeatureCount * encodedFormat.pixelSize); + + if (isArray) { + switch (gpuType) { + case ECesiumMetadataPackedGpuType::Uint8: { + uint8* pWritePos = reinterpret_cast<uint8*>(pTextureData); + for (int64 i = 0; i < featureCount; ++i) { + FCesiumMetadataArray arrayProperty = + UCesiumMetadataPropertyBlueprintLibrary::GetArray(property, i); + for (int64 j = 0; j < componentCount; ++j) { + *(pWritePos + j) = + UCesiumMetadataArrayBlueprintLibrary::GetByte(arrayProperty, j); + } + pWritePos += encodedFormat.pixelSize; + } + } break; + case ECesiumMetadataPackedGpuType::Float: { + uint8* pWritePos = reinterpret_cast<uint8*>(pTextureData); + for (int64 i = 0; i < featureCount; ++i) { + FCesiumMetadataArray arrayProperty = + UCesiumMetadataPropertyBlueprintLibrary::GetArray(property, i); + // Floats are encoded backwards (e.g., ABGR) + float* pWritePosF = + reinterpret_cast<float*>(pWritePos + encodedFormat.pixelSize) - 1; + for (int64 j = 0; j < componentCount; ++j) { + *pWritePosF = UCesiumMetadataArrayBlueprintLibrary::GetFloat( + arrayProperty, + j); + --pWritePosF; + } + pWritePos += encodedFormat.pixelSize; + } + } break; + } + } else { + switch (gpuType) { + case ECesiumMetadataPackedGpuType::Uint8: { + uint8* pWritePos = reinterpret_cast<uint8*>(pTextureData); + for (int64 i = 0; i < featureCount; ++i) { + *pWritePos = + UCesiumMetadataPropertyBlueprintLibrary::GetByte(property, i); + ++pWritePos; + } + } break; + case ECesiumMetadataPackedGpuType::Float: { + float* pWritePosF = reinterpret_cast<float*>(pTextureData); + for (int64 i = 0; i < featureCount; ++i) { + *pWritePosF = + UCesiumMetadataPropertyBlueprintLibrary::GetFloat(property, i); + ++pWritePosF; + } + } break; + } + } + + pMip->BulkData.Unlock(); + } + + return encodedFeatureTable; +} + +EncodedFeatureTexture encodeFeatureTextureAnyThreadPart( + TMap<const CesiumGltf::ImageCesium*, TWeakPtr<LoadedTextureResult>>& + featureTexturePropertyMap, + const FFeatureTextureDescription& featureTextureDescription, + const FString& featureTextureName, + const FCesiumFeatureTexture& featureTexture) { + + TRACE_CPUPROFILER_EVENT_SCOPE(Cesium::EncodeFeatureTexture) + + EncodedFeatureTexture encodedFeatureTexture; + + const CesiumGltf::FeatureTextureView& featureTextureView = + featureTexture.getFeatureTextureView(); + const std::unordered_map<std::string, CesiumGltf::FeatureTexturePropertyView>& + properties = featureTextureView.getProperties(); + + encodedFeatureTexture.properties.Reserve(properties.size()); + + for (const auto& propertyIt : properties) { + const FFeatureTexturePropertyDescription* pPropertyDescription = + featureTextureDescription.Properties.FindByPredicate( + [propertyName = UTF8_TO_TCHAR(propertyIt.first.c_str())]( + const FFeatureTexturePropertyDescription& expectedProperty) { + return propertyName == expectedProperty.Name; + }); + + if (!pPropertyDescription) { + continue; + } + + const CesiumGltf::FeatureTexturePropertyView& featureTexturePropertyView = + propertyIt.second; + + const CesiumGltf::ImageCesium* pImage = + featureTexturePropertyView.getImage(); + + if (!pImage) { + UE_LOG( + LogCesium, + Warning, + TEXT("This feature texture property does not have a valid image.")); + continue; + } + + int32 expectedComponentCount = 1; + switch (pPropertyDescription->Type) { + // case ECesiumPropertyType::Scalar: + // expectedComponentCount = 1; + // break; + case ECesiumPropertyType::Vec2: + expectedComponentCount = 2; + break; + case ECesiumPropertyType::Vec3: + expectedComponentCount = 3; + break; + case ECesiumPropertyType::Vec4: + expectedComponentCount = 4; + }; + + if (expectedComponentCount != propertyIt.second.getComponentCount() || + pPropertyDescription->Normalized != propertyIt.second.isNormalized() || + pPropertyDescription->Swizzle != + UTF8_TO_TCHAR(propertyIt.second.getSwizzle().c_str())) { + UE_LOG( + LogCesium, + Warning, + TEXT( + "This feature texture property does not have the expected component count, normalization, or swizzle string.")); + continue; + } + + TRACE_CPUPROFILER_EVENT_SCOPE(Cesium::EncodeFeatureTextureProperty) + + EncodedFeatureTextureProperty& encodedFeatureTextureProperty = + encodedFeatureTexture.properties.Emplace_GetRef(); + + encodedFeatureTextureProperty.baseName = + "FTX_" + featureTextureName + "_" + pPropertyDescription->Name + "_"; + encodedFeatureTextureProperty.textureCoordinateAttributeId = + featureTexturePropertyView.getTextureCoordinateAttributeId(); + + const CesiumGltf::FeatureTexturePropertyChannelOffsets& channelOffsets = + featureTexturePropertyView.getChannelOffsets(); + encodedFeatureTextureProperty.channelOffsets[0] = channelOffsets.r; + encodedFeatureTextureProperty.channelOffsets[1] = channelOffsets.g; + encodedFeatureTextureProperty.channelOffsets[2] = channelOffsets.b; + encodedFeatureTextureProperty.channelOffsets[3] = channelOffsets.a; + + TWeakPtr<LoadedTextureResult>* pMappedUnrealImageIt = + featureTexturePropertyMap.Find(pImage); + if (pMappedUnrealImageIt) { + encodedFeatureTextureProperty.pTexture = pMappedUnrealImageIt->Pin(); + } else { + encodedFeatureTextureProperty.pTexture = + MakeShared<LoadedTextureResult>(); + // TODO: upgrade to new texture creation path. + encodedFeatureTextureProperty.pTexture->textureSource = + LegacyTextureSource{}; + featureTexturePropertyMap.Emplace( + pImage, + encodedFeatureTextureProperty.pTexture); + encodedFeatureTextureProperty.pTexture->pTextureData = + createTexturePlatformData( + pImage->width, + pImage->height, + // TODO: currently the unnormalized pixels are always in + // unsigned R8G8B8A8 form, but this does not necessarily need + // to be the case in the future. + featureTexturePropertyView.isNormalized() + ? EPixelFormat::PF_R8G8B8A8 + : EPixelFormat::PF_R8G8B8A8_UINT); + + encodedFeatureTextureProperty.pTexture->addressX = + TextureAddress::TA_Clamp; + encodedFeatureTextureProperty.pTexture->addressY = + TextureAddress::TA_Clamp; + encodedFeatureTextureProperty.pTexture->filter = + TextureFilter::TF_Nearest; + + if (!encodedFeatureTextureProperty.pTexture->pTextureData) { + UE_LOG( + LogCesium, + Error, + TEXT( + "Error encoding a feature table property. Most likely could not allocate enough texture memory.")); + continue; + } + + FTexture2DMipMap* pMip = new FTexture2DMipMap(); + encodedFeatureTextureProperty.pTexture->pTextureData->Mips.Add(pMip); + pMip->SizeX = pImage->width; + pMip->SizeY = pImage->height; + pMip->BulkData.Lock(LOCK_READ_WRITE); + + void* pTextureData = pMip->BulkData.Realloc(pImage->pixelData.size()); + + FMemory::Memcpy( + pTextureData, + pImage->pixelData.data(), + pImage->pixelData.size()); + + pMip->BulkData.Unlock(); + } + } + + return encodedFeatureTexture; +} + +EncodedMetadataPrimitive encodeMetadataPrimitiveAnyThreadPart( + const FMetadataDescription& metadataDescription, + const FCesiumMetadataPrimitive& primitive) { + + TRACE_CPUPROFILER_EVENT_SCOPE(Cesium::EncodeMetadataPrimitive) + + EncodedMetadataPrimitive result; + + const TArray<FCesiumFeatureIdTexture>& featureIdTextures = + UCesiumMetadataPrimitiveBlueprintLibrary::GetFeatureIdTextures(primitive); + const TArray<FCesiumFeatureIdAttribute>& featureIdAttributes = + UCesiumMetadataPrimitiveBlueprintLibrary::GetFeatureIdAttributes( + primitive); + + const TArray<FString>& 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<const CesiumGltf::ImageCesium*, TWeakPtr<LoadedTextureResult>> + 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::Texture) { + + const FCesiumFeatureIdTexture* pFeatureIdTexture = + featureIdTextures.FindByPredicate([&featureTableName]( + const FCesiumFeatureIdTexture& + featureIdTexture) { + return featureTableName == + UCesiumFeatureIdTextureBlueprintLibrary::GetFeatureTableName( + featureIdTexture); + }); + + if (pFeatureIdTexture) { + const CesiumGltf::FeatureIDTextureView& featureIdTextureView = + pFeatureIdTexture->getFeatureIdTextureView(); + const CesiumGltf::ImageCesium* 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(); + + encodedFeatureIdTexture.baseName = "FIT_" + featureTableName + "_"; + encodedFeatureIdTexture.channel = featureIdTextureView.getChannel(); + encodedFeatureIdTexture.textureCoordinateAttributeId = + featureIdTextureView.getTextureCoordinateAttributeId(); + + TWeakPtr<LoadedTextureResult>* pMappedUnrealImageIt = + featureIdTextureMap.Find(pFeatureIdImage); + if (pMappedUnrealImageIt) { + encodedFeatureIdTexture.pTexture = pMappedUnrealImageIt->Pin(); + } else { + encodedFeatureIdTexture.pTexture = MakeShared<LoadedTextureResult>(); + // TODO: upgrade to new texture creation path + encodedFeatureIdTexture.pTexture->textureSource = + LegacyTextureSource{}; + featureIdTextureMap.Emplace( + pFeatureIdImage, + encodedFeatureIdTexture.pTexture); + encodedFeatureIdTexture.pTexture->pTextureData = + createTexturePlatformData( + pFeatureIdImage->width, + pFeatureIdImage->height, + // TODO: currently this is always the case, but doesn't have + // to be + EPixelFormat::PF_R8G8B8A8_UINT); + + encodedFeatureIdTexture.pTexture->addressX = TextureAddress::TA_Clamp; + encodedFeatureIdTexture.pTexture->addressY = TextureAddress::TA_Clamp; + encodedFeatureIdTexture.pTexture->filter = TextureFilter::TF_Nearest; + + if (!encodedFeatureIdTexture.pTexture->pTextureData) { + UE_LOG( + LogCesium, + Error, + TEXT( + "Error encoding a feature table property. Most likely could not allocate enough texture memory.")); + continue; + } + + FTexture2DMipMap* pMip = new FTexture2DMipMap(); + encodedFeatureIdTexture.pTexture->pTextureData->Mips.Add(pMip); + pMip->SizeX = pFeatureIdImage->width; + pMip->SizeY = pFeatureIdImage->height; + pMip->BulkData.Lock(LOCK_READ_WRITE); + + void* pTextureData = + pMip->BulkData.Realloc(pFeatureIdImage->pixelData.size()); + + FMemory::Memcpy( + pTextureData, + pFeatureIdImage->pixelData.data(), + pFeatureIdImage->pixelData.size()); + + pMip->BulkData.Unlock(); + } + + encodedFeatureIdTexture.featureTableName = featureTableName; + } + } else if ( + expectedFeatureTable.AccessType == + ECesiumFeatureTableAccessType::Attribute) { + 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<int32>(i); + + break; + } + } + } + } + + return result; +} + +EncodedMetadata encodeMetadataAnyThreadPart( + const FMetadataDescription& metadataDescription, + const FCesiumMetadataModel& metadata) { + + TRACE_CPUPROFILER_EVENT_SCOPE(Cesium::EncodeMetadataModel) + + EncodedMetadata result; + + const TMap<FString, FCesiumFeatureTable>& featureTables = + UCesiumMetadataModelBlueprintLibrary::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<FString, FCesiumFeatureTexture>& featureTextures = + UCesiumMetadataModelBlueprintLibrary::GetFeatureTextures(metadata); + result.encodedFeatureTextures.Reserve(featureTextures.Num()); + TMap<const CesiumGltf::ImageCesium*, TWeakPtr<LoadedTextureResult>> + 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<LoadedTextureResult*>& 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<const LoadedTextureResult*> 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<LoadedTextureResult*> 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->pTexture.IsValid()) { + CesiumLifetime::destroy(encodedFeatureIdTexture.pTexture->pTexture.Get()); + encodedFeatureIdTexture.pTexture->pTexture.Reset(); + } + } +} + +void destroyEncodedMetadata(EncodedMetadata& encodedMetadata) { + + // Destroy encoded feature tables. + for (auto& encodedFeatureTableIt : encodedMetadata.encodedFeatureTables) { + for (EncodedMetadataProperty& encodedProperty : + encodedFeatureTableIt.Value.encodedProperties) { + if (encodedProperty.pTexture->pTexture.IsValid()) { + CesiumLifetime::destroy(encodedProperty.pTexture->pTexture.Get()); + encodedProperty.pTexture->pTexture.Reset(); + } + } + } + + // Destroy encoded feature textures. + for (auto& encodedFeatureTextureIt : encodedMetadata.encodedFeatureTextures) { + for (EncodedFeatureTextureProperty& encodedFeatureTextureProperty : + encodedFeatureTextureIt.Value.properties) { + if (encodedFeatureTextureProperty.pTexture->pTexture.IsValid()) { + CesiumLifetime::destroy( + encodedFeatureTextureProperty.pTexture->pTexture.Get()); + encodedFeatureTextureProperty.pTexture->pTexture.Reset(); + } + } + } +} + +// 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 diff --git a/Plugins/CesiumForUnreal/Source/CesiumRuntime/Private/CesiumEncodedMetadataUtility.h b/Plugins/CesiumForUnreal/Source/CesiumRuntime/Private/CesiumEncodedMetadataUtility.h new file mode 100644 index 0000000000000000000000000000000000000000..71d766091d66ba19b715e19ff5251d5504f6036d --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/CesiumRuntime/Private/CesiumEncodedMetadataUtility.h @@ -0,0 +1,138 @@ +// Copyright 2020-2021 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" + +struct FCesiumMetadataModel; +struct FCesiumMetadataPrimitive; +struct FCesiumFeatureTable; +struct FCesiumFeatureTexture; +struct FFeatureTableDescription; +struct FFeatureTextureDescription; +struct FMetadataDescription; + +namespace CesiumEncodedMetadataUtility { +struct EncodedMetadataProperty { + /** + * @brief The name of this property. + */ + FString name; + + /** + * @brief The encoded property array. + */ + TUniquePtr<CesiumTextureUtility::LoadedTextureResult> pTexture; +}; + +struct EncodedMetadataFeatureTable { + /** + * @brief The encoded properties in this feature table. + */ + TArray<EncodedMetadataProperty> 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<CesiumTextureUtility::LoadedTextureResult> 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<CesiumTextureUtility::LoadedTextureResult> pTexture; + int64 textureCoordinateAttributeId; + int32 channelOffsets[4]; +}; + +struct EncodedFeatureTexture { + TArray<EncodedFeatureTextureProperty> properties; +}; + +struct EncodedMetadataPrimitive { + TArray<EncodedFeatureIdTexture> encodedFeatureIdTextures; + TArray<EncodedFeatureIdAttribute> encodedFeatureIdAttributes; + TArray<FString> featureTextureNames; +}; + +struct EncodedMetadata { + TMap<FString, EncodedMetadataFeatureTable> encodedFeatureTables; + TMap<FString, EncodedFeatureTexture> encodedFeatureTextures; +}; + +EncodedMetadataFeatureTable encodeMetadataFeatureTableAnyThreadPart( + const FFeatureTableDescription& featureTableDescription, + const FCesiumFeatureTable& featureTable); + +EncodedFeatureTexture encodeFeatureTextureAnyThreadPart( + TMap< + const CesiumGltf::ImageCesium*, + TWeakPtr<CesiumTextureUtility::LoadedTextureResult>>& + featureTexturePropertyMap, + const FFeatureTextureDescription& featureTextureDescription, + const FString& featureTextureName, + const FCesiumFeatureTexture& featureTexture); + +EncodedMetadataPrimitive encodeMetadataPrimitiveAnyThreadPart( + const FMetadataDescription& metadataDescription, + const FCesiumMetadataPrimitive& primitive); + +EncodedMetadata encodeMetadataAnyThreadPart( + const FMetadataDescription& metadataDescription, + const FCesiumMetadataModel& metadata); + +bool encodeMetadataFeatureTableGameThreadPart( + EncodedMetadataFeatureTable& encodedFeatureTable); + +bool encodeFeatureTextureGameThreadPart( + TArray<TUniquePtr<CesiumTextureUtility::LoadedTextureResult>>& + 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 diff --git a/Plugins/CesiumForUnreal/Source/CesiumRuntime/Private/CesiumFeatureIdAttribute.cpp b/Plugins/CesiumForUnreal/Source/CesiumRuntime/Private/CesiumFeatureIdAttribute.cpp new file mode 100644 index 0000000000000000000000000000000000000000..63dceaae4fd949e15168d0d232c10fa19e3cb756 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/CesiumRuntime/Private/CesiumFeatureIdAttribute.cpp @@ -0,0 +1,97 @@ +// Copyright 2020-2021 CesiumGS, Inc. and Contributors + +#include "CesiumFeatureIdAttribute.h" +#include "CesiumFeatureTable.h" +#include "CesiumGltf/Accessor.h" +#include "CesiumGltf/FeatureTable.h" +#include "CesiumGltf/Model.h" + +using namespace CesiumGltf; + +namespace { + +struct FeatureIDFromAccessor { + int64 operator()(std::monostate) { return -1; } + + int64 operator()( + const AccessorView<CesiumGltf::AccessorTypes::SCALAR<float>>& value) { + return static_cast<int64>(glm::round(value[vertexIdx].value[0])); + } + + template <typename T> int64 operator()(const AccessorView<T>& value) { + return static_cast<int64>(value[vertexIdx].value[0]); + } + + int64 vertexIdx; +}; + +struct VertexCountFromAccessor { + int64 operator()(std::monostate) { return 0; } + + template <typename T> int64 operator()(const AccessorView<T>& value) { + return static_cast<int64>(value.size()); + } +}; +} // namespace + +FCesiumFeatureIdAttribute::FCesiumFeatureIdAttribute( + const Model& model, + const Accessor& featureIDAccessor, + int32 attributeIndex, + const FString& featureTableName) + : _featureTableName(featureTableName), _attributeIndex(attributeIndex) { + switch (featureIDAccessor.componentType) { + case CesiumGltf::Accessor::ComponentType::BYTE: + this->_featureIDAccessor = + CesiumGltf::AccessorView<CesiumGltf::AccessorTypes::SCALAR<int8_t>>( + model, + featureIDAccessor); + break; + case CesiumGltf::Accessor::ComponentType::UNSIGNED_BYTE: + this->_featureIDAccessor = + CesiumGltf::AccessorView<CesiumGltf::AccessorTypes::SCALAR<uint8_t>>( + model, + featureIDAccessor); + break; + case CesiumGltf::Accessor::ComponentType::SHORT: + this->_featureIDAccessor = + CesiumGltf::AccessorView<CesiumGltf::AccessorTypes::SCALAR<int16_t>>( + model, + featureIDAccessor); + break; + case CesiumGltf::Accessor::ComponentType::UNSIGNED_SHORT: + this->_featureIDAccessor = + CesiumGltf::AccessorView<CesiumGltf::AccessorTypes::SCALAR<uint16_t>>( + model, + featureIDAccessor); + break; + case CesiumGltf::Accessor::ComponentType::FLOAT: + this->_featureIDAccessor = + CesiumGltf::AccessorView<CesiumGltf::AccessorTypes::SCALAR<float>>( + model, + featureIDAccessor); + break; + default: + break; + } +} + +const FString& UCesiumFeatureIdAttributeBlueprintLibrary::GetFeatureTableName( + UPARAM(ref) const FCesiumFeatureIdAttribute& FeatureIdAttribute) { + return FeatureIdAttribute._featureTableName; +} + +int64 UCesiumFeatureIdAttributeBlueprintLibrary::GetVertexCount( + UPARAM(ref) const FCesiumFeatureIdAttribute& FeatureIdAttribute) { + return std::visit( + VertexCountFromAccessor{}, + FeatureIdAttribute._featureIDAccessor); +} + +int64 UCesiumFeatureIdAttributeBlueprintLibrary::GetFeatureIDForVertex( + UPARAM(ref) const FCesiumFeatureIdAttribute& FeatureIdAttribute, + int64 vertexIdx) { + return std::visit( + FeatureIDFromAccessor{vertexIdx}, + FeatureIdAttribute._featureIDAccessor); +} diff --git a/Plugins/CesiumForUnreal/Source/CesiumRuntime/Private/CesiumFeatureIdTexture.cpp b/Plugins/CesiumForUnreal/Source/CesiumRuntime/Private/CesiumFeatureIdTexture.cpp new file mode 100644 index 0000000000000000000000000000000000000000..02f1f18dd5a7a543001130593bb9431bdab3eefd --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/CesiumRuntime/Private/CesiumFeatureIdTexture.cpp @@ -0,0 +1,47 @@ +// Copyright 2020-2021 CesiumGS, Inc. and Contributors + +#include "CesiumFeatureIdTexture.h" + +#include "CesiumGltf/FeatureIDTexture.h" +#include "CesiumGltf/Model.h" +#include "CesiumGltfPrimitiveComponent.h" + +using namespace CesiumGltf; + +FCesiumFeatureIdTexture::FCesiumFeatureIdTexture( + const Model& model, + const FeatureIDTexture& featureIdTexture) + : _featureIdTextureView(model, featureIdTexture), + _featureTableName(UTF8_TO_TCHAR( + this->_featureIdTextureView.getFeatureTableName().c_str())) {} + +const FString& UCesiumFeatureIdTextureBlueprintLibrary::GetFeatureTableName( + const FCesiumFeatureIdTexture& featureIdTexture) { + return featureIdTexture._featureTableName; +} + +int64 UCesiumFeatureIdTextureBlueprintLibrary::GetTextureCoordinateIndex( + const UPrimitiveComponent* component, + const FCesiumFeatureIdTexture& featureIdTexture) { + const UCesiumGltfPrimitiveComponent* pPrimitive = + Cast<UCesiumGltfPrimitiveComponent>(component); + if (!pPrimitive) { + return 0; + } + + auto textureCoordinateIndexIt = pPrimitive->textureCoordinateMap.find( + featureIdTexture._featureIdTextureView.getTextureCoordinateAttributeId()); + if (textureCoordinateIndexIt == pPrimitive->textureCoordinateMap.end()) { + return 0; + } + + return textureCoordinateIndexIt->second; +} + +int64 UCesiumFeatureIdTextureBlueprintLibrary:: + GetFeatureIdForTextureCoordinates( + const FCesiumFeatureIdTexture& featureIdTexture, + float u, + float v) { + return featureIdTexture._featureIdTextureView.getFeatureID(u, v); +} diff --git a/Plugins/CesiumForUnreal/Source/CesiumRuntime/Private/CesiumFeatureTable.cpp b/Plugins/CesiumForUnreal/Source/CesiumRuntime/Private/CesiumFeatureTable.cpp new file mode 100644 index 0000000000000000000000000000000000000000..ac8ed711080aaa732732ec3a8bb922fdeafddb5d --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/CesiumRuntime/Private/CesiumFeatureTable.cpp @@ -0,0 +1,72 @@ +// Copyright 2020-2021 CesiumGS, Inc. and Contributors + +#include "CesiumFeatureTable.h" +#include "CesiumGltf/MetadataFeatureTableView.h" +#include "CesiumMetadataPrimitive.h" + +FCesiumFeatureTable::FCesiumFeatureTable( + const CesiumGltf::Model& model, + const CesiumGltf::FeatureTable& featureTable) { + + CesiumGltf::MetadataFeatureTableView featureTableView{&model, &featureTable}; + + featureTableView.forEachProperty([&properties = _properties]( + const std::string& propertyName, + auto propertyValue) mutable { + if (propertyValue.status() == + CesiumGltf::MetadataPropertyViewStatus::Valid) { + FString key(UTF8_TO_TCHAR(propertyName.data())); + properties.Add(key, FCesiumMetadataProperty(propertyValue)); + } + }); +} + +TMap<FString, FCesiumMetadataGenericValue> +UCesiumFeatureTableBlueprintLibrary::GetMetadataValuesForFeatureID( + UPARAM(ref) const FCesiumFeatureTable& FeatureTable, + int64 featureID) { + TMap<FString, FCesiumMetadataGenericValue> feature; + for (const auto& pair : FeatureTable._properties) { + feature.Add( + pair.Key, + UCesiumMetadataPropertyBlueprintLibrary::GetGenericValue( + pair.Value, + featureID)); + } + + return feature; +} + +TMap<FString, FString> +UCesiumFeatureTableBlueprintLibrary::GetMetadataValuesAsStringForFeatureID( + UPARAM(ref) const FCesiumFeatureTable& FeatureTable, + int64 featureID) { + TMap<FString, FString> feature; + for (const auto& pair : FeatureTable._properties) { + feature.Add( + pair.Key, + UCesiumMetadataGenericValueBlueprintLibrary::GetString( + UCesiumMetadataPropertyBlueprintLibrary::GetGenericValue( + pair.Value, + featureID), + "")); + } + + return feature; +} + +int64 UCesiumFeatureTableBlueprintLibrary::GetNumberOfFeatures( + UPARAM(ref) const FCesiumFeatureTable& FeatureTable) { + if (FeatureTable._properties.Num() == 0) { + return 0; + } + + return UCesiumMetadataPropertyBlueprintLibrary::GetNumberOfFeatures( + FeatureTable._properties.begin().Value()); +} + +const TMap<FString, FCesiumMetadataProperty>& +UCesiumFeatureTableBlueprintLibrary::GetProperties( + UPARAM(ref) const FCesiumFeatureTable& FeatureTable) { + return FeatureTable._properties; +} diff --git a/Plugins/CesiumForUnreal/Source/CesiumRuntime/Private/CesiumFeatureTexture.cpp b/Plugins/CesiumForUnreal/Source/CesiumRuntime/Private/CesiumFeatureTexture.cpp new file mode 100644 index 0000000000000000000000000000000000000000..052058d3da51e154c4da07b2b6d9efa1482c153a --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/CesiumRuntime/Private/CesiumFeatureTexture.cpp @@ -0,0 +1,45 @@ +// Copyright 2020-2021 CesiumGS, Inc. and Contributors + +#include "CesiumFeatureTexture.h" +#include "CesiumGltf/FeatureTexturePropertyView.h" +#include "CesiumGltf/FeatureTextureView.h" +#include "CesiumGltf/Model.h" + +FCesiumFeatureTexture::FCesiumFeatureTexture( + const CesiumGltf::Model& model, + const CesiumGltf::FeatureTexture& featureTexture) + : _featureTextureView(model, featureTexture) { + + if (this->_featureTextureView.status() == + CesiumGltf::FeatureTextureViewStatus::Valid) { + const std::unordered_map< + std::string, + CesiumGltf::FeatureTexturePropertyView>& properties = + this->_featureTextureView.getProperties(); + this->_propertyKeys.Reserve(properties.size()); + for (auto propertyView : properties) { + this->_propertyKeys.Emplace(UTF8_TO_TCHAR(propertyView.first.c_str())); + } + } +} + +const TArray<FString>& UCesiumFeatureTextureBlueprintLibrary::GetPropertyKeys( + UPARAM(ref) const FCesiumFeatureTexture& FeatureTexture) { + return FeatureTexture._propertyKeys; +} + +FCesiumFeatureTextureProperty +UCesiumFeatureTextureBlueprintLibrary::FindProperty( + UPARAM(ref) const FCesiumFeatureTexture& FeatureTexture, + const FString& PropertyName) { + + const std::unordered_map<std::string, CesiumGltf::FeatureTexturePropertyView>& + properties = FeatureTexture._featureTextureView.getProperties(); + + auto propertyIt = properties.find(TCHAR_TO_UTF8(*PropertyName)); + if (propertyIt == properties.end()) { + return FCesiumFeatureTextureProperty(); + } + + return FCesiumFeatureTextureProperty(propertyIt->second); +} diff --git a/Plugins/CesiumForUnreal/Source/CesiumRuntime/Private/CesiumFeatureTextureProperty.cpp b/Plugins/CesiumForUnreal/Source/CesiumRuntime/Private/CesiumFeatureTextureProperty.cpp new file mode 100644 index 0000000000000000000000000000000000000000..7b817369be84f4dd56596dc376331ab7b4fd95ed --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/CesiumRuntime/Private/CesiumFeatureTextureProperty.cpp @@ -0,0 +1,107 @@ +// Copyright 2020-2021 CesiumGS, Inc. and Contributors + +#include "CesiumFeatureTextureProperty.h" +#include "CesiumGltfPrimitiveComponent.h" +#include "CesiumMetadataConversions.h" + +#include <cstdint> +#include <limits> + +int64 UCesiumFeatureTexturePropertyBlueprintLibrary::GetTextureCoordinateIndex( + const UPrimitiveComponent* component, + UPARAM(ref) const FCesiumFeatureTextureProperty& property) { + const UCesiumGltfPrimitiveComponent* pPrimitive = + Cast<UCesiumGltfPrimitiveComponent>(component); + if (!pPrimitive) { + return 0; + } + + auto textureCoordinateIndexIt = pPrimitive->textureCoordinateMap.find( + property._pProperty->getTextureCoordinateAttributeId()); + if (textureCoordinateIndexIt == pPrimitive->textureCoordinateMap.end()) { + return 0; + } + + return textureCoordinateIndexIt->second; +} + +int64 UCesiumFeatureTexturePropertyBlueprintLibrary::GetComponentCount( + UPARAM(ref) const FCesiumFeatureTextureProperty& property) { + return property._pProperty->getComponentCount(); +} + +bool UCesiumFeatureTexturePropertyBlueprintLibrary::IsNormalized( + UPARAM(ref) const FCesiumFeatureTextureProperty& property) { + return property._pProperty->isNormalized(); +} + +FString UCesiumFeatureTexturePropertyBlueprintLibrary::GetSwizzle( + UPARAM(ref) const FCesiumFeatureTextureProperty& property) { + return UTF8_TO_TCHAR(property._pProperty->getSwizzle().c_str()); +} + +FCesiumIntegerColor UCesiumFeatureTexturePropertyBlueprintLibrary:: + GetIntegerColorFromTextureCoordinates( + UPARAM(ref) const FCesiumFeatureTextureProperty& property, + float u, + float v) { + switch (property._pProperty->getPropertyType()) { + case CesiumGltf::FeatureTexturePropertyComponentType::Uint8: { + CesiumGltf::FeatureTexturePropertyValue<uint8_t> propertyValue = + property._pProperty->getProperty<uint8_t>(u, v); + return { + CesiumMetadataConversions<int32, uint8_t>::convert( + propertyValue.components[0], + 0), + CesiumMetadataConversions<int32, uint8_t>::convert( + propertyValue.components[1], + 0), + CesiumMetadataConversions<int32, uint8_t>::convert( + propertyValue.components[2], + 0), + CesiumMetadataConversions<int32, uint8_t>::convert( + propertyValue.components[3], + 0)}; + } break; + default: + return {0, 0, 0, 0}; + } +} + +FCesiumFloatColor UCesiumFeatureTexturePropertyBlueprintLibrary:: + GetFloatColorFromTextureCoordinates( + UPARAM(ref) const FCesiumFeatureTextureProperty& property, + float u, + float v) { + switch (property._pProperty->getPropertyType()) { + case CesiumGltf::FeatureTexturePropertyComponentType::Uint8: { + CesiumGltf::FeatureTexturePropertyValue<uint8_t> propertyValue = + property._pProperty->getProperty<uint8_t>(u, v); + + float normalizationDenominator = 1.0f; + if (property._pProperty->isNormalized()) { + normalizationDenominator = std::numeric_limits<uint8_t>::max(); + } + + return { + CesiumMetadataConversions<float, uint8_t>::convert( + propertyValue.components[0], + 0.0f) / + normalizationDenominator, + CesiumMetadataConversions<float, uint8_t>::convert( + propertyValue.components[1], + 0.0f) / + normalizationDenominator, + CesiumMetadataConversions<float, uint8_t>::convert( + propertyValue.components[2], + 0.0f) / + normalizationDenominator, + CesiumMetadataConversions<float, uint8_t>::convert( + propertyValue.components[3], + 0.0f) / + normalizationDenominator}; + } break; + default: + return {0.0f, 0.0f, 0.0f, 0.0f}; + } +} diff --git a/Plugins/CesiumForUnreal/Source/CesiumRuntime/Private/CesiumGeoreference.cpp b/Plugins/CesiumForUnreal/Source/CesiumRuntime/Private/CesiumGeoreference.cpp new file mode 100644 index 0000000000000000000000000000000000000000..01ab7fcff6aae559fcbac7b4e9960c25dc025e77 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/CesiumRuntime/Private/CesiumGeoreference.cpp @@ -0,0 +1,1178 @@ +// Copyright 2020-2021 CesiumGS, Inc. and Contributors + +#include "CesiumGeoreference.h" +#include "Camera/PlayerCameraManager.h" +#include "CesiumActors.h" +#include "CesiumCommon.h" +#include "CesiumGeospatial/Transforms.h" +#include "CesiumRuntime.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 "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 <glm/ext/matrix_transform.hpp> +#include <glm/gtc/matrix_inverse.hpp> +#include <glm/gtc/quaternion.hpp> +#include <optional> +#include <string> + +#if WITH_EDITOR +#include "DrawDebugHelpers.h" +#include "Editor.h" +#include "EditorViewportClient.h" +#include "Slate/SceneViewport.h" +#include "WorldBrowserModule.h" + +// These are in the Private directory, yet they are exported, so we're able to +// use them. And there's no other way (AFAIK) to get details of unloaded levels. +#include "../Private/LevelCollectionModel.h" +#include "../Private/LevelModel.h" +#endif + +FName ACesiumGeoreference::DEFAULT_GEOREFERENCE_TAG = + FName("DEFAULT_GEOREFERENCE"); + +/*static*/ ACesiumGeoreference* +ACesiumGeoreference::GetDefaultGeoreference(const UObject* WorldContextObject) { + 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 GetDefaultGeoreference: %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) + ACesiumGeoreference* pGeoreference = nullptr; + EActorIteratorFlags flags = EActorIteratorFlags::OnlyActiveLevels | + EActorIteratorFlags::SkipPendingKill; + for (TActorIterator<AActor> actorIterator( + world, + ACesiumGeoreference::StaticClass(), + flags); + actorIterator; + ++actorIterator) { + AActor* actor = *actorIterator; + if (actor->ActorHasTag(DEFAULT_GEOREFERENCE_TAG)) { + pGeoreference = Cast<ACesiumGeoreference>(actor); + break; + } + } + if (!pGeoreference) { + // Legacy method of finding Georeference, for backwards compatibility with + // existing projects + ACesiumGeoreference* pGeoreferenceCandidate = + FindObject<ACesiumGeoreference>( + world->PersistentLevel, + TEXT("CesiumGeoreferenceDefault")); + // Test if PendingKill + if (IsValid(pGeoreferenceCandidate)) { + pGeoreference = pGeoreferenceCandidate; + } + } + if (!pGeoreference) { + UE_LOG( + LogCesium, + Verbose, + TEXT("Creating default Georeference for actor %s"), + *WorldContextObject->GetName()); + // Spawn georeference in the persistent level + FActorSpawnParameters spawnParameters; + spawnParameters.SpawnCollisionHandlingOverride = + ESpawnActorCollisionHandlingMethod::AlwaysSpawn; + pGeoreference = world->SpawnActor<ACesiumGeoreference>(spawnParameters); + // Null check so the editor doesn't crash when it makes arbitrary calls to + // this function without a valid world context object. + if (pGeoreference) { + pGeoreference->Tags.Add(DEFAULT_GEOREFERENCE_TAG); + } + + } else { + UE_LOG( + LogCesium, + Verbose, + TEXT("Using existing Georeference %s for actor %s"), + *pGeoreference->GetName(), + *WorldContextObject->GetName()); + } + return pGeoreference; +} + +ACesiumGeoreference::ACesiumGeoreference() + : _ellipsoidRadii{ + CesiumGeospatial::Ellipsoid::WGS84.getRadii().x, + CesiumGeospatial::Ellipsoid::WGS84.getRadii().y, + CesiumGeospatial::Ellipsoid::WGS84.getRadii().z}, + _geoTransforms(), + _insideSublevel(false) { + PrimaryActorTick.bCanEverTick = true; +} + +#if WITH_EDITOR +void ACesiumGeoreference::PlaceGeoreferenceOriginHere() { + // If this is PIE mode, ignore + UWorld* pWorld = this->GetWorld(); + if (!GEditor || pWorld->IsGameWorld()) { + return; + } + + FViewport* pViewport = GEditor->GetActiveViewport(); + FViewportClient* pViewportClient = pViewport->GetClient(); + FEditorViewportClient* pEditorViewportClient = + static_cast<FEditorViewportClient*>(pViewportClient); + + FRotationTranslationMatrix fCameraTransform( + pEditorViewportClient->GetViewRotation(), + pEditorViewportClient->GetViewLocation()); + const FIntVector& originLocation = pWorld->OriginLocation; + + // TODO: optimize this, only need to transform the front direction and + // translation + + const FVector& viewLocation = pEditorViewportClient->GetViewLocation(); + glm::dvec4 translation = VecMath::add4D(viewLocation, originLocation); + + // camera local space to Unreal absolute world + glm::dmat4 cameraToAbsolute = + VecMath::createMatrix4D(fCameraTransform, translation); + + // camera local space to ECEF + glm::dmat4 cameraToECEF = + this->_geoTransforms + .GetAbsoluteUnrealWorldToEllipsoidCenteredTransform() * + cameraToAbsolute; + + // 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) + glm::dvec3 targetGeoreferenceOrigin = + _geoTransforms.TransformEcefToLongitudeLatitudeHeight( + glm::dvec3(cameraToECEF[3])); + + this->_setGeoreferenceOrigin( + targetGeoreferenceOrigin.x, + targetGeoreferenceOrigin.y, + targetGeoreferenceOrigin.z); + + glm::dmat4 absoluteToRelativeWorld = VecMath::createTranslationMatrix4D( + -originLocation.X, + -originLocation.Y, + -originLocation.Z, + 1.0); + + // TODO: check for degeneracy ? + glm::dmat4 newCameraTransform = + absoluteToRelativeWorld * + this->_geoTransforms + .GetEllipsoidCenteredToAbsoluteUnrealWorldTransform() * + cameraToECEF; + glm::dvec3 cameraFront = glm::normalize(glm::dvec3(newCameraTransform[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()); + pEditorViewportClient->SetViewLocation( + FVector(-originLocation.X, -originLocation.Y, -originLocation.Z)); + + this->_enableAndGeoreferenceCurrentSubLevel(); +} +#endif + +namespace { + +template <typename TStringish> +FString longPackageNameToCesiumName(UWorld* pWorld, const TStringish& name) { + FString levelName = FPackageName::GetShortName(name); + levelName.RemoveFromStart(pWorld->StreamingLevelsPrefix); + return levelName; +} + +struct WorldCompositionLevelPair { + FWorldCompositionTile* pTile; + ULevelStreaming* pLevelStreaming; +}; + +WorldCompositionLevelPair findWorldCompositionLevel( + UWorldComposition* pWorldComposition, + const FName& packageName) { + + UWorldComposition::FTilesList& tiles = pWorldComposition->GetTilesList(); + const TArray<ULevelStreaming*>& levels = pWorldComposition->TilesStreaming; + + for (int32 i = 0; i < tiles.Num(); ++i) { + FWorldCompositionTile& tile = tiles[i]; + + if (tile.Info.Layer.DistanceStreamingEnabled) { + // UE itself is managing distance-based streaming for this level, ignore + // it. + continue; + } + + if (tile.PackageName == packageName) { + assert(i < levels.Num()); + return {&tile, levels[i]}; + } + } + + return {nullptr, nullptr}; +} + +} // namespace + +#if WITH_EDITOR +void ACesiumGeoreference::_updateCesiumSubLevels() { + 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; + } + + const UWorldComposition::FTilesList& allLevels = + pWorld->WorldComposition->GetTilesList(); + + TArray<int32> newSubLevels; + TArray<int32> missingSubLevels; + + bool checkForNewCurrentLevel = false; + + // Find new sub-levels that we don't know about on the Cesium side. + for (int32 i = 0; i < allLevels.Num(); ++i) { + const FWorldCompositionTile& level = allLevels[i]; + + FString levelName = longPackageNameToCesiumName(pWorld, level.PackageName); + + // Check if the level is already known + FCesiumSubLevel* pFound = this->CesiumSubLevels.FindByPredicate( + [&levelName](FCesiumSubLevel& subLevel) { + return levelName.Equals(subLevel.LevelName); + }); + + if (pFound) { + bool newCanBeEnabled = !level.Info.Layer.DistanceStreamingEnabled; + if (pFound->CanBeEnabled != newCanBeEnabled) { + pFound->CanBeEnabled = newCanBeEnabled; + + // If this level can't be enabled, make sure it's not enabled. + if (!pFound->CanBeEnabled) { + pFound->Enabled = false; + } + + if (newCanBeEnabled) { + // This level existed before but is newly enable-able, probably + // because it was just added to the right streaming layer. If it also + // happens to be the current level, we'll want to immediately hide + // other levels. Set a flag to do that later. + checkForNewCurrentLevel = true; + } + } + } else { + newSubLevels.Add(i); + } + } + + // Find any Cesium sub-levels that don't exist anymore. + for (int32 i = 0; i < this->CesiumSubLevels.Num(); ++i) { + FCesiumSubLevel& cesiumLevel = this->CesiumSubLevels[i]; + + const FWorldCompositionTile* pLevel = allLevels.FindByPredicate( + [&cesiumLevel, pWorld](const FWorldCompositionTile& level) { + return longPackageNameToCesiumName(pWorld, level.PackageName) == + cesiumLevel.LevelName; + }); + + if (!pLevel) { + missingSubLevels.Add(i); + } + } + + if (newSubLevels.Num() == 1 && missingSubLevels.Num() == 1) { + // There is exactly one missing and one new, assume it's been renamed. + const FWorldCompositionTile& level = allLevels[newSubLevels[0]]; + this->CesiumSubLevels[missingSubLevels[0]].LevelName = + longPackageNameToCesiumName(pWorld, level.PackageName); + } else if (newSubLevels.Num() > 0 || missingSubLevels.Num() > 0) { + // Remove our record of the sub-levels that no longer exist. + // Do this in reverse order so the indices don't get invalidated. + for (int32 i = missingSubLevels.Num() - 1; i >= 0; --i) { + this->CesiumSubLevels.RemoveAt(missingSubLevels[i]); + } + + // Add new Cesium records for the new sub-levels + for (int32 i = 0; i < newSubLevels.Num(); ++i) { + const FWorldCompositionTile& level = allLevels[newSubLevels[i]]; + bool canBeEnabled = !level.Info.Layer.DistanceStreamingEnabled; + this->CesiumSubLevels.Add(FCesiumSubLevel{ + longPackageNameToCesiumName(pWorld, level.PackageName), + canBeEnabled, + OriginLongitude, + OriginLatitude, + OriginHeight, + 1000.0, + canBeEnabled}); + } + } + + if (checkForNewCurrentLevel) { + this->_onNewCurrentLevel(); + } +} +#endif + +bool ACesiumGeoreference::SwitchToLevel(int32 Index) { + FCesiumSubLevel* pLevel = nullptr; + + if (Index >= 0 && Index < this->CesiumSubLevels.Num()) { + pLevel = &this->CesiumSubLevels[Index]; + } + + UWorld* pWorld = this->GetWorld(); + const TArray<ULevelStreaming*>& levels = pWorld->GetStreamingLevels(); + + ULevelStreaming* pStreamedLevel = nullptr; + + if (pLevel) { + // Find the streaming level with this name. + pStreamedLevel = this->_findLevelStreamingByName(pLevel->LevelName); + if (!pStreamedLevel) { + UE_LOG( + LogCesium, + Warning, + TEXT("No streaming level found with name %s"), + *pLevel->LevelName); + } + } + + // Deactivate all other streaming levels controlled by Cesium + for (const FCesiumSubLevel& subLevel : this->CesiumSubLevels) { + if (&subLevel == pLevel) { + continue; + } + + if (!subLevel.CanBeEnabled) { + // A sub-level that can't be enabled is being controled by Unreal Engine, + // based on its own distance-based system, so we have no business trying + // to disable it. Ignore it. + continue; + } + + ULevelStreaming* pOtherLevel = + this->_findLevelStreamingByName(subLevel.LevelName); + + if (pOtherLevel->ShouldBeVisible() || pOtherLevel->ShouldBeLoaded()) { + // We need to unload immediately, not over the course of several frames. + // If we don't unload immediately, objects in the old level will still be + // visible, but they will be positioned incorrectly. + // If this causes an objectionable pause, we can do something much more + // complicated like defer the georeference switch and activation of the + // new level until after the old one has finished asynchronously + // unloading. We're considering that a future feature for the moment, + // though. + pOtherLevel->bShouldBlockOnUnload = true; + pOtherLevel->SetShouldBeLoaded(false); + pOtherLevel->SetShouldBeVisible(false); + } + } + + // Activate the new streaming level if it's not already active. + if (pStreamedLevel && (!pStreamedLevel->ShouldBeVisible() || + !pStreamedLevel->ShouldBeLoaded())) { + this->_setGeoreferenceOrigin( + pLevel->LevelLongitude, + pLevel->LevelLatitude, + pLevel->LevelHeight); + + pStreamedLevel->SetShouldBeLoaded(true); + pStreamedLevel->SetShouldBeVisible(true); + } + + return pStreamedLevel != nullptr; +} + +FVector +ACesiumGeoreference::GetGeoreferenceOriginLongitudeLatitudeHeight() const { + return FVector(OriginLongitude, OriginLatitude, OriginHeight); +} + +void ACesiumGeoreference::SetGeoreferenceOriginLongitudeLatitudeHeight( + const glm::dvec3& targetLongitudeLatitudeHeight) { + // Should not allow externally initiated georeference origin changing if we + // are inside a sublevel + if (this->_insideSublevel) { + return; + } + this->_setGeoreferenceOrigin( + targetLongitudeLatitudeHeight.x, + targetLongitudeLatitudeHeight.y, + targetLongitudeLatitudeHeight.z); +} + +void ACesiumGeoreference::SetGeoreferenceOrigin( + const glm::dvec3& TargetLongitudeLatitudeHeight) { + UE_LOG( + LogCesium, + Warning, + TEXT( + "SetGeoreferenceOrigin was renamed to SetGeoreferenceOriginLongitudeLatitudeHeight.")); + SetGeoreferenceOriginLongitudeLatitudeHeight(TargetLongitudeLatitudeHeight); +} + +void ACesiumGeoreference::SetGeoreferenceOriginEcef( + const glm::dvec3& TargetEcef) { + SetGeoreferenceOriginLongitudeLatitudeHeight( + _geoTransforms.TransformEcefToLongitudeLatitudeHeight(TargetEcef)); +} + +void ACesiumGeoreference::SetGeoreferenceOriginLongitudeLatitudeHeight( + const FVector& targetLongitudeLatitudeHeight) { + this->SetGeoreferenceOriginLongitudeLatitudeHeight(glm::dvec3( + targetLongitudeLatitudeHeight.X, + targetLongitudeLatitudeHeight.Y, + targetLongitudeLatitudeHeight.Z)); +} + +void ACesiumGeoreference::SetGeoreferenceOriginEcef(const FVector& TargetEcef) { + this->SetGeoreferenceOriginEcef( + glm::dvec3(TargetEcef.X, TargetEcef.Y, TargetEcef.Z)); +} + +// Called when the game starts or when spawned +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; + } + + if (!this->SubLevelCamera) { + // Find the first player's camera manager + APlayerController* pPlayerController = pWorld->GetFirstPlayerController(); + if (pPlayerController) { + this->SubLevelCamera = pPlayerController->PlayerCameraManager; + } + + if (!this->SubLevelCamera) { + UE_LOG( + LogCesium, + Warning, + TEXT( + "CesiumGeoreference could not find a FirstPlayerController or a corresponding PlayerCameraManager.")); + } + } + + UpdateGeoreference(); +} + +void ACesiumGeoreference::EndPlay(const EEndPlayReason::Type EndPlayReason) { + Super::EndPlay(EndPlayReason); +} + +/** In case the CesiumGeoreference gets spawned at run time, instead of design + * time, ensure that frames are updated */ +void ACesiumGeoreference::OnConstruction(const FTransform& Transform) { + UE_LOG( + LogCesium, + Verbose, + TEXT("Called OnConstruction on actor %s"), + *this->GetName()); + +#if WITH_EDITOR + if (!this->_newCurrentLevelSubscription.IsValid()) { + this->_newCurrentLevelSubscription = + FEditorDelegates::NewCurrentLevel.AddUObject( + this, + &ACesiumGeoreference::_onNewCurrentLevel); + } +#endif + + this->UpdateGeoreference(); +} + +void ACesiumGeoreference::BeginDestroy() { +#if WITH_EDITOR + if (this->_newCurrentLevelSubscription.IsValid()) { + FEditorDelegates::NewCurrentLevel.Remove( + this->_newCurrentLevelSubscription); + this->_newCurrentLevelSubscription.Reset(); + } +#endif + + Super::BeginDestroy(); +} + +void ACesiumGeoreference::UpdateGeoreference() { + this->_updateGeoTransforms(); + + UE_LOG( + LogCesium, + Verbose, + TEXT("Broadcasting OnGeoreferenceUpdated for Georeference %s"), + *this->GetFullName()); + + OnGeoreferenceUpdated.Broadcast(); +} + +#if WITH_EDITOR +void ACesiumGeoreference::PostEditChangeProperty(FPropertyChangedEvent& event) { + Super::PostEditChangeProperty(event); + + if (!event.Property) { + return; + } + + FName propertyName = event.Property->GetFName(); + + if (propertyName == + GET_MEMBER_NAME_CHECKED(ACesiumGeoreference, OriginPlacement) || + propertyName == + GET_MEMBER_NAME_CHECKED(ACesiumGeoreference, OriginLongitude) || + propertyName == + GET_MEMBER_NAME_CHECKED(ACesiumGeoreference, OriginLatitude) || + propertyName == + GET_MEMBER_NAME_CHECKED(ACesiumGeoreference, OriginHeight)) { + this->_enableAndGeoreferenceCurrentSubLevel(); + this->UpdateGeoreference(); + return; + } else if ( + propertyName == + GET_MEMBER_NAME_CHECKED(ACesiumGeoreference, CesiumSubLevels)) { + } +} +#endif + +bool ACesiumGeoreference::ShouldTickIfViewportsOnly() const { return true; } + +#if WITH_EDITOR +void ACesiumGeoreference::_showSubLevelLoadRadii() const { + UWorld* world = this->GetWorld(); + if (world->IsGameWorld()) { + return; + } + if (!this->ShowLoadRadii) { + return; + } + const glm::dvec4 originLocation = + glm::dvec4(VecMath::createVector3D(world->OriginLocation), 1.0); + for (const FCesiumSubLevel& level : this->CesiumSubLevels) { + glm::dvec3 levelECEF = + _geoTransforms.TransformLongitudeLatitudeHeightToEcef(glm::dvec3( + level.LevelLongitude, + level.LevelLatitude, + level.LevelHeight)); + + glm::dvec4 levelAbs = + this->_geoTransforms + .GetEllipsoidCenteredToAbsoluteUnrealWorldTransform() * + glm::dvec4(levelECEF, 1.0); + FVector levelRelative = VecMath::createVector(levelAbs - originLocation); + DrawDebugSphere( + world, + levelRelative, + 100.0 * level.LoadRadius, + 100, + FColor::Blue); + } +} +#endif // WITH_EDITOR + +#if WITH_EDITOR +void ACesiumGeoreference::_handleViewportOriginEditing() { + if (!this->EditOriginInViewport) { + return; + } + FHitResult mouseRayResults; + bool mouseRaySuccess; + + this->_lineTraceViewportMouse(false, mouseRaySuccess, mouseRayResults); + + if (!mouseRaySuccess) { + return; + } + const FIntVector& originLocation = this->GetWorld()->OriginLocation; + + FVector grabbedLocation = mouseRayResults.Location; + // convert from UE to ECEF to LongitudeLatitudeHeight + glm::dvec4 grabbedLocationAbs = + VecMath::add4D(grabbedLocation, originLocation); + + glm::dvec3 grabbedLocationECEF = glm::dvec3( + this->_geoTransforms + .GetAbsoluteUnrealWorldToEllipsoidCenteredTransform() * + grabbedLocationAbs); + + glm::dvec3 cartographic = + _geoTransforms.TransformEcefToLongitudeLatitudeHeight( + grabbedLocationECEF); + + UE_LOG( + LogActor, + Warning, + TEXT("Mouse Location: (Longitude: %f, Latitude: %f, Height: %f)"), + cartographic.x, + cartographic.y, + cartographic.z); + + // TODO: find editor viewport mouse click event + // if (mouseDown) { + // this->_setGeoreferenceOrigin() + // this->EditOriginInViewport = false; + //} +} +#endif // WITH_EDITOR + +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<int64>(f) + static_cast<int64>(i); + int64 min = static_cast<int64>(TNumericLimits<int32>::Min()); + int64 max = static_cast<int64>(TNumericLimits<int32>::Max()); + int64 clamped = FMath::Max(min, FMath::Min(max, sum)); + return static_cast<int32>(clamped); +} +} // namespace + +bool ACesiumGeoreference::_updateSublevelState() { + if (this->CesiumSubLevels.Num() == 0) { + // If we don't have any known sublevels, bail quickly to save ourselves a + // little work. + return false; + } + + if (!IsValid(this->SubLevelCamera)) { + return false; + } + + UWorld* pWorld = this->GetWorld(); + const FIntVector& originLocation = pWorld->OriginLocation; + const FMinimalViewInfo& pov = this->SubLevelCamera->ViewTarget.POV; + const FVector& cameraLocation = pov.Location; + + glm::dvec4 cameraAbsolute = VecMath::add4D(cameraLocation, originLocation); + + glm::dvec3 cameraECEF = glm::dvec3( + this->_geoTransforms + .GetAbsoluteUnrealWorldToEllipsoidCenteredTransform() * + cameraAbsolute); + + int32 activeLevel = -1; + double closestLevelDistance = std::numeric_limits<double>::max(); + + for (int32 i = 0; i < this->CesiumSubLevels.Num(); ++i) { + const FCesiumSubLevel& level = this->CesiumSubLevels[i]; + if (!level.Enabled) { + continue; + } + + glm::dvec3 levelECEF = + _geoTransforms.TransformLongitudeLatitudeHeightToEcef(glm::dvec3( + level.LevelLongitude, + level.LevelLatitude, + level.LevelHeight)); + + double levelDistance = glm::length(levelECEF - cameraECEF); + if (levelDistance < level.LoadRadius && + levelDistance < closestLevelDistance) { + activeLevel = i; + } + } + + // activeLevel may be -1, in which case all levels will be deactivated. + return this->SwitchToLevel(activeLevel); +} + +void ACesiumGeoreference::_updateGeoTransforms() { + glm::dvec3 center(0.0, 0.0, 0.0); + if (this->OriginPlacement == EOriginPlacement::CartographicOrigin) { + center = _geoTransforms.TransformLongitudeLatitudeHeightToEcef(glm::dvec3( + this->OriginLongitude, + this->OriginLatitude, + this->OriginHeight)); + } + + this->_geoTransforms = GeoTransforms( + CesiumGeospatial::Ellipsoid( + this->_ellipsoidRadii[0], + this->_ellipsoidRadii[1], + this->_ellipsoidRadii[2]), + center); +} + +void ACesiumGeoreference::Tick(float DeltaTime) { + Super::Tick(DeltaTime); + +#if WITH_EDITOR + // There doesn't appear to be a good way to be notified about the wide variety + // of level manipulations we care about, so in the Editor we'll poll. + if (GEditor && IsValid(this->GetWorld()) && + IsValid(this->GetWorld()->WorldComposition) && + !this->GetWorld()->IsGameWorld()) { + this->_updateCesiumSubLevels(); + } + + _showSubLevelLoadRadii(); + _handleViewportOriginEditing(); +#endif + + if (!this->_shouldManageSubLevels()) { + this->_insideSublevel = _updateSublevelState(); + } +} + +void ACesiumGeoreference::Serialize(FArchive& Ar) { + Super::Serialize(Ar); + + // Recompute derived values on load. + if (Ar.IsLoading()) { + this->_updateGeoTransforms(); + } +} + +/** + * Useful Conversion Functions + */ + +glm::dvec3 ACesiumGeoreference::TransformLongitudeLatitudeHeightToEcef( + const glm::dvec3& longitudeLatitudeHeight) const { + return _geoTransforms.TransformLongitudeLatitudeHeightToEcef( + longitudeLatitudeHeight); +} + +FVector ACesiumGeoreference::TransformLongitudeLatitudeHeightToEcef( + const FVector& longitudeLatitudeHeight) const { + glm::dvec3 ecef = this->_geoTransforms.TransformLongitudeLatitudeHeightToEcef( + VecMath::createVector3D(longitudeLatitudeHeight)); + return FVector(ecef.x, ecef.y, ecef.z); +} + +glm::dvec3 ACesiumGeoreference::TransformEcefToLongitudeLatitudeHeight( + const glm::dvec3& ecef) const { + return _geoTransforms.TransformEcefToLongitudeLatitudeHeight(ecef); +} + +FVector ACesiumGeoreference::TransformEcefToLongitudeLatitudeHeight( + const FVector& ecef) const { + glm::dvec3 llh = this->_geoTransforms.TransformEcefToLongitudeLatitudeHeight( + glm::dvec3(ecef.X, ecef.Y, ecef.Z)); + return FVector(llh.x, llh.y, llh.z); +} + +glm::dvec3 ACesiumGeoreference::TransformLongitudeLatitudeHeightToUnreal( + const glm::dvec3& longitudeLatitudeHeight) const { + return this->_geoTransforms.TransformLongitudeLatitudeHeightToUnreal( + glm::dvec3(CesiumActors::getWorldOrigin4D(this)), + longitudeLatitudeHeight); +} + +FVector ACesiumGeoreference::TransformLongitudeLatitudeHeightToUnreal( + const FVector& longitudeLatitudeHeight) const { + glm::dvec3 ue = this->_geoTransforms.TransformLongitudeLatitudeHeightToUnreal( + glm::dvec3(CesiumActors::getWorldOrigin4D(this)), + VecMath::createVector3D(longitudeLatitudeHeight)); + return FVector(ue.x, ue.y, ue.z); +} + +glm::dvec3 ACesiumGeoreference::TransformUnrealToLongitudeLatitudeHeight( + const glm::dvec3& ue) const { + return this->_geoTransforms.TransformUnrealToLongitudeLatitudeHeight( + glm::dvec3(CesiumActors::getWorldOrigin4D(this)), + ue); +} + +FVector ACesiumGeoreference::TransformUnrealToLongitudeLatitudeHeight( + const FVector& ue) const { + glm::dvec3 llh = + this->_geoTransforms.TransformUnrealToLongitudeLatitudeHeight( + glm::dvec3(CesiumActors::getWorldOrigin4D(this)), + VecMath::createVector3D(ue)); + return FVector(llh.x, llh.y, llh.z); +} + +glm::dvec3 +ACesiumGeoreference::TransformEcefToUnreal(const glm::dvec3& ecef) const { + return this->_geoTransforms.TransformEcefToUnreal( + glm::dvec3(CesiumActors::getWorldOrigin4D(this)), + ecef); +} + +FVector ACesiumGeoreference::TransformEcefToUnreal(const FVector& ecef) const { + glm::dvec3 ue = this->_geoTransforms.TransformEcefToUnreal( + glm::dvec3(CesiumActors::getWorldOrigin4D(this)), + VecMath::createVector3D(ecef)); + return FVector(ue.x, ue.y, ue.z); +} + +glm::dvec3 +ACesiumGeoreference::TransformUnrealToEcef(const glm::dvec3& ue) const { + return this->_geoTransforms.TransformUnrealToEcef( + glm::dvec3(CesiumActors::getWorldOrigin4D(this)), + ue); +} + +FVector ACesiumGeoreference::TransformUnrealToEcef(const FVector& ue) const { + glm::dvec3 ecef = this->_geoTransforms.TransformUnrealToEcef( + glm::dvec3(CesiumActors::getWorldOrigin4D(this)), + glm::dvec3(ue.X, ue.Y, ue.Z)); + return FVector(ecef.x, ecef.y, ecef.z); +} + +glm::dquat ACesiumGeoreference::TransformRotatorUnrealToEastSouthUp( + const glm::dquat& UeRotator, + const glm::dvec3& UeLocation) const { + return this->_geoTransforms.TransformRotatorUnrealToEastSouthUp( + glm::dvec3(CesiumActors::getWorldOrigin4D(this)), + UeRotator, + UeLocation); +} + +FRotator ACesiumGeoreference::TransformRotatorUnrealToEastSouthUp( + const FRotator& UERotator, + const FVector& ueLocation) const { + glm::dquat q = TransformRotatorUnrealToEastSouthUp( + VecMath::createQuaternion(UERotator.Quaternion()), + VecMath::createVector3D(ueLocation)); + return VecMath::createRotator(q); +} + +glm::dquat ACesiumGeoreference::TransformRotatorEastSouthUpToUnreal( + const glm::dquat& EsuRotator, + const glm::dvec3& UeLocation) const { + return this->_geoTransforms.TransformRotatorEastSouthUpToUnreal( + glm::dvec3(CesiumActors::getWorldOrigin4D(this)), + EsuRotator, + UeLocation); +} + +FRotator ACesiumGeoreference::TransformRotatorEastSouthUpToUnreal( + const FRotator& EsuRotator, + const FVector& ueLocation) const { + glm::dquat q = TransformRotatorEastSouthUpToUnreal( + VecMath::createQuaternion(EsuRotator.Quaternion()), + VecMath::createVector3D(ueLocation)); + return VecMath::createRotator(q); +} + +glm::dmat3 +ACesiumGeoreference::ComputeEastSouthUpToUnreal(const glm::dvec3& ue) const { + return _geoTransforms.ComputeEastSouthUpToUnreal( + glm::dvec3(CesiumActors::getWorldOrigin4D(this)), + ue); +} + +FMatrix +ACesiumGeoreference::ComputeEastSouthUpToUnreal(const FVector& ue) const { + glm::dmat3 esuToUe = this->_geoTransforms.ComputeEastSouthUpToUnreal( + glm::dvec3(CesiumActors::getWorldOrigin4D(this)), + glm::dvec3(ue.X, ue.Y, ue.Z)); + return VecMath::createMatrix(esuToUe); +} + +glm::dmat3 +ACesiumGeoreference::ComputeEastNorthUpToEcef(const glm::dvec3& ecef) const { + return _geoTransforms.ComputeEastNorthUpToEcef(ecef); +} + +FMatrix +ACesiumGeoreference::ComputeEastNorthUpToEcef(const FVector& ecef) const { + glm::dmat3 enuToEcef = this->_geoTransforms.ComputeEastNorthUpToEcef( + glm::dvec3(ecef.X, ecef.Y, ecef.Z)); + return VecMath::createMatrix(enuToEcef); +} + +/** + * Private Helper Functions + */ + +void ACesiumGeoreference::_setGeoreferenceOrigin( + double targetLongitude, + double targetLatitude, + double targetHeight) { + this->OriginLongitude = targetLongitude; + this->OriginLatitude = targetLatitude; + this->OriginHeight = targetHeight; + + this->UpdateGeoreference(); +} + +void ACesiumGeoreference::_jumpToLevel(const FCesiumSubLevel& level) { + this->_setGeoreferenceOrigin( + level.LevelLongitude, + level.LevelLatitude, + level.LevelHeight); +} + +// TODO: should consider raycasting the WGS84 ellipsoid instead. The Unreal +// raycast seems to be inaccurate at glancing angles, perhaps due to the large +// single-precision distances. +#if WITH_EDITOR +void ACesiumGeoreference::_lineTraceViewportMouse( + const bool ShowTrace, + bool& Success, + FHitResult& HitResult) const { + HitResult = FHitResult(); + Success = false; + + UWorld* world = this->GetWorld(); + + FViewport* pViewport = GEditor->GetActiveViewport(); + FViewportClient* pViewportClient = pViewport->GetClient(); + FEditorViewportClient* pEditorViewportClient = + static_cast<FEditorViewportClient*>(pViewportClient); + + if (!world || !pEditorViewportClient || + !pEditorViewportClient->Viewport->HasFocus()) { + return; + } + + FViewportCursorLocation cursor = + pEditorViewportClient->GetCursorWorldLocationFromMousePos(); + + const FVector& viewLoc = cursor.GetOrigin(); + const FVector& viewDir = cursor.GetDirection(); + + // TODO (low prio, because this whole function is preliminary) : + // This radius should probably be taken from the ellipsoid + const double earthRadiusCm = 637100000.0; + FVector lineEnd = viewLoc + viewDir * earthRadiusCm; + + static const FName LineTraceSingleName(TEXT("LevelEditorLineTrace")); + if (ShowTrace) { + world->DebugDrawTraceTag = LineTraceSingleName; + } else { + world->DebugDrawTraceTag = NAME_None; + } + + FCollisionQueryParams CollisionParams(LineTraceSingleName); + + FCollisionObjectQueryParams ObjectParams = + FCollisionObjectQueryParams(ECC_WorldStatic); + ObjectParams.AddObjectTypesToQuery(ECC_WorldDynamic); + ObjectParams.AddObjectTypesToQuery(ECC_Pawn); + ObjectParams.AddObjectTypesToQuery(ECC_Visibility); + + if (world->LineTraceSingleByObjectType( + HitResult, + viewLoc, + lineEnd, + ObjectParams, + CollisionParams)) { + Success = true; + } +} +#endif + +ULevelStreaming* +ACesiumGeoreference::_findLevelStreamingByName(const FString& name) { + UWorld* pWorld = this->GetWorld(); + const TArray<ULevelStreaming*>& levels = pWorld->GetStreamingLevels(); + const FString& streamingLevelPrefix = pWorld->StreamingLevelsPrefix; + + ULevelStreaming* const* ppStreamedLevel = + levels.FindByPredicate([&name, pWorld](ULevelStreaming* pStreamedLevel) { + return longPackageNameToCesiumName( + pWorld, + pStreamedLevel->GetWorldAssetPackageName()) == name; + }); + + if (ppStreamedLevel == nullptr) { + return nullptr; + } else { + return *ppStreamedLevel; + } +} + +FCesiumSubLevel* ACesiumGeoreference::_findCesiumSubLevelByName( + const FName& packageName, + bool createIfDoesNotExist) { + FString cesiumName = + longPackageNameToCesiumName(this->GetWorld(), packageName); + + FCesiumSubLevel* pCesiumLevel = this->CesiumSubLevels.FindByPredicate( + [cesiumName](const FCesiumSubLevel& level) { + return cesiumName == level.LevelName; + }); + + if (!pCesiumLevel && createIfDoesNotExist) { + // No Cesium sub-level exists, so create it now. + this->CesiumSubLevels.Add(FCesiumSubLevel{ + cesiumName, + true, + this->OriginLongitude, + this->OriginLatitude, + this->OriginHeight, + 1000.0, + true}); + pCesiumLevel = &this->CesiumSubLevels.Last(); + } + + return pCesiumLevel; +} + +#if WITH_EDITOR + +void ACesiumGeoreference::_onNewCurrentLevel() { + UWorld* pWorld = this->GetWorld(); + if (!pWorld) { + return; + } + + UWorldComposition* pWorldComposition = pWorld->WorldComposition; + if (!pWorldComposition) { + return; + } + + ULevel* pCurrent = pWorld->GetCurrentLevel(); + UPackage* pLevelPackage = pCurrent->GetOutermost(); + + // Find the world composition details for the new level. + WorldCompositionLevelPair worldCompositionLevelPair = + findWorldCompositionLevel(pWorldComposition, pLevelPackage->GetFName()); + + FWorldCompositionTile* pTile = worldCompositionLevelPair.pTile; + ULevelStreaming* pLevelStreaming = worldCompositionLevelPair.pLevelStreaming; + + if (!pTile || !pLevelStreaming) { + // The new level doesn't appear to participate in world composition, so + // ignore it. + return; + } + + // Find the corresponding FCesiumSubLevel, creating it if necessary. + FCesiumSubLevel* pCesiumLevel = + this->_findCesiumSubLevelByName(pLevelPackage->GetFName(), true); + + // Hide all other levels. + // I initially thought we could call handy methods like SetShouldBeVisible + // here, but I was wrong. That works ok in a game, but in the Editor + // there's a much more elaborate dance required. Rather than try to figure out + // all the steps, let's just ask the Editor to do it for us. + FWorldBrowserModule& worldBrowserModule = + FModuleManager::GetModuleChecked<FWorldBrowserModule>("WorldBrowser"); + TSharedPtr<FLevelCollectionModel> pWorldModel = + worldBrowserModule.SharedWorldModel(pWorld); + if (!pWorldModel) { + return; + } + + // Build a list of levels to hide, starting with _all_ the levels. + const FLevelModelList& allLevels = pWorldModel->GetAllLevels(); + FLevelModelList levelsToHide = allLevels; + + // Remove levels from the list that we don't want to hide for various reasons. + levelsToHide.RemoveAll( + [pCurrent, pWorldComposition](const TSharedPtr<FLevelModel>& pLevel) { + // Remove persistent levels. + if (pLevel->IsPersistent()) { + return true; + } + + // Remove the now-current level. + if (pLevel->GetLevelObject() == pCurrent) { + return true; + } + + WorldCompositionLevelPair compositionLevel = findWorldCompositionLevel( + pWorldComposition, + pLevel->GetLongPackageName()); + + // Remove levels that are not part of the world composition. + if (!compositionLevel.pLevelStreaming || !compositionLevel.pTile) { + return true; + } + + // Remove levels that Unreal Engine is handling distance-based streaming + // for. Hiding such a level that UE thinks should be shown would cause + // the level to toggle on and off continually. + if (compositionLevel.pTile->Info.Layer.DistanceStreamingEnabled) { + return true; + } + + return false; + }); + + pWorldModel->HideLevels(levelsToHide); + + // Set the georeference origin for the new level if it's enabled. + if (pCesiumLevel->Enabled) { + this->_setGeoreferenceOrigin( + pCesiumLevel->LevelLongitude, + pCesiumLevel->LevelLatitude, + pCesiumLevel->LevelHeight); + } +} + +void ACesiumGeoreference::_enableAndGeoreferenceCurrentSubLevel() { + // If a sub-level is the current one, enable it and also update the + // sub-level's location. + ULevel* pCurrent = this->GetWorld()->GetCurrentLevel(); + if (!pCurrent || pCurrent->IsPersistentLevel()) { + return; + } + + UPackage* pLevelPackage = pCurrent->GetOutermost(); + FCesiumSubLevel* pLevel = + this->_findCesiumSubLevelByName(pLevelPackage->GetFName(), false); + + if (pLevel) { + pLevel->LevelLongitude = this->OriginLongitude; + pLevel->LevelLatitude = this->OriginLatitude; + pLevel->LevelHeight = this->OriginHeight; + + pLevel->Enabled = pLevel->CanBeEnabled; + } +} + +#endif + +bool ACesiumGeoreference::_shouldManageSubLevels() const { + // Only a Georeference in the PersistentLevel should manage sub-levels. + return !this->GetLevel()->IsPersistentLevel(); +} diff --git a/Plugins/CesiumForUnreal/Source/CesiumRuntime/Private/CesiumGlobeAnchorComponent.cpp b/Plugins/CesiumForUnreal/Source/CesiumRuntime/Private/CesiumGlobeAnchorComponent.cpp new file mode 100644 index 0000000000000000000000000000000000000000..b91e772af9120c81ce11acdb2664f20e6171a272 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/CesiumRuntime/Private/CesiumGlobeAnchorComponent.cpp @@ -0,0 +1,730 @@ +// Copyright 2020-2021 CesiumGS, Inc. and Contributors + +#include "CesiumGlobeAnchorComponent.h" +#include "CesiumActors.h" +#include "CesiumCustomVersion.h" +#include "CesiumGeoreference.h" +#include "CesiumRuntime.h" +#include "CesiumTransforms.h" +#include "Components/SceneComponent.h" +#include "Engine/World.h" +#include "GameFramework/Actor.h" +#include "VecMath.h" +#include <glm/gtx/matrix_decompose.hpp> + +// 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. +// +// ## Origin Rebased +// +// * Detected by a call to `ApplyWorldOffset`. +// * Updates the Actor transform from the existing ECEF transform. +// * Ignores `AdjustOrientationForGlobeWhenMoving` because the globe position is +// not changing. + +ACesiumGeoreference* UCesiumGlobeAnchorComponent::GetGeoreference() const { + return this->Georeference; +} + +void UCesiumGlobeAnchorComponent::SetGeoreference( + ACesiumGeoreference* NewGeoreference) { + this->Georeference = NewGeoreference; + this->InvalidateResolvedGeoreference(); + this->ResolveGeoreference(); +} + +FVector UCesiumGlobeAnchorComponent::GetECEF() const { + if (!this->_actorToECEFIsValid) { + 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 VecMath::createVector(glm::dvec3(this->_actorToECEF[3])); +} + +void UCesiumGlobeAnchorComponent::MoveToECEF(const glm::dvec3& newPosition) { + this->ECEF_X = newPosition.x; + this->ECEF_Y = newPosition.y; + this->ECEF_Z = newPosition.z; + this->_applyCartesianProperties(); +} + +void UCesiumGlobeAnchorComponent::MoveToECEF(const FVector& TargetEcef) { + this->MoveToECEF(VecMath::createVector3D(TargetEcef)); +} + +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; + } + + // Compute the current local up axis of the actor (the +Z axis) + glm::dmat3 currentRotation = glm::dmat3(this->_actorToECEF); + const glm::dvec3 actorUp = glm::normalize(currentRotation[2]); + + // Compute the surface normal of the ellipsoid + const glm::dvec3 ellipsoidNormal = + this->ResolvedGeoreference->ComputeGeodeticSurfaceNormal( + VecMath::createVector3D(this->GetECEF())); + + // Find the shortest rotation to align local up with the ellipsoid normal + const glm::dquat R = glm::rotation(actorUp, ellipsoidNormal); + const glm::dmat3 alignmentRotation = glm::mat3_cast(R); + + // Compute the new actor rotation and apply it + const glm::dmat3 newRotation = alignmentRotation * currentRotation; + this->_actorToECEF = glm::dmat4( + glm::dvec4(newRotation[0], 0.0), + glm::dvec4(newRotation[1], 0.0), + glm::dvec4(newRotation[2], 0.0), + this->_actorToECEF[3]); + +#if WITH_EDITOR + // In the Editor, mark this component modified so Undo works properly. + this->Modify(); +#endif + + this->_updateActorTransformFromGlobeTransform(); +} + +void UCesiumGlobeAnchorComponent::SnapToEastSouthUp() { + 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; + } + + // Extract the translation and scale from the existing transformation. + // We assume there is no perspective or skew. + glm::dvec4 translation = this->_actorToECEF[3]; + glm::dvec3 scale = glm::dvec3( + glm::length(this->_actorToECEF[0]), + glm::length(this->_actorToECEF[1]), + glm::length(this->_actorToECEF[2])); + + // Compute the desired new orientation. + glm::dmat3 newOrientation = + this->ResolvedGeoreference->GetGeoTransforms().ComputeEastNorthUpToEcef( + glm::dvec3(translation)) * + glm::dmat3(CesiumTransforms::unrealToOrFromCesium); + + // Scale the new orientation + newOrientation[0] *= scale.x; + newOrientation[1] *= scale.y; + newOrientation[2] *= scale.z; + + // Recompose the transform. + this->_actorToECEF = glm::dmat4( + glm::dvec4(newOrientation[0], 0.0), + glm::dvec4(newOrientation[1], 0.0), + glm::dvec4(newOrientation[2], 0.0), + translation); + +#if WITH_EDITOR + // In the Editor, mark this component modified so Undo works properly. + this->Modify(); +#endif + + // Update the actor from the new globe transform + this->_updateActorTransformFromGlobeTransform(); +} + +ACesiumGeoreference* UCesiumGlobeAnchorComponent::ResolveGeoreference() { + if (IsValid(this->ResolvedGeoreference)) { + return this->ResolvedGeoreference; + } + + if (IsValid(this->Georeference)) { + this->ResolvedGeoreference = this->Georeference; + } else { + this->ResolvedGeoreference = + ACesiumGeoreference::GetDefaultGeoreference(this); + } + + if (this->ResolvedGeoreference) { + this->ResolvedGeoreference->OnGeoreferenceUpdated.AddUniqueDynamic( + this, + &UCesiumGlobeAnchorComponent::_onGeoreferenceChanged); + } + + this->_onGeoreferenceChanged(); + + return this->ResolvedGeoreference; +} + +void UCesiumGlobeAnchorComponent::InvalidateResolvedGeoreference() { + if (IsValid(this->ResolvedGeoreference)) { + this->ResolvedGeoreference->OnGeoreferenceUpdated.RemoveAll(this); + } + this->ResolvedGeoreference = nullptr; +} + +FVector UCesiumGlobeAnchorComponent::GetLongitudeLatitudeHeight() const { + if (!this->_actorToECEFIsValid || !this->ResolvedGeoreference) { + 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->ResolvedGeoreference->TransformEcefToLongitudeLatitudeHeight( + this->GetECEF()); +} + +void UCesiumGlobeAnchorComponent::MoveToLongitudeLatitudeHeight( + const glm::dvec3& TargetLongitudeLatitudeHeight) { + if (!this->_actorToECEFIsValid || !this->ResolvedGeoreference) { + UE_LOG( + LogCesium, + Error, + TEXT( + "CesiumGlobeAnchorComponent %s cannot move to a globe position because the component is not yet registered."), + *this->GetName()); + return; + } + + this->MoveToECEF( + this->ResolvedGeoreference->TransformLongitudeLatitudeHeightToEcef( + TargetLongitudeLatitudeHeight)); +} + +void UCesiumGlobeAnchorComponent::MoveToLongitudeLatitudeHeight( + const FVector& TargetLongitudeLatitudeHeight) { + return this->MoveToLongitudeLatitudeHeight( + VecMath::createVector3D(TargetLongitudeLatitudeHeight)); +} + +void UCesiumGlobeAnchorComponent::ApplyWorldOffset( + const FVector& InOffset, + bool bWorldShift) { + // By the time this is called, all of the Actor's SceneComponents (including + // its RootComponent) will already have had ApplyWorldOffset called on them. + // So the root component's transform already reflects the shifted origin. It's + // imprecise, though. + // + // Fortunately, this process does _not_ trigger the `TransformUpdated` event. + // So our _actorToECEF transform still represents the precise globe transform + // of the Actor. + // + // We simply need to convert the globe transform to a new Actor transform + // based on the updated OriginLocation. The only slightly tricky part of this + // is that the OriginLocation hasn't actually been updated yet. + UActorComponent::ApplyWorldOffset(InOffset, bWorldShift); + + const UWorld* pWorld = this->GetWorld(); + if (!IsValid(pWorld)) { + UE_LOG( + LogCesium, + Warning, + TEXT("CesiumGlobeAnchorComponent %s is not spawned in world"), + *this->GetName()); + return; + } + + // Compute the position that the world origin will have + // after the rebase, indeed by SUBTRACTING the offset + const glm::dvec3 oldWorldOriginLocation = + VecMath::createVector3D(pWorld->OriginLocation); + const glm::dvec3 offset = VecMath::createVector3D(InOffset); + const glm::dvec3 newWorldOriginLocation = oldWorldOriginLocation - offset; + + // Update the Actor transform from the globe transform with the new origin + // location explicitly provided. + this->_updateActorTransformFromGlobeTransform(newWorldOriginLocation); +} + +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; + } +} + +void UCesiumGlobeAnchorComponent::OnComponentCreated() { + Super::OnComponentCreated(); + this->_actorToECEFIsValid = false; +} + +#if WITH_EDITOR +void UCesiumGlobeAnchorComponent::PostEditChangeProperty( + FPropertyChangedEvent& PropertyChangedEvent) { + Super::PostEditChangeProperty(PropertyChangedEvent); + + if (!PropertyChangedEvent.Property) { + return; + } + + FName propertyName = PropertyChangedEvent.Property->GetFName(); + + if (propertyName == + GET_MEMBER_NAME_CHECKED(UCesiumGlobeAnchorComponent, Longitude) || + propertyName == + GET_MEMBER_NAME_CHECKED(UCesiumGlobeAnchorComponent, Latitude) || + propertyName == + GET_MEMBER_NAME_CHECKED(UCesiumGlobeAnchorComponent, Height)) { + this->_applyCartographicProperties(); + } else if ( + propertyName == + GET_MEMBER_NAME_CHECKED(UCesiumGlobeAnchorComponent, ECEF_X) || + propertyName == + GET_MEMBER_NAME_CHECKED(UCesiumGlobeAnchorComponent, ECEF_Y) || + propertyName == + GET_MEMBER_NAME_CHECKED(UCesiumGlobeAnchorComponent, ECEF_Z)) { + this->_applyCartesianProperties(); + } else if ( + propertyName == + GET_MEMBER_NAME_CHECKED(UCesiumGlobeAnchorComponent, Georeference)) { + this->InvalidateResolvedGeoreference(); + } +} +#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) { + if (_onTransformChangedWhileUnregistered.IsValid()) { + pOwnerRoot->TransformUpdated.Remove(_onTransformChangedWhileUnregistered); + } + pOwnerRoot->TransformUpdated.AddUObject( + this, + &UCesiumGlobeAnchorComponent::_onActorTransformChanged); + } + + // Resolve the georeference, which will also subscribe to the new georeference + // (if there is one) and call _onGeoreferenceChanged. + // This will update the actor transform with the globe position, but only if + // the globe transform is valid. + this->ResolveGeoreference(); + + // If the globe transform is not yet valid, compute it from the actor + // transform now. + if (!this->_actorToECEFIsValid) { + this->_updateGlobeTransformFromActorTransform(); + } +} + +void UCesiumGlobeAnchorComponent::OnUnregister() { + Super::OnUnregister(); + + // Unsubscribe from the ResolvedGeoreference. + this->InvalidateResolvedGeoreference(); + + // 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); + _onTransformChangedWhileUnregistered = + pOwnerRoot->TransformUpdated.AddLambda( + [this](USceneComponent*, EUpdateTransformFlags, ETeleportType) { + this->_actorToECEFIsValid = false; + }); + } +} + +void UCesiumGlobeAnchorComponent::_onActorTransformChanged( + USceneComponent* InRootComponent, + EUpdateTransformFlags UpdateTransformFlags, + ETeleportType Teleport) { + if (this->_updatingActorTransform) { + return; + } + + if (!this->ResolvedGeoreference) { + UE_LOG( + LogCesium, + Warning, + TEXT( + "CesiumGlobeAnchorComponent %s cannot update globe transform from actor transform because there is no valid Georeference."), + *this->GetName()); + return; + } + + if (!this->_actorToECEFIsValid || + !this->AdjustOrientationForGlobeWhenMoving) { + // We can't or don't want to adjust the orientation, so just compute the new + // globe transform. + this->_updateGlobeTransformFromActorTransform(); + return; + } + + // Also adjust the orientation so that the Object is still "upright" at the + // new position on the globe. + + // Store the old globe position and compute the new transform. + const glm::dvec3 oldGlobePosition = glm::dvec3(this->_actorToECEF[3]); + const glm::dmat4& newGlobeTransform = + this->_updateGlobeTransformFromActorTransform(); + + // Compute the surface normal rotation between the old and new positions. + const glm::dvec3 newGlobePosition = glm::dvec3(newGlobeTransform[3]); + const glm::dquat ellipsoidNormalRotation = + this->ResolvedGeoreference->GetGeoTransforms() + .ComputeSurfaceNormalRotationUnreal( + oldGlobePosition, + newGlobePosition); + + // Adjust the new rotation by the surface normal rotation + const glm::dquat rotation = VecMath::createQuaternion( + InRootComponent->GetComponentRotation().Quaternion()); + const glm::dquat adjustedRotation = ellipsoidNormalRotation * rotation; + +#if WITH_EDITOR + // In the Editor, mark the root component modified so Undo works properly. + InRootComponent->Modify(); +#endif + + // Set the new Actor transform, taking care not to do this recursively. + this->_updatingActorTransform = true; + InRootComponent->SetWorldRotation( + VecMath::createQuaternion(adjustedRotation), + false, + nullptr, + this->TeleportWhenUpdatingTransform ? ETeleportType::TeleportPhysics + : ETeleportType::None); + this->_updatingActorTransform = false; + + // Compute the globe transform from the updated Actor transform. + this->_updateGlobeTransformFromActorTransform(); +} + +void UCesiumGlobeAnchorComponent::_onGeoreferenceChanged() { + if (this->_actorToECEFIsValid) { + this->_updateActorTransformFromGlobeTransform(); + } +} + +const glm::dmat4& +UCesiumGlobeAnchorComponent::_updateGlobeTransformFromActorTransform() { + if (!this->ResolvedGeoreference) { + UE_LOG( + LogCesium, + Warning, + TEXT( + "CesiumGlobeAnchorComponent %s cannot update globe transform from actor transform because there is no valid Georeference."), + *this->GetName()); + this->_actorToECEFIsValid = false; + return this->_actorToECEF; + } + + const AActor* pOwner = this->GetOwner(); + if (!IsValid(pOwner)) { + UE_LOG( + LogCesium, + Warning, + TEXT("UCesiumGlobeAnchorComponent %s does not have a valid owner"), + *this->GetName()); + this->_actorToECEFIsValid = false; + return this->_actorToECEF; + } + + const 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()); + this->_actorToECEFIsValid = false; + return this->_actorToECEF; + } + + // Get the relative world transform. + glm::dmat4 actorTransform = VecMath::createMatrix4D( + pOwnerRoot->GetComponentTransform().ToMatrixWithScale()); + + // Convert to an absolute world transform + actorTransform[3] += CesiumActors::getWorldOrigin4D(pOwner); + actorTransform[3].w = 1.0; + + // Convert to ECEF + const glm::dmat4& absoluteUnrealToEcef = + this->ResolvedGeoreference->GetGeoTransforms() + .GetAbsoluteUnrealWorldToEllipsoidCenteredTransform(); + + this->_actorToECEF = absoluteUnrealToEcef * actorTransform; + this->_actorToECEFIsValid = true; + + this->_updateCartesianProperties(); + this->_updateCartographicProperties(); + +#if WITH_EDITOR + // In the Editor, mark this component modified so Undo works properly. + this->Modify(); +#endif + + return this->_actorToECEF; +} + +FTransform UCesiumGlobeAnchorComponent::_updateActorTransformFromGlobeTransform( + const std::optional<glm::dvec3>& newWorldOrigin) { + const AActor* pOwner = this->GetOwner(); + if (!IsValid(pOwner)) { + UE_LOG( + LogCesium, + Warning, + TEXT("UCesiumGlobeAnchorComponent %s does not have a valid owner"), + *this->GetName()); + return FTransform(); + } + + 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 FTransform(); + } + + if (!this->_actorToECEFIsValid) { + UE_LOG( + LogCesium, + Warning, + TEXT( + "UCesiumGlobeAnchorComponent %s cannot update Actor transform from Globe transform because the Globe transform is not known."), + *this->GetName()); + return pOwnerRoot->GetComponentTransform(); + } + + const GeoTransforms& geoTransforms = + this->ResolveGeoreference()->GetGeoTransforms(); + + // Transform ECEF to UE absolute world + const glm::dmat4& ecefToAbsoluteUnreal = + geoTransforms.GetEllipsoidCenteredToAbsoluteUnrealWorldTransform(); + glm::dmat4 actorToUnreal = ecefToAbsoluteUnreal * this->_actorToECEF; + + // Transform UE absolute world to UE relative world + actorToUnreal[3] -= newWorldOrigin ? glm::dvec4(*newWorldOrigin, 1.0) + : CesiumActors::getWorldOrigin4D(pOwner); + actorToUnreal[3].w = 1.0; + + FTransform actorTransform = FTransform(VecMath::createMatrix(actorToUnreal)); + +#if WITH_EDITOR + // In the Editor, mark the root component modified so Undo works properly. + pOwnerRoot->Modify(); +#endif + + // Set the Actor transform + this->_updatingActorTransform = true; + pOwnerRoot->SetWorldTransform( + actorTransform, + false, + nullptr, + this->TeleportWhenUpdatingTransform ? ETeleportType::TeleportPhysics + : ETeleportType::None); + this->_updatingActorTransform = false; + + return actorTransform; +} + +const glm::dmat4& UCesiumGlobeAnchorComponent::_setGlobeTransform( + const glm::dmat4& newTransform) { +#if WITH_EDITOR + // In the Editor, mark this component modified so Undo works properly. + this->Modify(); +#endif + + // If we don't yet know our globe transform, we can't update the orientation + // for globe curvature, so just replace the globe transform and we're done. + // Do the same if we don't want to update the orientation for globe curvature. + if (!this->_actorToECEFIsValid || + !this->AdjustOrientationForGlobeWhenMoving) { + this->_actorToECEF = newTransform; + this->_updateActorTransformFromGlobeTransform(); + return this->_actorToECEF; + } + + // Save the old position and apply the new transform. + const glm::dvec3 oldPosition = glm::dvec3(this->_actorToECEF[3]); + const glm::dvec3 newPosition = glm::dvec3(newTransform[3]); + + // Adjust the orientation so that the Object is still "upright" at the new + // position on the globe. + + // Compute the surface normal rotation between the old and new positions. + const glm::dquat ellipsoidNormalRotation = + this->ResolveGeoreference() + ->GetGeoTransforms() + .ComputeSurfaceNormalRotation(oldPosition, newPosition); + + // Adjust the new rotation by the surface normal rotation + glm::dmat3 newRotation = + glm::mat3_cast(ellipsoidNormalRotation) * glm::dmat3(newTransform); + this->_actorToECEF = glm::dmat4( + glm::dvec4(newRotation[0], 0.0), + glm::dvec4(newRotation[1], 0.0), + glm::dvec4(newRotation[2], 0.0), + glm::dvec4(newPosition, 1.0)); + + // Update the Actor transform from the new globe transform. + this->_updateActorTransformFromGlobeTransform(); + + return this->_actorToECEF; +} + +void UCesiumGlobeAnchorComponent::_applyCartesianProperties() { + // If we don't yet know our globe transform, compute it from the Actor + // transform now. But restore the ECEF position properties afterward. + if (!this->_actorToECEFIsValid) { + double x = this->ECEF_X; + double y = this->ECEF_Y; + double z = this->ECEF_Z; + this->_updateGlobeTransformFromActorTransform(); + this->ECEF_X = x; + this->ECEF_Y = y; + this->ECEF_Z = z; + } + + glm::dmat4 transform = this->_actorToECEF; + transform[3] = glm::dvec4(this->ECEF_X, this->ECEF_Y, this->ECEF_Z, 1.0); + this->_setGlobeTransform(transform); + + this->_updateCartographicProperties(); +} + +void UCesiumGlobeAnchorComponent::_updateCartesianProperties() { + if (!this->_actorToECEFIsValid) { + return; + } + + this->ECEF_X = this->_actorToECEF[3].x; + this->ECEF_Y = this->_actorToECEF[3].y; + this->ECEF_Z = this->_actorToECEF[3].z; +} + +void UCesiumGlobeAnchorComponent::_applyCartographicProperties() { + // If we don't yet know our globe transform, compute it from the Actor + // transform now. But restore the LLH position properties afterward. + if (!this->_actorToECEFIsValid) { + double longitude = this->Longitude; + double latitude = this->Latitude; + double height = this->Height; + this->_updateGlobeTransformFromActorTransform(); + this->Longitude = longitude; + this->Latitude = latitude; + this->Height = height; + } + + ACesiumGeoreference* pGeoreference = this->ResolveGeoreference(); + if (!pGeoreference) { + UE_LOG( + LogCesium, + Warning, + TEXT( + "The UCesiumGlobeAnchorComponent %s does not have a valid Georeference"), + *this->GetName()); + } + + glm::dmat4 transform = this->_actorToECEF; + glm::dvec3 newEcef = + pGeoreference->GetGeoTransforms().TransformLongitudeLatitudeHeightToEcef( + glm::dvec3(this->Longitude, this->Latitude, this->Height)); + transform[3] = glm::dvec4(newEcef, 1.0); + this->_setGlobeTransform(transform); + + this->_updateCartesianProperties(); +} + +void UCesiumGlobeAnchorComponent::_updateCartographicProperties() { + if (!this->_actorToECEFIsValid) { + return; + } + + ACesiumGeoreference* pGeoreference = this->ResolveGeoreference(); + if (!pGeoreference) { + UE_LOG( + LogCesium, + Warning, + TEXT( + "The UCesiumGlobeAnchorComponent %s does not have a valid Georeference"), + *this->GetName()); + } + + glm::dvec3 llh = + pGeoreference->GetGeoTransforms().TransformEcefToLongitudeLatitudeHeight( + glm::dvec3(this->_actorToECEF[3])); + + this->Longitude = llh.x; + this->Latitude = llh.y; + this->Height = llh.z; +} diff --git a/Plugins/CesiumForUnreal/Source/CesiumRuntime/Private/CesiumGltfComponent.cpp b/Plugins/CesiumForUnreal/Source/CesiumRuntime/Private/CesiumGltfComponent.cpp new file mode 100644 index 0000000000000000000000000000000000000000..5a6da4d566bda89c3fd84c38ac9c368db9a9911c --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/CesiumRuntime/Private/CesiumGltfComponent.cpp @@ -0,0 +1,2451 @@ +// Copyright 2020-2021 CesiumGS, Inc. and Contributors + +#include "CesiumGltfComponent.h" +#include "Async/Async.h" +#include "Cesium3DTilesSelection/GltfUtilities.h" +#include "Cesium3DTilesSelection/RasterOverlay.h" +#include "Cesium3DTilesSelection/RasterOverlayTile.h" +#include "CesiumCommon.h" +#include "CesiumEncodedMetadataUtility.h" +#include "CesiumFeatureIdAttribute.h" +#include "CesiumFeatureIdTexture.h" +#include "CesiumFeatureTable.h" +#include "CesiumFeatureTexture.h" +#include "CesiumFeatureTextureProperty.h" +#include "CesiumGeometry/Axis.h" +#include "CesiumGeometry/AxisTransforms.h" +#include "CesiumGeometry/Rectangle.h" +#include "CesiumGltf/AccessorView.h" +#include "CesiumGltf/ExtensionMeshPrimitiveExtFeatureMetadata.h" +#include "CesiumGltf/ExtensionModelExtFeatureMetadata.h" +#include "CesiumGltf/PropertyType.h" +#include "CesiumGltf/TextureInfo.h" +#include "CesiumGltfPrimitiveComponent.h" +#include "CesiumMaterialUserData.h" +#include "CesiumRasterOverlays.h" +#include "CesiumRuntime.h" +#include "CesiumTextureUtility.h" +#include "CesiumTransforms.h" +#include "CesiumUtility/Tracing.h" +#include "CesiumUtility/joinToString.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 "mikktspace.h" +#include <cstddef> +#include <glm/ext/matrix_transform.hpp> +#include <glm/gtc/quaternion.hpp> +#include <glm/mat3x3.hpp> +#include <iostream> + +#if WITH_EDITOR +#include "ScopedTransaction.h" +#endif + +using namespace CesiumGltf; +using namespace CesiumTextureUtility; +using namespace CesiumEncodedMetadataUtility; +using namespace CreateGltfOptions; +using namespace LoadGltfResult; + +namespace { + +// UE4 and UE5 both use single-precision vectors for meshes, but they have +// different names. +#if ENGINE_MAJOR_VERSION == 5 +using TMeshVector2 = FVector2f; +using TMeshVector3 = FVector3f; +using TMeshVector4 = FVector4f; +#else +using TMeshVector2 = FVector2D; +using TMeshVector3 = FVector; +using TMeshVector4 = FVector4; +#endif + +} // namespace + +static uint32_t nextMaterialId = 0; + +namespace { +void destroyHalfLoadedTexture( + TUniquePtr<CesiumTextureUtility::LoadedTextureResult>& pHalfLoadedTexture) { + if (pHalfLoadedTexture) { + CesiumTextureUtility::destroyHalfLoadedTexture(*pHalfLoadedTexture.Get()); + } +} +class HalfConstructedReal : public UCesiumGltfComponent::HalfConstructed { +public: + LoadModelResult loadModelResult; + + virtual ~HalfConstructedReal() { + // TODO: deal with metadata case, when metadata uses async texture creation + // path See: https://github.com/CesiumGS/cesium-unreal/issues/979 + for (LoadNodeResult& node : loadModelResult.nodeResults) { + if (node.meshResult) { + for (LoadPrimitiveResult& primitive : + node.meshResult->primitiveResults) { + destroyHalfLoadedTexture(primitive.baseColorTexture); + destroyHalfLoadedTexture(primitive.metallicRoughnessTexture); + destroyHalfLoadedTexture(primitive.normalTexture); + destroyHalfLoadedTexture(primitive.emissiveTexture); + destroyHalfLoadedTexture(primitive.occlusionTexture); + destroyHalfLoadedTexture(primitive.waterMaskTexture); + } + } + } + } +}; +} // namespace + +template <class... T> struct IsAccessorView; + +template <class T> struct IsAccessorView<T> : std::false_type {}; + +template <class T> struct IsAccessorView<AccessorView<T>> : std::true_type {}; + +template <class T> +static uint32_t updateTextureCoordinates( + const Model& model, + const MeshPrimitive& primitive, + bool duplicateVertices, + TArray<FStaticMeshBuildVertex>& vertices, + const TArray<uint32>& indices, + const std::optional<T>& texture, + std::unordered_map<uint32_t, uint32_t>& textureCoordinateMap) { + if (!texture) { + return 0; + } + + return updateTextureCoordinates( + model, + primitive, + duplicateVertices, + vertices, + indices, + "TEXCOORD_" + std::to_string(texture.value().texCoord), + textureCoordinateMap); +} + +uint32_t updateTextureCoordinates( + const Model& model, + const MeshPrimitive& primitive, + bool duplicateVertices, + TArray<FStaticMeshBuildVertex>& vertices, + const TArray<uint32>& indices, + const std::string& attributeName, + std::unordered_map<uint32_t, uint32_t>& textureCoordinateMap) { + auto uvAccessorIt = primitive.attributes.find(attributeName); + if (uvAccessorIt == primitive.attributes.end()) { + // Texture not used, texture coordinates don't matter. + return 0; + } + + int uvAccessorID = uvAccessorIt->second; + auto mapIt = textureCoordinateMap.find(uvAccessorID); + if (mapIt != textureCoordinateMap.end()) { + // Texture coordinates for this accessor are already populated. + return mapIt->second; + } + + size_t textureCoordinateIndex = textureCoordinateMap.size(); + textureCoordinateMap[uvAccessorID] = textureCoordinateIndex; + + AccessorView<TMeshVector2> uvAccessor(model, uvAccessorID); + if (uvAccessor.status() != 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<FStaticMeshBuildVertex>& vertices = + *reinterpret_cast<TArray<FStaticMeshBuildVertex>*>(Context->m_pUserData); + return vertices.Num() / 3; +} + +static int +mikkGetNumVertsOfFace(const SMikkTSpaceContext* Context, const int FaceIdx) { + TArray<FStaticMeshBuildVertex>& vertices = + *reinterpret_cast<TArray<FStaticMeshBuildVertex>*>(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<FStaticMeshBuildVertex>& vertices = + *reinterpret_cast<TArray<FStaticMeshBuildVertex>*>(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<FStaticMeshBuildVertex>& vertices = + *reinterpret_cast<TArray<FStaticMeshBuildVertex>*>(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<FStaticMeshBuildVertex>& vertices = + *reinterpret_cast<TArray<FStaticMeshBuildVertex>*>(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<FStaticMeshBuildVertex>& vertices = + *reinterpret_cast<TArray<FStaticMeshBuildVertex>*>(Context->m_pUserData); + FStaticMeshBuildVertex& vertex = vertices[FaceIdx * 3 + VertIdx]; + vertex.TangentX = TMeshVector3(Tangent[0], Tangent[1], Tangent[2]); + vertex.TangentY = + BitangentSign * + TMeshVector3::CrossProduct(vertex.TangentZ, vertex.TangentX); +} + +static void computeTangentSpace(TArray<FStaticMeshBuildVertex>& 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 computeFlatNormals( + const TArray<uint32_t>& indices, + TArray<FStaticMeshBuildVertex>& vertices) { + // Compute flat normals + for (int i = 0; i < indices.Num(); i += 3) { + FStaticMeshBuildVertex& v0 = vertices[i]; + FStaticMeshBuildVertex& v1 = vertices[i + 1]; + FStaticMeshBuildVertex& v2 = vertices[i + 2]; + + TMeshVector3 v01 = v1.Position - v0.Position; + TMeshVector3 v02 = v2.Position - v0.Position; + TMeshVector3 normal = TMeshVector3::CrossProduct(v01, v02); + + 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(); + } +} + +static TSharedPtr<Chaos::FTriangleMeshImplicitObject, ESPMode::ThreadSafe> +BuildChaosTriangleMeshes( + const TArray<FStaticMeshBuildVertex>& vertexData, + const TArray<uint32>& indices); + +static const Material defaultMaterial; +static const MaterialPBRMetallicRoughness defaultPbrMetallicRoughness; + +struct ColorVisitor { + bool duplicateVertices; + TArray<FStaticMeshBuildVertex>& StaticMeshBuildVertices; + const TArray<uint32>& indices; + + bool operator()(AccessorView<nullptr_t>&& invalidView) { return false; } + + template <typename TColorView> bool operator()(TColorView&& colorView) { + if (colorView.status() != 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 <typename TElement> + static bool + convertColor(const AccessorTypes::VEC3<TElement>& 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 <typename TElement> + static bool + convertColor(const AccessorTypes::VEC4<TElement>& 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 <typename T> static bool convertColor(const T& color, FColor& out) { + return false; + } + + template <typename T> + static bool convertElement(const T& color, uint8_t& out) { + return false; + } +}; + +template <class T> +static TUniquePtr<CesiumTextureUtility::LoadedTextureResult> loadTexture( + CesiumGltf::Model& model, + const std::optional<T>& gltfTexture, + bool sRGB) { + if (!gltfTexture || gltfTexture.value().index < 0 || + gltfTexture.value().index >= model.textures.size()) { + if (gltfTexture && gltfTexture.value().index >= 0) { + UE_LOG( + LogCesium, + Warning, + TEXT("Texture index must be less than %d, but is %d"), + model.textures.size(), + gltfTexture.value().index); + } + return nullptr; + } + + const Texture& texture = model.textures[gltfTexture.value().index]; + + return loadTextureAnyThreadPart(model, texture, sRGB); +} + +static void applyWaterMask( + Model& model, + const 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<int32_t>( + waterMaskTextureIdIt->second.getInt64OrDefault(-1)); + 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); + } +} + +static FCesiumMetadataPrimitive +loadMetadataPrimitive(const Model& model, const MeshPrimitive& primitive) { + + // NOTE: will have a deprecation period after which this function should no + // longer rely on model, only primitive. + + const ExtensionMeshPrimitiveExtFeatureMetadata* pMetadata = + primitive.getExtension<ExtensionMeshPrimitiveExtFeatureMetadata>(); + if (!pMetadata) { + return FCesiumMetadataPrimitive(); + } + + const ExtensionModelExtFeatureMetadata* pModelMetadata = + model.getExtension<ExtensionModelExtFeatureMetadata>(); + if (!pModelMetadata) { + return FCesiumMetadataPrimitive{}; + } + + // This will change to no longer require the model-level extension + return FCesiumMetadataPrimitive( + model, + primitive, + *pMetadata, + *pModelMetadata); +} + +static void updateTextureCoordinatesForMetadata( + const Model& model, + const MeshPrimitive& primitive, + bool duplicateVertices, + TArray<FStaticMeshBuildVertex>& vertices, + const TArray<uint32>& indices, + const EncodedMetadata& encodedMetadata, + const EncodedMetadataPrimitive& encodedPrimitiveMetadata, + const TArray<FCesiumFeatureIdAttribute>& featureIdAttributes, + TMap<FString, uint32_t>& metadataTextureCoordinateParameters, + std::unordered_map<uint32_t, uint32_t>& textureCoordinateMap) { + + TRACE_CPUPROFILER_EVENT_SCOPE(Cesium::UpdateTextureCoordinatesForMetadata) + + for (const EncodedFeatureIdTexture& encodedFeatureIdTexture : + encodedPrimitiveMetadata.encodedFeatureIdTextures) { + metadataTextureCoordinateParameters.Emplace( + encodedFeatureIdTexture.baseName + "UV", + updateTextureCoordinates( + model, + primitive, + duplicateVertices, + vertices, + indices, + "TEXCOORD_" + + std::to_string( + encodedFeatureIdTexture.textureCoordinateAttributeId), + textureCoordinateMap)); + } + + for (const FString& featureTextureName : + encodedPrimitiveMetadata.featureTextureNames) { + const EncodedFeatureTexture* pEncodedFeatureTexture = + encodedMetadata.encodedFeatureTextures.Find(featureTextureName); + if (pEncodedFeatureTexture) { + for (const EncodedFeatureTextureProperty& encodedProperty : + pEncodedFeatureTexture->properties) { + metadataTextureCoordinateParameters.Emplace( + encodedProperty.baseName + "UV", + updateTextureCoordinates( + model, + primitive, + duplicateVertices, + vertices, + indices, + "TEXCOORD_" + std::to_string( + encodedProperty.textureCoordinateAttributeId), + textureCoordinateMap)); + } + } + } + + const ExtensionMeshPrimitiveExtFeatureMetadata* pMetadata = + primitive.getExtension<ExtensionMeshPrimitiveExtFeatureMetadata>(); + + if (pMetadata) { + for (const EncodedFeatureIdAttribute& encodedFeatureIdAttribute : + encodedPrimitiveMetadata.encodedFeatureIdAttributes) { + const FCesiumFeatureIdAttribute& featureIdAttribute = + featureIdAttributes[encodedFeatureIdAttribute.index]; + + int32_t attribute = featureIdAttribute.getAttributeIndex(); + uint32_t textureCoordinateIndex = textureCoordinateMap.size(); + textureCoordinateMap[attribute] = textureCoordinateIndex; + metadataTextureCoordinateParameters.Emplace( + encodedFeatureIdAttribute.name, + textureCoordinateIndex); + + int64 vertexCount = + UCesiumFeatureIdAttributeBlueprintLibrary::GetVertexCount( + 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<float>( + UCesiumFeatureIdAttributeBlueprintLibrary:: + GetFeatureIDForVertex(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<float>( + UCesiumFeatureIdAttributeBlueprintLibrary:: + GetFeatureIDForVertex(featureIdAttribute, i)); + vertex.UVs[textureCoordinateIndex] = TMeshVector2(featureId, 0.0f); + } else { + vertex.UVs[textureCoordinateIndex] = TMeshVector2(0.0f, 0.0f); + } + } + } + } + } +} + +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()); +} + +} // namespace + +template <class TIndexAccessor> +static void loadPrimitive( + LoadPrimitiveResult& primitiveResult, + const glm::dmat4x4& transform, + const CreatePrimitiveOptions& options, + const Accessor& positionAccessor, + const AccessorView<TMeshVector3>& positionView, + const TIndexAccessor& indicesView) { + + TRACE_CPUPROFILER_EVENT_SCOPE(Cesium::loadPrimitive<T>) + + Model& model = *options.pMeshOptions->pNodeOptions->pModelOptions->pModel; + const Mesh& mesh = *options.pMeshOptions->pMesh; + const MeshPrimitive& primitive = *options.pPrimitive; + + if (primitive.mode != MeshPrimitive::Mode::TRIANGLES && + primitive.mode != MeshPrimitive::Mode::TRIANGLE_STRIP) { + // TODO: add support for primitive types other than triangles. + 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 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 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() != AccessorViewStatus::Valid) { + UE_LOG( + LogCesium, + Warning, + TEXT("%s: Invalid position buffer"), + UTF8_TO_TCHAR(name.c_str())); + return; + } + + if constexpr (IsAccessorView<TIndexAccessor>::value) { + if (indicesView.status() != AccessorViewStatus::Valid) { + UE_LOG( + LogCesium, + Warning, + TEXT("%s: Invalid indices buffer"), + UTF8_TO_TCHAR(name.c_str())); + return; + } + } + + auto normalAccessorIt = primitive.attributes.find("NORMAL"); + AccessorView<TMeshVector3> normalAccessor; + bool hasNormals = false; + if (normalAccessorIt != primitive.attributes.end()) { + int normalAccessorID = normalAccessorIt->second; + normalAccessor = AccessorView<TMeshVector3>(model, normalAccessorID); + hasNormals = normalAccessor.status() == AccessorViewStatus::Valid; + if (!hasNormals) { + UE_LOG( + LogCesium, + Warning, + TEXT( + "%s: Invalid normal buffer. Flat normal will be auto-generated instead"), + UTF8_TO_TCHAR(name.c_str())); + } + } + + int materialID = primitive.material; + const Material& material = + materialID >= 0 && materialID < model.materials.size() + ? model.materials[materialID] + : defaultMaterial; + const MaterialPBRMetallicRoughness& pbrMetallicRoughness = + material.pbrMetallicRoughness ? material.pbrMetallicRoughness.value() + : defaultPbrMetallicRoughness; + + bool hasNormalMap = material.normalTexture.has_value(); + if (hasNormalMap) { + const Texture* pTexture = + Model::getSafe(&model.textures, material.normalTexture->index); + hasNormalMap = pTexture != nullptr && + Model::getSafe(&model.images, pTexture->source) != nullptr; + } + + bool needsTangents = + hasNormalMap || + options.pMeshOptions->pNodeOptions->pModelOptions->alwaysIncludeTangents; + + bool hasTangents = false; + auto tangentAccessorIt = primitive.attributes.find("TANGENT"); + AccessorView<TMeshVector4> tangentAccessor; + if (tangentAccessorIt != primitive.attributes.end()) { + int tangentAccessorID = tangentAccessorIt->second; + tangentAccessor = AccessorView<TMeshVector4>(model, tangentAccessorID); + hasTangents = tangentAccessor.status() == 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<FStaticMeshRenderData> RenderData = + MakeUnique<FStaticMeshRenderData>(); + RenderData->AllocateLODResources(1); + + FStaticMeshLODResources& LODResources = RenderData->LODResources[0]; + + { + TRACE_CPUPROFILER_EVENT_SCOPE(Cesium::ComputeAABB) + + const std::vector<double>& min = positionAccessor.min; + const std::vector<double>& max = positionAccessor.max; + glm::dvec3 minPosition{std::numeric_limits<double>::max()}; + glm::dvec3 maxPosition{std::numeric_limits<double>::lowest()}; + if (min.size() != 3 || max.size() != 3) { + for (int32_t i = 0; i < positionView.size(); ++i) { + minPosition.x = glm::min<double>(minPosition.x, positionView[i].X); + minPosition.y = glm::min<double>(minPosition.y, positionView[i].Y); + minPosition.z = glm::min<double>(minPosition.z, positionView[i].Z); + + maxPosition.x = glm::max<double>(maxPosition.x, positionView[i].X); + maxPosition.y = glm::max<double>(maxPosition.y, positionView[i].Y); + maxPosition.z = glm::max<double>(maxPosition.z, positionView[i].Z); + } + } else { + minPosition = glm::dvec3(min[0], min[1], min[2]); + maxPosition = glm::dvec3(max[0], max[1], max[2]); + } + +#if ENGINE_MAJOR_VERSION >= 5 + FBox aaBox( + FVector3d(minPosition.x, minPosition.y, minPosition.z), + FVector3d(maxPosition.x, maxPosition.y, maxPosition.z)); +#else + FBox aaBox( + FVector(minPosition.x, minPosition.y, minPosition.z), + FVector(maxPosition.x, maxPosition.y, maxPosition.z)); +#endif + + aaBox.GetCenterAndExtents( + RenderData->Bounds.Origin, + RenderData->Bounds.BoxExtent); + RenderData->Bounds.SphereRadius = 0.0f; + } + + TArray<uint32> indices; + if (primitive.mode == MeshPrimitive::Mode::TRIANGLES) { + TRACE_CPUPROFILER_EVENT_SCOPE(Cesium::CopyIndices) + indices.SetNum(static_cast<TArray<uint32>::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<TArray<uint32>::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 duplicateVertices = !hasNormals || (needsTangents && !hasTangents); + + TArray<FStaticMeshBuildVertex> StaticMeshBuildVertices; + StaticMeshBuildVertices.SetNum( + duplicateVertices ? indices.Num() + : static_cast<int>(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]; + vertex.Position = positionView[vertexIndex]; + 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]; + vertex.Position = positionView[i]; + 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<uint32_t, uint32_t>& textureCoordinateMap = + primitiveResult.textureCoordinateMap; + + { + 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, + textureCoordinateMap); + primitiveResult.textureCoordinateParameters + ["metallicRoughnessTextureCoordinateIndex"] = updateTextureCoordinates( + model, + primitive, + duplicateVertices, + StaticMeshBuildVertices, + indices, + pbrMetallicRoughness.metallicRoughnessTexture, + textureCoordinateMap); + primitiveResult + .textureCoordinateParameters["normalTextureCoordinateIndex"] = + updateTextureCoordinates( + model, + primitive, + duplicateVertices, + StaticMeshBuildVertices, + indices, + material.normalTexture, + textureCoordinateMap); + primitiveResult + .textureCoordinateParameters["occlusionTextureCoordinateIndex"] = + updateTextureCoordinates( + model, + primitive, + duplicateVertices, + StaticMeshBuildVertices, + indices, + material.occlusionTexture, + textureCoordinateMap); + primitiveResult + .textureCoordinateParameters["emissiveTextureCoordinateIndex"] = + updateTextureCoordinates( + model, + primitive, + duplicateVertices, + StaticMeshBuildVertices, + indices, + material.emissiveTexture, + textureCoordinateMap); + + 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, + textureCoordinateMap); + } else { + primitiveResult.overlayTextureCoordinateIDToUVIndex[i] = 0; + } + } + } + + primitiveResult.Metadata = loadMetadataPrimitive(model, primitive); + + const FMetadataDescription* pEncodedMetadataDescription = + options.pMeshOptions->pNodeOptions->pModelOptions + ->pEncodedMetadataDescription; + if (pEncodedMetadataDescription) { + primitiveResult.EncodedMetadata = encodeMetadataPrimitiveAnyThreadPart( + *pEncodedMetadataDescription, + primitiveResult.Metadata); + } + + updateTextureCoordinatesForMetadata( + model, + primitive, + duplicateVertices, + StaticMeshBuildVertices, + indices, + options.pMeshOptions->pNodeOptions->pHalfConstructedModelResult + ->EncodedMetadata, + primitiveResult.EncodedMetadata, + UCesiumMetadataPrimitiveBlueprintLibrary::GetFeatureIdAttributes( + primitiveResult.Metadata), + primitiveResult.metadataTextureCoordinateParameters, + textureCoordinateMap); + + // 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); + vertex.TangentZ = normalAccessor[vertexIndex]; + } + } 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); + vertex.TangentZ = normalAccessor[i]; + } + } + } else { + TRACE_CPUPROFILER_EVENT_SCOPE(Cesium::ComputeFlatNormals) + computeFlatNormals(indices, 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 = tangent; + 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.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) + LODResources.VertexBuffers.PositionVertexBuffer.Init( + StaticMeshBuildVertices, + false); + + FColorVertexBuffer& ColorVertexBuffer = + LODResources.VertexBuffers.ColorVertexBuffer; + if (hasVertexColors) { + ColorVertexBuffer.Init(StaticMeshBuildVertices, false); + } + + LODResources.VertexBuffers.StaticMeshVertexBuffer.Init( + StaticMeshBuildVertices, + textureCoordinateMap.size() == 0 ? 1 : textureCoordinateMap.size(), + false); + } + +#if ENGINE_MAJOR_VERSION == 5 + FStaticMeshSectionArray& Sections = LODResources.Sections; +#else + FStaticMeshLODResources::FStaticMeshSectionArray& Sections = + LODResources.Sections; +#endif + + FStaticMeshSection& section = Sections.AddDefaulted_GetRef(); + section.bEnableCollision = true; + + section.NumTriangles = indices.Num() / 3; + section.FirstIndex = 0; + section.MinVertexIndex = 0; + section.MaxVertexIndex = StaticMeshBuildVertices.Num() - 1; + section.bEnableCollision = true; + section.bCastShadow = true; + + // Note that we're reversing the order of the indices, because the change + // from the glTF right-handed to the Unreal left-handed coordinate system + // reverses the winding order. + // Note also that we don't want to just flip the index buffer, since that + // will change the order of the faces. + if (duplicateVertices) { + TRACE_CPUPROFILER_EVENT_SCOPE(Cesium::ReverseWindingOrder) + for (int32 i = 2; i < indices.Num(); i += 3) { + indices[i - 2] = i; + indices[i - 1] = i - 1; + indices[i] = i - 2; + } + } else { + TRACE_CPUPROFILER_EVENT_SCOPE(Cesium::ReverseWindingOrder) + for (int32 i = 2; i < indices.Num(); i += 3) { + std::swap(indices[i - 2], indices[i]); + } + } + + { + TRACE_CPUPROFILER_EVENT_SCOPE(Cesium::SetIndices) + LODResources.IndexBuffer.SetIndices( + indices, + StaticMeshBuildVertices.Num() >= std::numeric_limits<uint16>::max() + ? EIndexBufferStride::Type::Force32Bit + : EIndexBufferStride::Type::Force16Bit); + } + + LODResources.bHasDepthOnlyIndices = false; + LODResources.bHasReversedIndices = false; + LODResources.bHasReversedDepthOnlyIndices = false; +#if ENGINE_MAJOR_VERSION < 5 + LODResources.bHasAdjacencyInfo = false; +#endif + + primitiveResult.pModel = &model; + primitiveResult.pMeshPrimitive = &primitive; + primitiveResult.RenderData = std::move(RenderData); + primitiveResult.transform = transform; + primitiveResult.pMaterial = &material; + + section.MaterialIndex = 0; + + primitiveResult.pCollisionMesh = nullptr; + + if (StaticMeshBuildVertices.Num() != 0 && indices.Num() != 0) { + if (options.pMeshOptions->pNodeOptions->pModelOptions + ->createPhysicsMeshes) { + TRACE_CPUPROFILER_EVENT_SCOPE(Cesium::ChaosCook) + primitiveResult.pCollisionMesh = + BuildChaosTriangleMeshes(StaticMeshBuildVertices, indices); + } + } + + // load primitive metadata + primitiveResult.Metadata = loadMetadataPrimitive(model, primitive); +} + +static void loadIndexedPrimitive( + LoadPrimitiveResult& primitiveResult, + const glm::dmat4x4& transform, + const CreatePrimitiveOptions& options, + const Accessor& positionAccessor, + const AccessorView<TMeshVector3>& positionView) { + + const Model& model = + *options.pMeshOptions->pNodeOptions->pModelOptions->pModel; + const MeshPrimitive& primitive = *options.pPrimitive; + + const Accessor& indexAccessorGltf = model.accessors[primitive.indices]; + if (indexAccessorGltf.componentType == Accessor::ComponentType::BYTE) { + AccessorView<int8_t> indexAccessor(model, primitive.indices); + loadPrimitive( + primitiveResult, + transform, + options, + positionAccessor, + positionView, + indexAccessor); + } else if ( + indexAccessorGltf.componentType == + Accessor::ComponentType::UNSIGNED_BYTE) { + AccessorView<uint8_t> indexAccessor(model, primitive.indices); + loadPrimitive( + primitiveResult, + transform, + options, + positionAccessor, + positionView, + indexAccessor); + } else if ( + indexAccessorGltf.componentType == Accessor::ComponentType::SHORT) { + AccessorView<int16_t> indexAccessor(model, primitive.indices); + loadPrimitive( + primitiveResult, + transform, + options, + positionAccessor, + positionView, + indexAccessor); + } else if ( + indexAccessorGltf.componentType == + Accessor::ComponentType::UNSIGNED_SHORT) { + AccessorView<uint16_t> indexAccessor(model, primitive.indices); + loadPrimitive( + primitiveResult, + transform, + options, + positionAccessor, + positionView, + indexAccessor); + } else if ( + indexAccessorGltf.componentType == + Accessor::ComponentType::UNSIGNED_INT) { + AccessorView<uint32_t> indexAccessor(model, primitive.indices); + loadPrimitive( + primitiveResult, + transform, + options, + positionAccessor, + positionView, + indexAccessor); + } +} + +static void loadPrimitive( + LoadPrimitiveResult& result, + const glm::dmat4x4& transform, + const CreatePrimitiveOptions& options) { + TRACE_CPUPROFILER_EVENT_SCOPE(Cesium::loadPrimitive) + + const Model& model = + *options.pMeshOptions->pNodeOptions->pModelOptions->pModel; + const MeshPrimitive& primitive = *options.pPrimitive; + + 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 Accessor* pPositionAccessor = + Model::getSafe(&model.accessors, positionAccessorID); + if (!pPositionAccessor) { + // Position accessor does not exist, so ignore this primitive. + return; + } + + AccessorView<TMeshVector3> positionView(model, *pPositionAccessor); + + if (primitive.indices < 0 || primitive.indices >= model.accessors.size()) { + std::vector<uint32_t> 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); + } else { + loadIndexedPrimitive( + result, + transform, + options, + *pPositionAccessor, + positionView); + } +} + +static void loadMesh( + std::optional<LoadMeshResult>& result, + const glm::dmat4x4& transform, + const CreateMeshOptions& options) { + + TRACE_CPUPROFILER_EVENT_SCOPE(Cesium::loadMesh) + + const Model& model = *options.pNodeOptions->pModelOptions->pModel; + const Mesh& mesh = *options.pMesh; + + result = LoadMeshResult(); + result->primitiveResults.reserve(mesh.primitives.size()); + for (const CesiumGltf::MeshPrimitive& primitive : mesh.primitives) { + CreatePrimitiveOptions primitiveOptions = {&options, &*result, &primitive}; + auto& primitiveResult = result->primitiveResults.emplace_back(); + loadPrimitive(primitiveResult, transform, primitiveOptions); + + // if it doesn't have render data, then it can't be loaded + if (!primitiveResult.RenderData) { + result->primitiveResults.pop_back(); + } + } +} + +static void loadNode( + std::vector<LoadNodeResult>& loadNodeResults, + const glm::dmat4x4& transform, + const CreateNodeOptions& options) { + + TRACE_CPUPROFILER_EVENT_SCOPE(Cesium::loadNode) + + static constexpr std::array<double, 16> 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}; + + const Model& model = *options.pModelOptions->pModel; + const Node& node = *options.pNode; + + LoadNodeResult& result = loadNodeResults.emplace_back(); + + glm::dmat4x4 nodeTransform = transform; + + const std::vector<double>& 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()) { + CreateMeshOptions meshOptions = {&options, &result, &model.meshes[meshId]}; + loadMesh(result.meshResult, nodeTransform, meshOptions); + } + + 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); + } + } +} + +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 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::AxisTransforms::Y_UP_TO_Z_UP; + return; + } + const CesiumUtility::JsonValue& gltfUpAxis = gltfUpAxisIt->second; + int gltfUpAxisValue = static_cast<int>(gltfUpAxis.getSafeNumberOrDefault(1)); + if (gltfUpAxisValue == static_cast<int>(CesiumGeometry::Axis::X)) { + rootTransform *= CesiumGeometry::AxisTransforms::X_UP_TO_Z_UP; + } else if (gltfUpAxisValue == static_cast<int>(CesiumGeometry::Axis::Y)) { + rootTransform *= CesiumGeometry::AxisTransforms::Y_UP_TO_Z_UP; + } else if (gltfUpAxisValue == static_cast<int>(CesiumGeometry::Axis::Z)) { + // No transform required + } else { + UE_LOG( + LogCesium, + VeryVerbose, + TEXT("Unknown gltfUpAxis value: {}"), + gltfUpAxisValue); + } +} +} // namespace + +static void loadModelAnyThreadPart( + LoadModelResult& result, + const glm::dmat4x4& transform, + const CreateModelOptions& options) { + TRACE_CPUPROFILER_EVENT_SCOPE(Cesium::loadModelAnyThreadPart) + + const Model& model = *options.pModel; + + const ExtensionModelExtFeatureMetadata* pMetadataExtension = + model.getExtension<ExtensionModelExtFeatureMetadata>(); + if (pMetadataExtension) { + result.Metadata = FCesiumMetadataModel(model, *pMetadataExtension); + if (options.pEncodedMetadataDescription) { + result.EncodedMetadata = encodeMetadataAnyThreadPart( + *options.pEncodedMetadataDescription, + result.Metadata); + } + } + + glm::dmat4x4 rootTransform = transform; + + { + rootTransform = Cesium3DTilesSelection::GltfUtilities::applyRtcCenter( + model, + rootTransform); + applyGltfUpAxisTransform(model, rootTransform); + } + + if (model.scene >= 0 && model.scene < model.scenes.size()) { + // Show the default scene + const Scene& defaultScene = model.scenes[model.scene]; + for (int nodeId : defaultScene.nodes) { + CreateNodeOptions nodeOptions = {&options, &result, &model.nodes[nodeId]}; + loadNode(result.nodeResults, rootTransform, nodeOptions); + } + } else if (model.scenes.size() > 0) { + // There's no default, so show the first scene + const Scene& defaultScene = model.scenes[0]; + for (int nodeId : defaultScene.nodes) { + CreateNodeOptions nodeOptions = {&options, &result, &model.nodes[nodeId]}; + loadNode(result.nodeResults, rootTransform, nodeOptions); + } + } else if (model.nodes.size() > 0) { + // No scenes at all, use the first node as the root node. + CreateNodeOptions nodeOptions = {&options, &result, &model.nodes[0]}; + loadNode(result.nodeResults, rootTransform, nodeOptions); + } else if (model.meshes.size() > 0) { + // No nodes either, show all the meshes. + for (const Mesh& mesh : model.meshes) { + CreateNodeOptions dummyNodeOptions = {&options, &result, nullptr}; + LoadNodeResult& dummyNodeResult = result.nodeResults.emplace_back(); + CreateMeshOptions meshOptions = { + &dummyNodeOptions, + &dummyNodeResult, + &mesh}; + loadMesh(dummyNodeResult.meshResult, rootTransform, meshOptions); + } + } +} + +bool applyTexture( + const CesiumGltf::Model& model, + UMaterialInstanceDynamic* pMaterial, + const FMaterialParameterInfo& info, + CesiumTextureUtility::LoadedTextureResult* pLoadedTexture) { + UTexture2D* pTexture = + CesiumTextureUtility::loadTextureGameThreadPart(model, pLoadedTexture); + if (!pTexture) { + return false; + } + + pMaterial->SetTextureParameterValueByInfo(info, pTexture); + + return true; +} + +static void SetGltfParameterValues( + const CesiumGltf::Model& model, + LoadPrimitiveResult& loadResult, + const Material& material, + const 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<float>(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<float>(pbr.metallicFactor)); + pMaterial->SetScalarParameterValueByInfo( + FMaterialParameterInfo("roughnessFactor", association, index), + static_cast<float>(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()); + + 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( + const CesiumGltf::Model& model, + LoadPrimitiveResult& loadResult, + UMaterialInstanceDynamic* pMaterial, + EMaterialParameterAssociation association, + int32 index) { + pMaterial->SetScalarParameterValueByInfo( + FMaterialParameterInfo("OnlyLand", association, index), + static_cast<float>(loadResult.onlyLand)); + pMaterial->SetScalarParameterValueByInfo( + FMaterialParameterInfo("OnlyWater", association, index), + static_cast<float>(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 SetMetadataFeatureTableParameterValues( + const EncodedMetadataFeatureTable& encodedFeatureTable, + UMaterialInstanceDynamic* pMaterial, + EMaterialParameterAssociation association, + int32 index) { + for (const EncodedMetadataProperty& encodedProperty : + encodedFeatureTable.encodedProperties) { + + pMaterial->SetTextureParameterValueByInfo( + FMaterialParameterInfo(FName(encodedProperty.name), association, index), + encodedProperty.pTexture->pTexture.Get()); + } +} + +static void SetMetadataParameterValues( + const CesiumGltf::Model& model, + UCesiumGltfComponent& gltfComponent, + LoadPrimitiveResult& loadResult, + UMaterialInstanceDynamic* pMaterial, + EMaterialParameterAssociation association, + int32 index) { + + /** + * TODO: Write down this convention somewhere more permanent / accessible. + * + * The following is the naming convention for encoded metadata: + * + * Feature Id Textures: + * - Base: "FIT_<feature table name>_"... + * - Texture: ..."TX" + * - Texture Coordinate Index: ..."UV" + * - Channel Mask: ..."CM" + * + * Feature Id Attributes: + * - Texture Coordinate Index (feature ids are encoded into UVs): + * "FA_<feature table name>" + * + * Feature Texture Properties: + * - Base: "FTX_<feature texture name>_<property name>_"... + * - Texture: ..."TX" + * - Texture Coordinate Index: ..."UV" + * - Swizzle: ..."SW" + * + * Encoded Feature Table Properties: + * - Encoded Property Table: + * "FTB_<feature table name>_<property name>" + */ + + if (!encodeMetadataPrimitiveGameThreadPart(loadResult.EncodedMetadata)) { + return; + } + + for (const auto& textureCoordinateSet : + loadResult.metadataTextureCoordinateParameters) { + pMaterial->SetScalarParameterValueByInfo( + FMaterialParameterInfo( + FName(textureCoordinateSet.Key), + association, + index), + textureCoordinateSet.Value); + } + + for (const FString& featureTextureName : + loadResult.EncodedMetadata.featureTextureNames) { + EncodedFeatureTexture* pEncodedFeatureTexture = + gltfComponent.EncodedMetadata.encodedFeatureTextures.Find( + featureTextureName); + + if (pEncodedFeatureTexture) { + for (EncodedFeatureTextureProperty& encodedProperty : + pEncodedFeatureTexture->properties) { + + pMaterial->SetTextureParameterValueByInfo( + FMaterialParameterInfo( + FName(encodedProperty.baseName + "TX"), + association, + index), + encodedProperty.pTexture->pTexture.Get()); + + pMaterial->SetVectorParameterValueByInfo( + FMaterialParameterInfo( + FName(encodedProperty.baseName + "SW"), + association, + index), + FLinearColor( + encodedProperty.channelOffsets[0], + encodedProperty.channelOffsets[1], + encodedProperty.channelOffsets[2], + encodedProperty.channelOffsets[3])); + } + } + } + + for (EncodedFeatureIdTexture& encodedFeatureIdTexture : + loadResult.EncodedMetadata.encodedFeatureIdTextures) { + + pMaterial->SetTextureParameterValueByInfo( + FMaterialParameterInfo( + FName(encodedFeatureIdTexture.baseName + "TX"), + association, + index), + encodedFeatureIdTexture.pTexture->pTexture.Get()); + + 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 EncodedMetadataFeatureTable* pEncodedFeatureTable = + gltfComponent.EncodedMetadata.encodedFeatureTables.Find( + encodedFeatureIdTexture.featureTableName); + + if (pEncodedFeatureTable) { + SetMetadataFeatureTableParameterValues( + *pEncodedFeatureTable, + pMaterial, + association, + index); + } + } + + for (const EncodedFeatureIdAttribute& encodedFeatureIdAttribute : + loadResult.EncodedMetadata.encodedFeatureIdAttributes) { + const EncodedMetadataFeatureTable* pEncodedFeatureTable = + gltfComponent.EncodedMetadata.encodedFeatureTables.Find( + encodedFeatureIdAttribute.featureTableName); + + if (pEncodedFeatureTable) { + SetMetadataFeatureTableParameterValues( + *pEncodedFeatureTable, + pMaterial, + association, + index); + } + } +} + +static void loadPrimitiveGameThreadPart( + const CesiumGltf::Model& model, + UCesiumGltfComponent* pGltf, + LoadPrimitiveResult& loadResult, + const glm::dmat4x4& cesiumToUnrealTransform, + const Cesium3DTilesSelection::BoundingVolume& boundingVolume) { + TRACE_CPUPROFILER_EVENT_SCOPE(Cesium::LoadPrimitive) + + FName meshName = createSafeName(loadResult.name, ""); + UCesiumGltfPrimitiveComponent* pMesh = + NewObject<UCesiumGltfPrimitiveComponent>(pGltf, meshName); + pMesh->overlayTextureCoordinateIDToUVIndex = + loadResult.overlayTextureCoordinateIDToUVIndex; + pMesh->textureCoordinateMap = std::move(loadResult.textureCoordinateMap); + pMesh->HighPrecisionNodeTransform = loadResult.transform; + pMesh->UpdateTransformFromCesium(cesiumToUnrealTransform); + + pMesh->bUseDefaultCollision = false; + pMesh->SetCollisionObjectType(ECollisionChannel::ECC_WorldStatic); + pMesh->SetFlags( + RF_Transient | RF_DuplicateTransient | RF_TextExportTransient); + pMesh->pModel = loadResult.pModel; + pMesh->pMeshPrimitive = loadResult.pMeshPrimitive; + pMesh->boundingVolume = boundingVolume; + pMesh->SetRenderCustomDepth(pGltf->CustomDepthParameters.RenderCustomDepth); + pMesh->SetCustomDepthStencilWriteMask( + pGltf->CustomDepthParameters.CustomDepthStencilWriteMask); + pMesh->SetCustomDepthStencilValue( + pGltf->CustomDepthParameters.CustomDepthStencilValue); + + UStaticMesh* pStaticMesh = NewObject<UStaticMesh>(pMesh, meshName); + pMesh->SetStaticMesh(pStaticMesh); + + pStaticMesh->SetFlags( + RF_Transient | RF_DuplicateTransient | RF_TextExportTransient); + pStaticMesh->NeverStream = true; + +#if ENGINE_MAJOR_VERSION == 4 && ENGINE_MINOR_VERSION < 27 + // UE 4.26 or earlier + pStaticMesh->bIsBuiltAtRuntime = true; + pStaticMesh->RenderData = std::move(loadResult.RenderData); +#elif ENGINE_MAJOR_VERSION == 4 + // UE 4.27 or later + pStaticMesh->SetIsBuiltAtRuntime(true); + pStaticMesh->SetRenderData(std::move(loadResult.RenderData)); +#else + // UE 5 + pStaticMesh->SetRenderData(std::move(loadResult.RenderData)); +#endif + + const Material& material = + loadResult.pMaterial ? *loadResult.pMaterial : defaultMaterial; + + const MaterialPBRMetallicRoughness& pbr = + material.pbrMetallicRoughness ? material.pbrMetallicRoughness.value() + : defaultPbrMetallicRoughness; + + const FName ImportedSlotName( + *(TEXT("CesiumMaterial") + FString::FromInt(nextMaterialId++))); + + const auto is_in_blend_mode = [](auto& result) { + return !!result.pMaterial && result.pMaterial->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 && + pbr.baseColorFactor[3] < 0.996) // 1. - 1. / 256. + ? pGltf->BaseMaterialWithTranslucency + : pGltf->BaseMaterial; +#else + UMaterialInterface* pBaseMaterial = + (loadResult.onlyWater || !loadResult.onlyLand) + ? pGltf->BaseMaterialWithWater + : (is_in_blend_mode(loadResult) && pbr.baseColorFactor.size() > 3 && + pbr.baseColorFactor[3] < 0.996) // 1. - 1. / 256. + ? pGltf->BaseMaterialWithTranslucency + : pGltf->BaseMaterial; +#endif + + UMaterialInstanceDynamic* 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<UMaterialInstance>(pBaseMaterial); + UCesiumMaterialUserData* pCesiumData = + pBaseAsMaterialInstance + ? pBaseAsMaterialInstance->GetAssetUserData<UCesiumMaterialUserData>() + : nullptr; + + // If possible and necessary, attach the CesiumMaterialUserData now. +#if WITH_EDITORONLY_DATA + if (pBaseAsMaterialInstance && !pCesiumData) { + const FStaticParameterSet& parameters = + pBaseAsMaterialInstance->GetStaticParameters(); + +#if ENGINE_MAJOR_VERSION >= 5 + bool hasLayers = parameters.bHasMaterialLayers; +#else + const TArray<FStaticMaterialLayersParameter>& layerParameters = + parameters.MaterialLayersParameters; + const FStaticMaterialLayersParameter* pCesiumLayers = + layerParameters.FindByPredicate( + [](const FStaticMaterialLayersParameter& layerParameter) { + return layerParameter.ParameterInfo.Name == "Cesium"; + }); + bool hasLayers = pCesiumLayers != nullptr; +#endif + + if (hasLayers) { +#if WITH_EDITOR + FScopedTransaction transaction( + FText::FromString("Add Cesium User Data to Material")); + pBaseAsMaterialInstance->Modify(); +#endif + pCesiumData = NewObject<UCesiumMaterialUserData>( + pBaseAsMaterialInstance, + NAME_None, + RF_Public); + 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 metadataIndex = pCesiumData->LayerNames.Find("Metadata"); + if (metadataIndex >= 0) { + SetMetadataParameterValues( + model, + *pGltf, + loadResult, + pMaterial, + EMaterialParameterAssociation::LayerParameter, + metadataIndex); + } + } + + pMesh->Metadata = std::move(loadResult.Metadata); + pMesh->EncodedMetadata = std::move(loadResult.EncodedMetadata); + + pMaterial->TwoSided = true; + + pStaticMesh->AddMaterial(pMaterial); + + pStaticMesh->InitResources(); + + // Set up RenderData bounds and LOD data + pStaticMesh->CalculateExtendedBounds(); + +#if ENGINE_MAJOR_VERSION == 4 && ENGINE_MINOR_VERSION < 27 + pStaticMesh->RenderData->ScreenSize[0].Default = 1.0f; +#else + pStaticMesh->GetRenderData()->ScreenSize[0].Default = 1.0f; +#endif + pStaticMesh->CreateBodySetup(); + + UBodySetup* pBodySetup = pMesh->GetBodySetup(); + + // pMesh->UpdateCollisionFromStaticMesh(); + pBodySetup->CollisionTraceFlag = ECollisionTraceFlag::CTF_UseComplexAsSimple; + + if (loadResult.pCollisionMesh) { + pBodySetup->ChaosTriMeshes.Add(loadResult.pCollisionMesh); + } + + // 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; + + pMesh->SetMobility(pGltf->Mobility); + + // pMesh->bDrawMeshCollisionIfComplex = true; + // pMesh->bDrawMeshCollisionIfSimple = true; + pMesh->SetupAttachment(pGltf); + pMesh->RegisterComponent(); +} + +/*static*/ TUniquePtr<UCesiumGltfComponent::HalfConstructed> +UCesiumGltfComponent::CreateOffGameThread( + const glm::dmat4x4& Transform, + const CreateModelOptions& Options) { + auto pResult = MakeUnique<HalfConstructedReal>(); + loadModelAnyThreadPart(pResult->loadModelResult, Transform, Options); + + return pResult; +} + +/*static*/ UCesiumGltfComponent* UCesiumGltfComponent::CreateOnGameThread( + const CesiumGltf::Model& model, + AActor* pParentActor, + TUniquePtr<HalfConstructed> pHalfConstructed, + const glm::dmat4x4& cesiumToUnrealTransform, + UMaterialInterface* pBaseMaterial, + UMaterialInterface* pBaseTranslucentMaterial, + UMaterialInterface* pBaseWaterMaterial, + FCustomDepthParameters CustomDepthParameters, + const Cesium3DTilesSelection::BoundingVolume& boundingVolume) { + + TRACE_CPUPROFILER_EVENT_SCOPE(Cesium::LoadModel) + + HalfConstructedReal* pReal = + static_cast<HalfConstructedReal*>(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<UCesiumGltfComponent>(pParentActor); + Gltf->SetUsingAbsoluteLocation(true); + Gltf->SetMobility(pParentActor->GetRootComponent()->Mobility); + Gltf->SetFlags(RF_Transient | RF_DuplicateTransient | RF_TextExportTransient); + + Gltf->Metadata = std::move(pReal->loadModelResult.Metadata); + Gltf->EncodedMetadata = std::move(pReal->loadModelResult.EncodedMetadata); + + if (pBaseMaterial) { + Gltf->BaseMaterial = pBaseMaterial; + } + + if (pBaseTranslucentMaterial) { + Gltf->BaseMaterialWithTranslucency = pBaseTranslucentMaterial; + } + + if (pBaseWaterMaterial) { + Gltf->BaseMaterialWithWater = pBaseWaterMaterial; + } + + Gltf->CustomDepthParameters = CustomDepthParameters; + + encodeMetadataGameThreadPart(Gltf->EncodedMetadata); + for (LoadNodeResult& node : pReal->loadModelResult.nodeResults) { + if (node.meshResult) { + for (LoadPrimitiveResult& primitive : node.meshResult->primitiveResults) { + loadPrimitiveGameThreadPart( + model, + Gltf, + primitive, + cesiumToUnrealTransform, + boundingVolume); + } + } + } + + Gltf->SetVisibility(false, true); + Gltf->SetCollisionEnabled(ECollisionEnabled::NoCollision); + return Gltf; +} + +UCesiumGltfComponent::UCesiumGltfComponent() : USceneComponent() { + // Structure to hold one-time initialization + struct FConstructorStatics { + ConstructorHelpers::FObjectFinder<UMaterialInstance> BaseMaterial; + ConstructorHelpers::FObjectFinder<UMaterialInstance> + BaseMaterialWithTranslucency; + ConstructorHelpers::FObjectFinder<UMaterialInstance> BaseMaterialWithWater; + ConstructorHelpers::FObjectFinder<UTexture2D> 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; +} + +UCesiumGltfComponent::~UCesiumGltfComponent() { + UE_LOG(LogCesium, VeryVerbose, TEXT("~UCesiumGltfComponent")); +} + +void UCesiumGltfComponent::UpdateTransformFromCesium( + const glm::dmat4& cesiumToUnrealTransform) { + for (USceneComponent* pSceneComponent : this->GetAttachChildren()) { + UCesiumGltfPrimitiveComponent* pPrimitive = + Cast<UCesiumGltfPrimitiveComponent>(pSceneComponent); + if (pPrimitive) { + pPrimitive->UpdateTransformFromCesium(cesiumToUnrealTransform); + } + } +} + +namespace { + +template <typename Func> +void forEachPrimitiveComponent(UCesiumGltfComponent* pGltf, Func&& f) { + for (USceneComponent* pSceneComponent : pGltf->GetAttachChildren()) { + UCesiumGltfPrimitiveComponent* pPrimitive = + Cast<UCesiumGltfPrimitiveComponent>(pSceneComponent); + if (pPrimitive) { + UMaterialInstanceDynamic* pMaterial = + Cast<UMaterialInstanceDynamic>(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<UMaterialInstance>(pBaseMaterial); + UCesiumMaterialUserData* pCesiumData = + pBaseAsMaterialInstance + ? pBaseAsMaterialInstance + ->GetAssetUserData<UCesiumMaterialUserData>() + : nullptr; + + f(pPrimitive, pMaterial, pCesiumData); + } + } +} // namespace + +} // namespace + +void UCesiumGltfComponent::AttachRasterTile( + const Cesium3DTilesSelection::Tile& tile, + const Cesium3DTilesSelection::RasterOverlayTile& rasterTile, + UTexture2D* pTexture, + const glm::dvec2& translation, + const glm::dvec2& scale, + int32 textureCoordinateID) { + +#if CESIUM_UNREAL_ENGINE_DOUBLE + FVector4 translationAndScale(translation.x, translation.y, scale.x, scale.y); +#else + FLinearColor translationAndScale( + translation.x, + translation.y, + scale.x, + scale.y); +#endif + + forEachPrimitiveComponent( + this, + [&rasterTile, pTexture, &translationAndScale, textureCoordinateID]( + UCesiumGltfPrimitiveComponent* pPrimitive, + UMaterialInstanceDynamic* pMaterial, + UCesiumMaterialUserData* pCesiumData) { + // 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); + pMaterial->SetScalarParameterValueByInfo( + FMaterialParameterInfo( + "TextureCoordinateIndex", + EMaterialParameterAssociation::LayerParameter, + i), + static_cast<float>( + pPrimitive->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<float>(pPrimitive->overlayTextureCoordinateIDToUVIndex + [textureCoordinateID])); + } + }); +} + +void UCesiumGltfComponent::DetachRasterTile( + const Cesium3DTilesSelection::Tile& tile, + const Cesium3DTilesSelection::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<UCesiumGltfPrimitiveComponent>(pSceneComponent); + if (pPrimitive) { + pPrimitive->SetCollisionEnabled(NewType); + } + } +} + +void UCesiumGltfComponent::BeginDestroy() { + destroyEncodedMetadata(this->EncodedMetadata); + Super::BeginDestroy(); +} + +void UCesiumGltfComponent::UpdateFade(float fadePercentage, bool fadingIn) { + if (!this->IsVisible()) { + return; + } + + fadePercentage = glm::clamp(fadePercentage, 0.0f, 1.0f); + + UCesiumMaterialUserData* pCesiumData = + BaseMaterial->GetAssetUserData<UCesiumMaterialUserData>(); + + if (!pCesiumData) { + return; + } + + int fadeLayerIndex = pCesiumData->LayerNames.Find("DitherFade"); + if (fadeLayerIndex < 0) { + return; + } + + for (USceneComponent* pChild : this->GetAttachChildren()) { + UCesiumGltfPrimitiveComponent* pPrimitive = + Cast<UCesiumGltfPrimitiveComponent>(pChild); + if (!pPrimitive || !pPrimitive->GetMaterials().Num()) { + continue; + } + + UMaterialInstanceDynamic* pMaterial = + Cast<UMaterialInstanceDynamic>(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 <typename TIndex> +static void fillTriangles( + TArray<Chaos::TVector<TIndex, 3>>& triangles, + const TArray<FStaticMeshBuildVertex>& vertexData, + const TArray<uint32>& indices, + int32 triangleCount) { + + triangles.Reserve(triangleCount); + + for (int32 i = 0; i < triangleCount; ++i) { + const int32 index0 = 3 * i; + triangles.Add(Chaos::TVector<int32, 3>( + indices[index0 + 1], + indices[index0], + indices[index0 + 2])); + } +} + +static TSharedPtr<Chaos::FTriangleMeshImplicitObject, ESPMode::ThreadSafe> +BuildChaosTriangleMeshes( + const TArray<FStaticMeshBuildVertex>& vertexData, + const TArray<uint32>& indices) { + + int32 vertexCount = vertexData.Num(); + int32 triangleCount = indices.Num() / 3; + + Chaos::TParticles<Chaos::FRealSingle, 3> vertices; + vertices.AddParticles(vertexCount); + + for (int32 i = 0; i < vertexCount; ++i) { + vertices.X(i) = vertexData[i].Position; + } + + TArray<uint16> materials; + materials.SetNum(triangleCount); + + TArray<int32> faceRemap; + faceRemap.SetNum(triangleCount); + + for (int32 i = 0; i < triangleCount; ++i) { + faceRemap[i] = i; + } + + TUniquePtr<TArray<int32>> pFaceRemap = MakeUnique<TArray<int32>>(faceRemap); + + if (vertexCount < TNumericLimits<uint16>::Max()) { + TArray<Chaos::TVector<uint16, 3>> triangles; + fillTriangles(triangles, vertexData, indices, triangleCount); + return MakeShared<Chaos::FTriangleMeshImplicitObject, ESPMode::ThreadSafe>( + MoveTemp(vertices), + MoveTemp(triangles), + MoveTemp(materials), + MoveTemp(pFaceRemap), + nullptr, + false); + } else { + TArray<Chaos::TVector<int32, 3>> triangles; + fillTriangles(triangles, vertexData, indices, triangleCount); + return MakeShared<Chaos::FTriangleMeshImplicitObject, ESPMode::ThreadSafe>( + MoveTemp(vertices), + MoveTemp(triangles), + MoveTemp(materials), + MoveTemp(pFaceRemap), + nullptr, + false); + } +} diff --git a/Plugins/CesiumForUnreal/Source/CesiumRuntime/Private/CesiumGltfComponent.h b/Plugins/CesiumForUnreal/Source/CesiumRuntime/Private/CesiumGltfComponent.h new file mode 100644 index 0000000000000000000000000000000000000000..12bd1f9078507b8edf7a03f59f72fcc93b79ed7d --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/CesiumRuntime/Private/CesiumGltfComponent.h @@ -0,0 +1,121 @@ +// Copyright 2020-2021 CesiumGS, Inc. and Contributors + +#pragma once + +#include "Cesium3DTilesSelection/BoundingVolume.h" +#include "CesiumEncodedMetadataUtility.h" +#include "CesiumMetadataModel.h" +#include "Components/PrimitiveComponent.h" +#include "Components/SceneComponent.h" +#include "CoreMinimal.h" +#include "CustomDepthParameters.h" +#include "Interfaces/IHttpRequest.h" +#include <glm/mat4x4.hpp> +#include <memory> +#include "CesiumGltfComponent.generated.h" + +class UMaterialInterface; +class UTexture2D; +class UStaticMeshComponent; + +namespace CreateGltfOptions { +struct CreateModelOptions; +} // namespace CreateGltfOptions + +namespace CesiumGltf { +struct Model; +} + +namespace Cesium3DTilesSelection { +class Tile; +class RasterOverlayTile; +} // namespace Cesium3DTilesSelection + +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; + }; + + static TUniquePtr<HalfConstructed> CreateOffGameThread( + const glm::dmat4x4& Transform, + const CreateGltfOptions::CreateModelOptions& Options); + + static UCesiumGltfComponent* CreateOnGameThread( + const CesiumGltf::Model& model, + AActor* ParentActor, + TUniquePtr<HalfConstructed> HalfConstructed, + const glm::dmat4x4& CesiumToUnrealTransform, + UMaterialInterface* BaseMaterial, + UMaterialInterface* BaseTranslucentMaterial, + UMaterialInterface* BaseWaterMaterial, + FCustomDepthParameters CustomDepthParameters, + const Cesium3DTilesSelection::BoundingVolume& boundingVolume); + + UCesiumGltfComponent(); + virtual ~UCesiumGltfComponent(); + + UPROPERTY(EditAnywhere, Category = "Cesium") + UMaterialInterface* BaseMaterial; + + UPROPERTY(EditAnywhere, Category = "Cesium") + UMaterialInterface* BaseMaterialWithTranslucency; + + UPROPERTY(EditAnywhere, Category = "Cesium") + UMaterialInterface* BaseMaterialWithWater; + + UPROPERTY(EditAnywhere, Category = "Rendering") + FCustomDepthParameters CustomDepthParameters; + + FCesiumMetadataModel Metadata; + + CesiumEncodedMetadataUtility::EncodedMetadata EncodedMetadata; + + void UpdateTransformFromCesium(const glm::dmat4& CesiumToUnrealTransform); + + void AttachRasterTile( + const Cesium3DTilesSelection::Tile& Tile, + const Cesium3DTilesSelection::RasterOverlayTile& RasterTile, + UTexture2D* Texture, + const glm::dvec2& Translation, + const glm::dvec2& Scale, + int32_t TextureCoordinateID); + + void DetachRasterTile( + const Cesium3DTilesSelection::Tile& Tile, + const Cesium3DTilesSelection::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; +}; diff --git a/Plugins/CesiumForUnreal/Source/CesiumRuntime/Private/CesiumGltfPrimitiveComponent.cpp b/Plugins/CesiumForUnreal/Source/CesiumRuntime/Private/CesiumGltfPrimitiveComponent.cpp new file mode 100644 index 0000000000000000000000000000000000000000..ba0b7c526f99fb10a83fbcff83fb921a5804072e --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/CesiumRuntime/Private/CesiumGltfPrimitiveComponent.cpp @@ -0,0 +1,168 @@ +// Copyright 2020-2021 CesiumGS, Inc. and Contributors + +#include "CesiumGltfPrimitiveComponent.h" +#include "CalcBounds.h" +#include "CesiumLifetime.h" +#include "CesiumMaterialUserData.h" +#include "Engine/StaticMesh.h" +#include "Engine/Texture.h" +#include "Materials/MaterialInstanceDynamic.h" +#include "PhysicsEngine/BodySetup.h" +#include "VecMath.h" +#include <variant> + +// Sets default values for this component's properties +UCesiumGltfPrimitiveComponent::UCesiumGltfPrimitiveComponent() { + // 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; + pModel = nullptr; + pMeshPrimitive = nullptr; +} + +UCesiumGltfPrimitiveComponent::~UCesiumGltfPrimitiveComponent() {} + +void UCesiumGltfPrimitiveComponent::UpdateTransformFromCesium( + const glm::dmat4& CesiumToUnrealTransform) { + this->SetUsingAbsoluteLocation(true); + this->SetUsingAbsoluteRotation(true); + this->SetUsingAbsoluteScale(true); + + const FTransform transform = FTransform(VecMath::createMatrix( + CesiumToUnrealTransform * this->HighPrecisionNodeTransform)); + + if (this->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. + this->SetRelativeTransform( + transform, + false, + nullptr, + ETeleportType::TeleportPhysics); + } else { + // Unreall 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. + this->SetRelativeTransform_Direct(transform); + this->SetComponentToWorld(transform); + this->MarkRenderTransformDirty(); + this->SendPhysicsTransform(ETeleportType::ResetPhysics); + } +} + +namespace { + +void destroyMaterialTexture( + UMaterialInstanceDynamic* pMaterial, + const char* name, + EMaterialParameterAssociation assocation, + int32 index) { + UTexture* pTexture = nullptr; + if (pMaterial->GetTextureParameterValue( + FMaterialParameterInfo(name, assocation, index), + pTexture, + true)) { + CesiumTextureUtility::destroyTexture(pTexture); + } +} + +void destroyGltfParameterValues( + UMaterialInstanceDynamic* pMaterial, + EMaterialParameterAssociation assocation, + int32 index) { + destroyMaterialTexture(pMaterial, "baseColorTexture", assocation, index); + destroyMaterialTexture( + pMaterial, + "metallicRoughnessTexture", + assocation, + index); + destroyMaterialTexture(pMaterial, "normalTexture", assocation, index); + destroyMaterialTexture(pMaterial, "emissiveTexture", assocation, index); + destroyMaterialTexture(pMaterial, "occlusionTexture", assocation, index); +} + +void destroyWaterParameterValues( + UMaterialInstanceDynamic* pMaterial, + EMaterialParameterAssociation assocation, + int32 index) { + destroyMaterialTexture(pMaterial, "WaterMask", assocation, index); +} +} // namespace + +void UCesiumGltfPrimitiveComponent::BeginDestroy() { + // This should mirror the logic in loadPrimitiveGameThreadPart in + // CesiumGltfComponent.cpp + UMaterialInstanceDynamic* pMaterial = + Cast<UMaterialInstanceDynamic>(this->GetMaterial(0)); + if (pMaterial) { + + destroyGltfParameterValues( + pMaterial, + EMaterialParameterAssociation::GlobalParameter, + INDEX_NONE); + destroyWaterParameterValues( + pMaterial, + EMaterialParameterAssociation::GlobalParameter, + INDEX_NONE); + + UMaterialInterface* pBaseMaterial = pMaterial->Parent; + UMaterialInstance* pBaseAsMaterialInstance = + Cast<UMaterialInstance>(pBaseMaterial); + UCesiumMaterialUserData* pCesiumData = + pBaseAsMaterialInstance + ? pBaseAsMaterialInstance + ->GetAssetUserData<UCesiumMaterialUserData>() + : nullptr; + if (pCesiumData) { + destroyGltfParameterValues( + pMaterial, + EMaterialParameterAssociation::LayerParameter, + 0); + + int32 waterIndex = pCesiumData->LayerNames.Find("Water"); + if (waterIndex >= 0) { + destroyWaterParameterValues( + pMaterial, + EMaterialParameterAssociation::LayerParameter, + waterIndex); + } + } + + CesiumEncodedMetadataUtility::destroyEncodedMetadataPrimitive( + this->EncodedMetadata); + + CesiumLifetime::destroy(pMaterial); + } + + UStaticMesh* pMesh = this->GetStaticMesh(); + if (pMesh) { +#if ENGINE_MAJOR_VERSION == 4 && ENGINE_MINOR_VERSION < 27 + UBodySetup* pBodySetup = pMesh->BodySetup; +#else + UBodySetup* pBodySetup = pMesh->GetBodySetup(); +#endif + if (pBodySetup) { + CesiumLifetime::destroy(pBodySetup); + } + + CesiumLifetime::destroy(pMesh); + } + + Super::BeginDestroy(); +} + +FBoxSphereBounds UCesiumGltfPrimitiveComponent::CalcBounds( + const FTransform& LocalToWorld) const { + if (!this->boundingVolume) { + return Super::CalcBounds(LocalToWorld); + } + + return std::visit( + CalcBoundsOperation{LocalToWorld, this->HighPrecisionNodeTransform}, + *this->boundingVolume); +} diff --git a/Plugins/CesiumForUnreal/Source/CesiumRuntime/Private/CesiumGltfPrimitiveComponent.h b/Plugins/CesiumForUnreal/Source/CesiumRuntime/Private/CesiumGltfPrimitiveComponent.h new file mode 100644 index 0000000000000000000000000000000000000000..6a9e8b23f5dffc60129674e55eea8b3c69f6b8cd --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/CesiumRuntime/Private/CesiumGltfPrimitiveComponent.h @@ -0,0 +1,57 @@ +// Copyright 2020-2021 CesiumGS, Inc. and Contributors + +#pragma once + +#include "Cesium3DTilesSelection/BoundingVolume.h" +#include "CesiumEncodedMetadataUtility.h" +#include "CesiumGltf/MeshPrimitive.h" +#include "CesiumGltf/Model.h" +#include "CesiumMetadataPrimitive.h" +#include "CesiumRasterOverlays.h" +#include "Components/StaticMeshComponent.h" +#include "CoreMinimal.h" +#include <cstdint> +#include <glm/mat4x4.hpp> +#include <unordered_map> +#include "CesiumGltfPrimitiveComponent.generated.h" + +UCLASS() +class UCesiumGltfPrimitiveComponent : public UStaticMeshComponent { + GENERATED_BODY() + +public: + // Sets default values for this component's properties + UCesiumGltfPrimitiveComponent(); + virtual ~UCesiumGltfPrimitiveComponent(); + + FCesiumMetadataPrimitive Metadata; + + CesiumEncodedMetadataUtility::EncodedMetadataPrimitive EncodedMetadata; + + const CesiumGltf::Model* pModel; + + const CesiumGltf::MeshPrimitive* pMeshPrimitive; + + /** + * The double-precision transformation matrix for this glTF node. + */ + glm::dmat4x4 HighPrecisionNodeTransform; + + OverlayTextureCoordinateIDMap overlayTextureCoordinateIDToUVIndex; + std::unordered_map<uint32_t, uint32_t> textureCoordinateMap; + + std::optional<Cesium3DTilesSelection::BoundingVolume> boundingVolume; + + /** + * 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 HighPrecisionNodeTransform. + * + * @param CesiumToUnrealTransform The new transformation. + */ + void UpdateTransformFromCesium(const glm::dmat4& CesiumToUnrealTransform); + + virtual void BeginDestroy() override; + + virtual FBoxSphereBounds CalcBounds(const FTransform& LocalToWorld) const; +}; diff --git a/Plugins/CesiumForUnreal/Source/CesiumRuntime/Private/CesiumIonRasterOverlay.cpp b/Plugins/CesiumForUnreal/Source/CesiumRuntime/Private/CesiumIonRasterOverlay.cpp new file mode 100644 index 0000000000000000000000000000000000000000..7f5c616d1c9762ea2c93e8ed58c3c171f3ee61c9 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/CesiumRuntime/Private/CesiumIonRasterOverlay.cpp @@ -0,0 +1,30 @@ +// Copyright 2020-2021 CesiumGS, Inc. and Contributors + +#include "CesiumIonRasterOverlay.h" +#include "Cesium3DTilesSelection/IonRasterOverlay.h" +#include "Cesium3DTilesSelection/Tileset.h" +#include "CesiumRuntime.h" +#include "CesiumRuntimeSettings.h" + +void UCesiumIonRasterOverlay::TroubleshootToken() { + OnCesiumRasterOverlayIonTroubleshooting.Broadcast(this); +} + +std::unique_ptr<Cesium3DTilesSelection::RasterOverlay> +UCesiumIonRasterOverlay::CreateOverlay( + const Cesium3DTilesSelection::RasterOverlayOptions& options) { + if (this->IonAssetID <= 0) { + // Don't create an overlay for an invalid asset ID. + return nullptr; + } + + FString token = + this->IonAccessToken.IsEmpty() + ? GetDefault<UCesiumRuntimeSettings>()->DefaultIonAccessToken + : this->IonAccessToken; + return std::make_unique<Cesium3DTilesSelection::IonRasterOverlay>( + TCHAR_TO_UTF8(*this->MaterialLayerKey), + this->IonAssetID, + TCHAR_TO_UTF8(*token), + options); +} diff --git a/Plugins/CesiumForUnreal/Source/CesiumRuntime/Private/CesiumLifetime.cpp b/Plugins/CesiumForUnreal/Source/CesiumRuntime/Private/CesiumLifetime.cpp new file mode 100644 index 0000000000000000000000000000000000000000..183698ed6a40ed6af47f04cd95727b6096e83179 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/CesiumRuntime/Private/CesiumLifetime.cpp @@ -0,0 +1,149 @@ +// Copyright 2020-2021 CesiumGS, Inc. and Contributors + +#include "CesiumLifetime.h" +#include "Engine/StaticMesh.h" +#include "Engine/Texture2D.h" +#include "PhysicsEngine/BodySetup.h" +#include "UObject/Object.h" +#include <algorithm> + +/*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<USceneComponent*> children = pComponent->GetAttachChildren(); + for (USceneComponent* pChild : children) { + destroyComponentRecursively(pChild); + } + + 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; + } + +#if ENGINE_MAJOR_VERSION >= 5 + pObject->MarkAsGarbage(); +#else + if (!pObject->IsPendingKill()) { + pObject->MarkPendingKill(); + } +#endif + + 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<UObject> 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<UTexture2D>(pObject); + if (pTexture2D) { +#if ENGINE_MAJOR_VERSION >= 5 + FTexturePlatformData* pPlatformData = pTexture2D->GetPlatformData(); + pTexture2D->SetPlatformData(nullptr); + delete pPlatformData; +#else + delete pTexture2D->PlatformData; + pTexture2D->PlatformData = nullptr; +#endif + } + + UStaticMesh* pMesh = Cast<UStaticMesh>(pObject); + if (pMesh) { +#if ENGINE_MAJOR_VERSION >= 5 || \ + (ENGINE_MAJOR_VERSION == 4 && ENGINE_MINOR_VERSION >= 27) + pMesh->SetRenderData(nullptr); +#else + pMesh->RenderData.Reset(); +#endif + } + + UBodySetup* pBodySetup = Cast<UBodySetup>(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 0000000000000000000000000000000000000000..221b785e1f093d627917399e3bab41996ed1214d --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/CesiumRuntime/Private/CesiumLifetime.h @@ -0,0 +1,38 @@ +// Copyright 2020-2021 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<TWeakObjectPtr<UObject>> _pending; + TArray<TWeakObjectPtr<UObject>> _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 0000000000000000000000000000000000000000..a73d05ec0754758d04dc7df8fb868cab9aeee40a --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/CesiumRuntime/Private/CesiumMaterialUserData.cpp @@ -0,0 +1,30 @@ +// Copyright 2020-2021 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<UMaterialInstance>(this->GetOuter()); + if (pMaterial) { + const FStaticParameterSet& parameters = pMaterial->GetStaticParameters(); + + const auto& layerParameters = parameters.MaterialLayers; + + this->LayerNames.Reserve(layerParameters.Layers.Num()); + + for (int32 i = 0; i < layerParameters.Layers.Num(); ++i) { +#if ENGINE_MAJOR_VERSION == 5 && ENGINE_MINOR_VERSION == 0 + this->LayerNames.Add(layerParameters.GetLayerName(i).ToString()); +#else + this->LayerNames.Add(layerParameters.Layers[i].GetName()); +#endif + } + } +#endif +} diff --git a/Plugins/CesiumForUnreal/Source/CesiumRuntime/Private/CesiumMaterialUserData.h b/Plugins/CesiumForUnreal/Source/CesiumRuntime/Private/CesiumMaterialUserData.h new file mode 100644 index 0000000000000000000000000000000000000000..de8e3b57ff443080def771afaad05afc873eb429 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/CesiumRuntime/Private/CesiumMaterialUserData.h @@ -0,0 +1,29 @@ +// Copyright 2020-2021 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<FString> LayerNames; +}; diff --git a/Plugins/CesiumForUnreal/Source/CesiumRuntime/Private/CesiumMetadataArray.cpp b/Plugins/CesiumForUnreal/Source/CesiumRuntime/Private/CesiumMetadataArray.cpp new file mode 100644 index 0000000000000000000000000000000000000000..f5b687f99f0e7bbce67efe4ad371fadc01cabf93 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/CesiumRuntime/Private/CesiumMetadataArray.cpp @@ -0,0 +1,138 @@ +// Copyright 2020-2021 CesiumGS, Inc. and Contributors + +#include "CesiumMetadataArray.h" +#include "CesiumGltf/PropertyTypeTraits.h" +#include "CesiumMetadataConversions.h" + +ECesiumMetadataBlueprintType +UCesiumMetadataArrayBlueprintLibrary::GetBlueprintComponentType( + UPARAM(ref) const FCesiumMetadataArray& array) { + return CesiuMetadataTrueTypeToBlueprintType(array._type); +} + +ECesiumMetadataTrueType +UCesiumMetadataArrayBlueprintLibrary::GetTrueComponentType( + UPARAM(ref) const FCesiumMetadataArray& array) { + return array._type; +} + +int64 UCesiumMetadataArrayBlueprintLibrary::GetSize( + UPARAM(ref) const FCesiumMetadataArray& array) { + return std::visit([](const auto& view) { return view.size(); }, array._value); +} + +bool UCesiumMetadataArrayBlueprintLibrary::GetBoolean( + UPARAM(ref) const FCesiumMetadataArray& array, + int64 index, + bool defaultValue) { + return std::visit( + [index, defaultValue](const auto& v) -> bool { + if (index < 0 || index >= v.size()) { + return defaultValue; + } + auto value = v[index]; + return CesiumMetadataConversions<bool, decltype(value)>::convert( + value, + defaultValue); + }, + array._value); +} + +uint8 UCesiumMetadataArrayBlueprintLibrary::GetByte( + UPARAM(ref) const FCesiumMetadataArray& array, + int64 index, + uint8 defaultValue) { + return std::visit( + [index, defaultValue](const auto& v) -> uint8 { + if (index < 0 || index >= v.size()) { + return defaultValue; + } + auto value = v[index]; + return CesiumMetadataConversions<uint8, decltype(value)>::convert( + value, + defaultValue); + }, + array._value); +} + +int32 UCesiumMetadataArrayBlueprintLibrary::GetInteger( + UPARAM(ref) const FCesiumMetadataArray& array, + int64 index, + int32 defaultValue) { + return std::visit( + [index, defaultValue](const auto& v) -> int32 { + if (index < 0 || index >= v.size()) { + return defaultValue; + } + auto value = v[index]; + return CesiumMetadataConversions<int32, decltype(value)>::convert( + value, + defaultValue); + }, + array._value); +} + +int64 UCesiumMetadataArrayBlueprintLibrary::GetInteger64( + UPARAM(ref) const FCesiumMetadataArray& array, + int64 index, + int64 defaultValue) { + return std::visit( + [index, defaultValue](const auto& v) -> int64 { + if (index < 0 || index >= v.size()) { + return defaultValue; + } + auto value = v[index]; + return CesiumMetadataConversions<int64, decltype(value)>::convert( + value, + defaultValue); + }, + array._value); +} + +float UCesiumMetadataArrayBlueprintLibrary::GetFloat( + UPARAM(ref) const FCesiumMetadataArray& array, + int64 index, + float defaultValue) { + return std::visit( + [index, defaultValue](const auto& v) -> float { + if (index < 0 || index >= v.size()) { + return defaultValue; + } + auto value = v[index]; + return CesiumMetadataConversions<float, decltype(value)>::convert( + value, + defaultValue); + }, + array._value); +} + +double UCesiumMetadataArrayBlueprintLibrary::GetFloat64( + UPARAM(ref) const FCesiumMetadataArray& array, + int64 index, + double defaultValue) { + return std::visit( + [index, defaultValue](const auto& v) -> double { + auto value = v[index]; + return CesiumMetadataConversions<double, decltype(value)>::convert( + value, + defaultValue); + }, + array._value); +} + +FString UCesiumMetadataArrayBlueprintLibrary::GetString( + UPARAM(ref) const FCesiumMetadataArray& array, + int64 index, + const FString& defaultValue) { + return std::visit( + [index, defaultValue](const auto& v) -> FString { + if (index < 0 || index >= v.size()) { + return defaultValue; + } + auto value = v[index]; + return CesiumMetadataConversions<FString, decltype(value)>::convert( + value, + defaultValue); + }, + array._value); +} diff --git a/Plugins/CesiumForUnreal/Source/CesiumRuntime/Private/CesiumMetadataConversions.cpp b/Plugins/CesiumForUnreal/Source/CesiumRuntime/Private/CesiumMetadataConversions.cpp new file mode 100644 index 0000000000000000000000000000000000000000..ab0f2e383e703c025e8e320de20d5e59af6065ce --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/CesiumRuntime/Private/CesiumMetadataConversions.cpp @@ -0,0 +1,54 @@ +// Copyright 2020-2021 CesiumGS, Inc. and Contributors + +#include "CesiumMetadataConversions.h" + +ECesiumMetadataBlueprintType +CesiuMetadataTrueTypeToBlueprintType(ECesiumMetadataTrueType trueType) { + switch (trueType) { + case ECesiumMetadataTrueType::Boolean: + return ECesiumMetadataBlueprintType::Boolean; + case ECesiumMetadataTrueType::Uint8: + return ECesiumMetadataBlueprintType::Byte; + case ECesiumMetadataTrueType::Int8: + case ECesiumMetadataTrueType::Int16: + case ECesiumMetadataTrueType::Uint16: + case ECesiumMetadataTrueType::Int32: + // TODO: remove this one + case ECesiumMetadataTrueType::Uint32: + return ECesiumMetadataBlueprintType::Integer; + case ECesiumMetadataTrueType::Int64: + return ECesiumMetadataBlueprintType::Integer64; + case ECesiumMetadataTrueType::Float32: + return ECesiumMetadataBlueprintType::Float; + case ECesiumMetadataTrueType::Float64: + return ECesiumMetadataBlueprintType::Float64; + case ECesiumMetadataTrueType::Uint64: + case ECesiumMetadataTrueType::String: + return ECesiumMetadataBlueprintType::String; + case ECesiumMetadataTrueType::Array: + return ECesiumMetadataBlueprintType::Array; + default: + return ECesiumMetadataBlueprintType::None; + } +} + +ECesiumMetadataPackedGpuType +CesiumMetadataTrueTypeToDefaultPackedGpuType(ECesiumMetadataTrueType trueType) { + switch (trueType) { + case ECesiumMetadataTrueType::Boolean: + case ECesiumMetadataTrueType::Int8: // lossy or reinterpreted + case ECesiumMetadataTrueType::Uint8: + return ECesiumMetadataPackedGpuType::Uint8; + case ECesiumMetadataTrueType::Float32: + case ECesiumMetadataTrueType::Float64: // lossy + case ECesiumMetadataTrueType::Int16: + case ECesiumMetadataTrueType::Uint16: + case ECesiumMetadataTrueType::Int32: // lossy or reinterpreted + case ECesiumMetadataTrueType::Uint32: // lossy or reinterpreted + case ECesiumMetadataTrueType::Int64: // lossy + case ECesiumMetadataTrueType::Uint64: // lossy + return ECesiumMetadataPackedGpuType::Float; + default: + return ECesiumMetadataPackedGpuType::None; + } +} diff --git a/Plugins/CesiumForUnreal/Source/CesiumRuntime/Private/CesiumMetadataFeatureTable.cpp b/Plugins/CesiumForUnreal/Source/CesiumRuntime/Private/CesiumMetadataFeatureTable.cpp new file mode 100644 index 0000000000000000000000000000000000000000..0f2b15f5990a096d883283bb3bc511193a36f242 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/CesiumRuntime/Private/CesiumMetadataFeatureTable.cpp @@ -0,0 +1,141 @@ +// Copyright 2020-2021 CesiumGS, Inc. and Contributors + +#include "CesiumMetadataFeatureTable.h" +#include "CesiumGltf/MetadataFeatureTableView.h" +#include "CesiumMetadataPrimitive.h" + +namespace { + +struct FeatureIDFromAccessor_Deprecated { + int64 operator()(std::monostate) { return -1; } + + int64 operator()( + const CesiumGltf::AccessorView<CesiumGltf::AccessorTypes::SCALAR<float>>& + value) { + return static_cast<int64>(glm::round(value[vertexIdx].value[0])); + } + + template <typename T> + int64 operator()(const CesiumGltf::AccessorView<T>& value) { + return static_cast<int64>(value[vertexIdx].value[0]); + } + + int64 vertexIdx; +}; + +} // namespace + +FCesiumMetadataFeatureTable::FCesiumMetadataFeatureTable( + const CesiumGltf::Model& model, + const CesiumGltf::Accessor& featureIDAccessor, + const CesiumGltf::FeatureTable& featureTable) { + + switch (featureIDAccessor.componentType) { + case CesiumGltf::Accessor::ComponentType::BYTE: + _featureIDAccessor = + CesiumGltf::AccessorView<CesiumGltf::AccessorTypes::SCALAR<int8_t>>( + model, + featureIDAccessor); + break; + case CesiumGltf::Accessor::ComponentType::UNSIGNED_BYTE: + _featureIDAccessor = + CesiumGltf::AccessorView<CesiumGltf::AccessorTypes::SCALAR<uint8_t>>( + model, + featureIDAccessor); + break; + case CesiumGltf::Accessor::ComponentType::SHORT: + _featureIDAccessor = + CesiumGltf::AccessorView<CesiumGltf::AccessorTypes::SCALAR<int16_t>>( + model, + featureIDAccessor); + break; + case CesiumGltf::Accessor::ComponentType::UNSIGNED_SHORT: + _featureIDAccessor = + CesiumGltf::AccessorView<CesiumGltf::AccessorTypes::SCALAR<uint16_t>>( + model, + featureIDAccessor); + break; + case CesiumGltf::Accessor::ComponentType::FLOAT: + _featureIDAccessor = + CesiumGltf::AccessorView<CesiumGltf::AccessorTypes::SCALAR<float>>( + model, + featureIDAccessor); + break; + default: + break; + } + + CesiumGltf::MetadataFeatureTableView featureTableView{&model, &featureTable}; + + featureTableView.forEachProperty([&properties = _properties]( + const std::string& propertyName, + auto propertyValue) mutable { + if (propertyValue.status() == + CesiumGltf::MetadataPropertyViewStatus::Valid) { + FString key(UTF8_TO_TCHAR(propertyName.data())); + properties.Add(key, FCesiumMetadataProperty(propertyValue)); + } + }); +} + +PRAGMA_DISABLE_DEPRECATION_WARNINGS + +TMap<FString, FCesiumMetadataGenericValue> +UCesiumMetadataFeatureTableBlueprintLibrary::GetMetadataValuesForFeatureID( + UPARAM(ref) const FCesiumMetadataFeatureTable& FeatureTable, + int64 featureID) { + TMap<FString, FCesiumMetadataGenericValue> feature; + for (const auto& pair : FeatureTable._properties) { + feature.Add( + pair.Key, + UCesiumMetadataPropertyBlueprintLibrary::GetGenericValue( + pair.Value, + featureID)); + } + + return feature; +} + +TMap<FString, FString> UCesiumMetadataFeatureTableBlueprintLibrary:: + GetMetadataValuesAsStringForFeatureID( + UPARAM(ref) const FCesiumMetadataFeatureTable& FeatureTable, + int64 featureID) { + TMap<FString, FString> feature; + for (const auto& pair : FeatureTable._properties) { + feature.Add( + pair.Key, + UCesiumMetadataGenericValueBlueprintLibrary::GetString( + UCesiumMetadataPropertyBlueprintLibrary::GetGenericValue( + pair.Value, + featureID), + "")); + } + + return feature; +} + +int64 UCesiumMetadataFeatureTableBlueprintLibrary::GetNumberOfFeatures( + UPARAM(ref) const FCesiumMetadataFeatureTable& FeatureTable) { + if (FeatureTable._properties.Num() == 0) { + return 0; + } + + return UCesiumMetadataPropertyBlueprintLibrary::GetNumberOfFeatures( + FeatureTable._properties.begin().Value()); +} + +int64 UCesiumMetadataFeatureTableBlueprintLibrary::GetFeatureIDForVertex( + UPARAM(ref) const FCesiumMetadataFeatureTable& FeatureTable, + int64 vertexIdx) { + return std::visit( + FeatureIDFromAccessor_Deprecated{vertexIdx}, + FeatureTable._featureIDAccessor); +} + +const TMap<FString, FCesiumMetadataProperty>& +UCesiumMetadataFeatureTableBlueprintLibrary::GetProperties( + UPARAM(ref) const FCesiumMetadataFeatureTable& FeatureTable) { + return FeatureTable._properties; +} + +PRAGMA_ENABLE_DEPRECATION_WARNINGS diff --git a/Plugins/CesiumForUnreal/Source/CesiumRuntime/Private/CesiumMetadataGenericValue.cpp b/Plugins/CesiumForUnreal/Source/CesiumRuntime/Private/CesiumMetadataGenericValue.cpp new file mode 100644 index 0000000000000000000000000000000000000000..cf853e24354a3c91b34e58e07e8d3559d6d5c65b --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/CesiumRuntime/Private/CesiumMetadataGenericValue.cpp @@ -0,0 +1,125 @@ +// Copyright 2020-2021 CesiumGS, Inc. and Contributors + +#include "CesiumMetadataGenericValue.h" +#include "CesiumGltf/PropertyTypeTraits.h" +#include "CesiumMetadataConversions.h" + +ECesiumMetadataBlueprintType +UCesiumMetadataGenericValueBlueprintLibrary::GetBlueprintType( + UPARAM(ref) const FCesiumMetadataGenericValue& Value) { + return CesiuMetadataTrueTypeToBlueprintType(Value._type); +} + +ECesiumMetadataBlueprintType +UCesiumMetadataGenericValueBlueprintLibrary::GetBlueprintComponentType( + UPARAM(ref) const FCesiumMetadataGenericValue& Value) { + return CesiuMetadataTrueTypeToBlueprintType(Value._componentType); +} + +ECesiumMetadataTrueType +UCesiumMetadataGenericValueBlueprintLibrary::GetTrueType( + UPARAM(ref) const FCesiumMetadataGenericValue& Value) { + return Value._type; +} + +ECesiumMetadataTrueType +UCesiumMetadataGenericValueBlueprintLibrary::GetTrueComponentType( + UPARAM(ref) const FCesiumMetadataGenericValue& Value) { + return Value._componentType; +} + +bool UCesiumMetadataGenericValueBlueprintLibrary::GetBoolean( + UPARAM(ref) const FCesiumMetadataGenericValue& Value, + bool DefaultValue) { + return std::visit( + [DefaultValue](auto value) -> bool { + return CesiumMetadataConversions<bool, decltype(value)>::convert( + value, + DefaultValue); + }, + Value._value); +} + +uint8 UCesiumMetadataGenericValueBlueprintLibrary::GetByte( + UPARAM(ref) const FCesiumMetadataGenericValue& Value, + uint8 DefaultValue) { + return std::visit( + [DefaultValue](auto value) -> uint8 { + return CesiumMetadataConversions<uint8, decltype(value)>::convert( + value, + DefaultValue); + }, + Value._value); +} + +int32 UCesiumMetadataGenericValueBlueprintLibrary::GetInteger( + UPARAM(ref) const FCesiumMetadataGenericValue& Value, + int32 DefaultValue) { + return std::visit( + [DefaultValue](auto value) { + return CesiumMetadataConversions<int32, decltype(value)>::convert( + value, + DefaultValue); + }, + Value._value); +} + +int64 UCesiumMetadataGenericValueBlueprintLibrary::GetInteger64( + UPARAM(ref) const FCesiumMetadataGenericValue& Value, + int64 DefaultValue) { + return std::visit( + [DefaultValue](auto value) -> int64 { + return CesiumMetadataConversions<int64, decltype(value)>::convert( + value, + DefaultValue); + }, + Value._value); +} + +float UCesiumMetadataGenericValueBlueprintLibrary::GetFloat( + UPARAM(ref) const FCesiumMetadataGenericValue& Value, + float DefaultValue) { + return std::visit( + [DefaultValue](auto value) -> float { + return CesiumMetadataConversions<float, decltype(value)>::convert( + value, + DefaultValue); + }, + Value._value); +} + +double UCesiumMetadataGenericValueBlueprintLibrary::GetFloat64( + UPARAM(ref) const FCesiumMetadataGenericValue& Value, + double DefaultValue) { + return std::visit( + [DefaultValue](auto value) -> double { + return CesiumMetadataConversions<double, decltype(value)>::convert( + value, + DefaultValue); + }, + Value._value); +} + +FString UCesiumMetadataGenericValueBlueprintLibrary::GetString( + UPARAM(ref) const FCesiumMetadataGenericValue& Value, + const FString& DefaultValue) { + return std::visit( + [DefaultValue](auto value) -> FString { + return CesiumMetadataConversions<FString, decltype(value)>::convert( + value, + DefaultValue); + }, + Value._value); +} + +FCesiumMetadataArray UCesiumMetadataGenericValueBlueprintLibrary::GetArray( + UPARAM(ref) const FCesiumMetadataGenericValue& Value) { + return std::visit( + [](auto value) -> FCesiumMetadataArray { + if constexpr (CesiumGltf::IsMetadataArray<decltype(value)>::value) { + return FCesiumMetadataArray(value); + } + return FCesiumMetadataArray(); + }, + Value._value); +} diff --git a/Plugins/CesiumForUnreal/Source/CesiumRuntime/Private/CesiumMetadataModel.cpp b/Plugins/CesiumForUnreal/Source/CesiumRuntime/Private/CesiumMetadataModel.cpp new file mode 100644 index 0000000000000000000000000000000000000000..af669e3f1daac1e620253ebef397178ffac5ae82 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/CesiumRuntime/Private/CesiumMetadataModel.cpp @@ -0,0 +1,40 @@ +// Copyright 2020-2021 CesiumGS, Inc. and Contributors + +#include "CesiumMetadataModel.h" +#include "CesiumGltf/ExtensionModelExtFeatureMetadata.h" +#include "CesiumGltf/Model.h" + +using namespace CesiumGltf; + +FCesiumMetadataModel::FCesiumMetadataModel( + const Model& model, + const ExtensionModelExtFeatureMetadata& metadata) { + + this->_featureTables.Reserve(metadata.featureTables.size()); + for (const auto& featureTableIt : metadata.featureTables) { + this->_featureTables.Emplace( + UTF8_TO_TCHAR(featureTableIt.first.c_str()), + FCesiumFeatureTable(model, featureTableIt.second)); + } + + this->_featureTextures.Reserve(metadata.featureTextures.size()); + for (const auto& featureTextureIt : metadata.featureTextures) { + this->_featureTextures.Emplace( + UTF8_TO_TCHAR(featureTextureIt.first.c_str()), + FCesiumFeatureTexture(model, featureTextureIt.second)); + } +} + +/*static*/ +const TMap<FString, FCesiumFeatureTable>& +UCesiumMetadataModelBlueprintLibrary::GetFeatureTables( + UPARAM(ref) const FCesiumMetadataModel& MetadataModel) { + return MetadataModel._featureTables; +} + +/*static*/ +const TMap<FString, FCesiumFeatureTexture>& +UCesiumMetadataModelBlueprintLibrary::GetFeatureTextures( + UPARAM(ref) const FCesiumMetadataModel& MetadataModel) { + return MetadataModel._featureTextures; +} diff --git a/Plugins/CesiumForUnreal/Source/CesiumRuntime/Private/CesiumMetadataPrimitive.cpp b/Plugins/CesiumForUnreal/Source/CesiumRuntime/Private/CesiumMetadataPrimitive.cpp new file mode 100644 index 0000000000000000000000000000000000000000..8e6acf1151dfacd953e2c2bebc7cf98a9c804838 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/CesiumRuntime/Private/CesiumMetadataPrimitive.cpp @@ -0,0 +1,141 @@ +// Copyright 2020-2021 CesiumGS, Inc. and Contributors + +#include "CesiumMetadataPrimitive.h" +#include "CesiumGltf/ExtensionMeshPrimitiveExtFeatureMetadata.h" +#include "CesiumGltf/Model.h" + +// REMOVE AFTER DEPRECATION +#include "CesiumGltf/ExtensionModelExtFeatureMetadata.h" + +FCesiumMetadataPrimitive::FCesiumMetadataPrimitive( + const CesiumGltf::Model& model, + const CesiumGltf::MeshPrimitive& primitive, + const CesiumGltf::ExtensionMeshPrimitiveExtFeatureMetadata& metadata, + const CesiumGltf::ExtensionModelExtFeatureMetadata& modelMetadata) { + + const CesiumGltf::Accessor& indicesAccessor = + model.getSafe(model.accessors, primitive.indices); + switch (indicesAccessor.componentType) { + case CesiumGltf::Accessor::ComponentType::UNSIGNED_BYTE: + _vertexIDAccessor = + CesiumGltf::AccessorView<CesiumGltf::AccessorTypes::SCALAR<uint8_t>>( + model, + indicesAccessor); + break; + case CesiumGltf::Accessor::ComponentType::UNSIGNED_SHORT: + _vertexIDAccessor = + CesiumGltf::AccessorView<CesiumGltf::AccessorTypes::SCALAR<uint16_t>>( + model, + indicesAccessor); + break; + case CesiumGltf::Accessor::ComponentType::UNSIGNED_INT: + _vertexIDAccessor = + CesiumGltf::AccessorView<CesiumGltf::AccessorTypes::SCALAR<uint32_t>>( + model, + indicesAccessor); + break; + default: + break; + } + + for (const CesiumGltf::FeatureIDAttribute& attribute : + metadata.featureIdAttributes) { + if (attribute.featureIds.attribute) { + auto featureID = + primitive.attributes.find(attribute.featureIds.attribute.value()); + if (featureID == primitive.attributes.end()) { + continue; + } + + const CesiumGltf::Accessor* accessor = + model.getSafe<CesiumGltf::Accessor>( + &model.accessors, + featureID->second); + if (!accessor) { + continue; + } + + if (accessor->type != CesiumGltf::Accessor::Type::SCALAR) { + continue; + } + + this->_featureIdAttributes.Add(FCesiumFeatureIdAttribute( + model, + *accessor, + featureID->second, + UTF8_TO_TCHAR(attribute.featureTable.c_str()))); + + // REMOVE AFTER DEPRECATION + PRAGMA_DISABLE_DEPRECATION_WARNINGS + auto featureTableIt = + modelMetadata.featureTables.find(attribute.featureTable); + if (featureTableIt == modelMetadata.featureTables.end()) { + continue; + } + this->_featureTables_deprecated.Add((FCesiumMetadataFeatureTable( + model, + *accessor, + featureTableIt->second))); + PRAGMA_ENABLE_DEPRECATION_WARNINGS + } + } + + for (const CesiumGltf::FeatureIDTexture& featureIdTexture : + metadata.featureIdTextures) { + this->_featureIdTextures.Add( + FCesiumFeatureIdTexture(model, featureIdTexture)); + } + + this->_featureTextureNames.Reserve(metadata.featureTextures.size()); + for (const std::string& featureTextureName : metadata.featureTextures) { + this->_featureTextureNames.Emplace( + UTF8_TO_TCHAR(featureTextureName.c_str())); + } +} + +PRAGMA_DISABLE_DEPRECATION_WARNINGS +const TArray<FCesiumMetadataFeatureTable>& +UCesiumMetadataPrimitiveBlueprintLibrary::GetFeatureTables( + const FCesiumMetadataPrimitive& MetadataPrimitive) { + return MetadataPrimitive._featureTables_deprecated; +} +PRAGMA_ENABLE_DEPRECATION_WARNINGS + +const TArray<FCesiumFeatureIdAttribute>& +UCesiumMetadataPrimitiveBlueprintLibrary::GetFeatureIdAttributes( + UPARAM(ref) const FCesiumMetadataPrimitive& MetadataPrimitive) { + return MetadataPrimitive._featureIdAttributes; +} + +const TArray<FCesiumFeatureIdTexture>& +UCesiumMetadataPrimitiveBlueprintLibrary::GetFeatureIdTextures( + UPARAM(ref) const FCesiumMetadataPrimitive& MetadataPrimitive) { + return MetadataPrimitive._featureIdTextures; +} + +const TArray<FString>& +UCesiumMetadataPrimitiveBlueprintLibrary::GetFeatureTextureNames( + UPARAM(ref) const FCesiumMetadataPrimitive& MetadataPrimitive) { + return MetadataPrimitive._featureTextureNames; +} + +int64 UCesiumMetadataPrimitiveBlueprintLibrary::GetFirstVertexIDFromFaceID( + UPARAM(ref) const FCesiumMetadataPrimitive& MetadataPrimitive, + int64 faceID) { + return std::visit( + [faceID](const auto& accessor) { + int64 index = faceID * 3; + + if (accessor.status() != CesiumGltf::AccessorViewStatus::Valid) { + // No indices, so each successive face is just the next three + // vertices. + return index; + } else if (index >= accessor.size()) { + // Invalid face index. + return -1LL; + } + + return int64(accessor[index].value[0]); + }, + MetadataPrimitive._vertexIDAccessor); +} diff --git a/Plugins/CesiumForUnreal/Source/CesiumRuntime/Private/CesiumMetadataProperty.cpp b/Plugins/CesiumForUnreal/Source/CesiumRuntime/Private/CesiumMetadataProperty.cpp new file mode 100644 index 0000000000000000000000000000000000000000..f06136a0b69be5c0af102c0cd6e1c50d0f035154 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/CesiumRuntime/Private/CesiumMetadataProperty.cpp @@ -0,0 +1,201 @@ +// Copyright 2020-2021 CesiumGS, Inc. and Contributors + +#include "CesiumMetadataProperty.h" +#include "CesiumGltf/PropertyTypeTraits.h" +#include "CesiumMetadataConversions.h" + +using namespace CesiumGltf; + +ECesiumMetadataBlueprintType +UCesiumMetadataPropertyBlueprintLibrary::GetBlueprintType( + UPARAM(ref) const FCesiumMetadataProperty& Property) { + return CesiuMetadataTrueTypeToBlueprintType(Property._type); +} + +ECesiumMetadataBlueprintType +UCesiumMetadataPropertyBlueprintLibrary::GetBlueprintComponentType( + UPARAM(ref) const FCesiumMetadataProperty& Property) { + return CesiuMetadataTrueTypeToBlueprintType(Property._componentType); +} + +ECesiumMetadataTrueType UCesiumMetadataPropertyBlueprintLibrary::GetTrueType( + UPARAM(ref) const FCesiumMetadataProperty& Property) { + return Property._type; +} + +ECesiumMetadataTrueType +UCesiumMetadataPropertyBlueprintLibrary::GetTrueComponentType( + UPARAM(ref) const FCesiumMetadataProperty& Property) { + return Property._componentType; +} + +int64 UCesiumMetadataPropertyBlueprintLibrary::GetNumberOfFeatures( + UPARAM(ref) const FCesiumMetadataProperty& Property) { + return std::visit( + [](const auto& view) { return view.size(); }, + Property._property); +} + +int64 UCesiumMetadataPropertyBlueprintLibrary::GetComponentCount( + UPARAM(ref) const FCesiumMetadataProperty& Property) { + return Property._componentCount; +} + +bool UCesiumMetadataPropertyBlueprintLibrary::GetBoolean( + UPARAM(ref) const FCesiumMetadataProperty& Property, + int64 featureID, + bool defaultValue) { + return std::visit( + [featureID, defaultValue](const auto& v) -> bool { + if (featureID < 0 || featureID >= v.size()) { + return defaultValue; + } + auto value = v.get(featureID); + return CesiumMetadataConversions<bool, decltype(value)>::convert( + value, + defaultValue); + }, + Property._property); +} + +uint8 UCesiumMetadataPropertyBlueprintLibrary::GetByte( + UPARAM(ref) const FCesiumMetadataProperty& Property, + int64 featureID, + uint8 defaultValue) { + return std::visit( + [featureID, defaultValue](const auto& v) -> uint8 { + if (featureID < 0 || featureID >= v.size()) { + return defaultValue; + } + auto value = v.get(featureID); + return CesiumMetadataConversions<uint8, decltype(value)>::convert( + value, + defaultValue); + }, + Property._property); +} + +int32 UCesiumMetadataPropertyBlueprintLibrary::GetInteger( + UPARAM(ref) const FCesiumMetadataProperty& Property, + int64 featureID, + int32 defaultValue) { + return std::visit( + [featureID, defaultValue](const auto& v) -> int32 { + if (featureID < 0 || featureID >= v.size()) { + return defaultValue; + } + auto value = v.get(featureID); + return CesiumMetadataConversions<int32, decltype(value)>::convert( + value, + defaultValue); + }, + Property._property); +} + +int64 UCesiumMetadataPropertyBlueprintLibrary::GetInteger64( + UPARAM(ref) const FCesiumMetadataProperty& Property, + int64 featureID, + int64 defaultValue) { + return std::visit( + [featureID, defaultValue](const auto& v) -> int64 { + if (featureID < 0 || featureID >= v.size()) { + return defaultValue; + } + auto value = v.get(featureID); + return CesiumMetadataConversions<int64, decltype(value)>::convert( + value, + defaultValue); + }, + Property._property); +} + +float UCesiumMetadataPropertyBlueprintLibrary::GetFloat( + UPARAM(ref) const FCesiumMetadataProperty& Property, + int64 featureID, + float defaultValue) { + return std::visit( + [featureID, defaultValue](const auto& v) -> float { + if (featureID < 0 || featureID >= v.size()) { + return defaultValue; + } + auto value = v.get(featureID); + return CesiumMetadataConversions<float, decltype(value)>::convert( + value, + defaultValue); + }, + Property._property); +} + +double UCesiumMetadataPropertyBlueprintLibrary::GetFloat64( + UPARAM(ref) const FCesiumMetadataProperty& Property, + int64 featureID, + double defaultValue) { + return std::visit( + [featureID, defaultValue](const auto& v) -> double { + auto value = v.get(featureID); + return CesiumMetadataConversions<double, decltype(value)>::convert( + value, + defaultValue); + }, + Property._property); +} + +FString UCesiumMetadataPropertyBlueprintLibrary::GetString( + UPARAM(ref) const FCesiumMetadataProperty& Property, + int64 featureID, + const FString& defaultValue) { + return std::visit( + [featureID, &defaultValue](const auto& v) -> FString { + if (featureID < 0 || featureID >= v.size()) { + return defaultValue; + } + auto value = v.get(featureID); + return CesiumMetadataConversions<FString, decltype(value)>::convert( + value, + defaultValue); + }, + Property._property); +} + +FCesiumMetadataArray UCesiumMetadataPropertyBlueprintLibrary::GetArray( + UPARAM(ref) const FCesiumMetadataProperty& Property, + int64 featureID) { + return std::visit( + [featureID](const auto& v) -> FCesiumMetadataArray { + if (featureID < 0 || featureID >= v.size()) { + return FCesiumMetadataArray(); + } + auto value = v.get(featureID); + + auto createArrayView = [](const auto& array) -> FCesiumMetadataArray { + return FCesiumMetadataArray(array); + }; + + // TODO: Is this the best way? + if constexpr (CesiumGltf::IsMetadataArray<decltype(value)>::value) { + return createArrayView(value); + } + + return FCesiumMetadataArray(); + }, + Property._property); +} + +FCesiumMetadataGenericValue +UCesiumMetadataPropertyBlueprintLibrary::GetGenericValue( + UPARAM(ref) const FCesiumMetadataProperty& Property, + int64 featureID) { + return std::visit( + [featureID](const auto& view) { + if (featureID < 0 || featureID >= view.size()) { + return FCesiumMetadataGenericValue(); + } + return FCesiumMetadataGenericValue{view.get(featureID)}; + }, + Property._property); +} + +bool UCesiumMetadataPropertyBlueprintLibrary::IsNormalized( + UPARAM(ref) const FCesiumMetadataProperty& Property) { + return Property._normalized; +} diff --git a/Plugins/CesiumForUnreal/Source/CesiumRuntime/Private/CesiumMetadataUtilityBlueprintLibrary.cpp b/Plugins/CesiumForUnreal/Source/CesiumRuntime/Private/CesiumMetadataUtilityBlueprintLibrary.cpp new file mode 100644 index 0000000000000000000000000000000000000000..523eeb1fd20eff460f51af351db851f2373ace39 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/CesiumRuntime/Private/CesiumMetadataUtilityBlueprintLibrary.cpp @@ -0,0 +1,167 @@ +// Copyright 2020-2021 CesiumGS, Inc. and Contributors + +#include "CesiumMetadataUtilityBlueprintLibrary.h" +#include "CesiumFeatureIdAttribute.h" +#include "CesiumFeatureIdTexture.h" +#include "CesiumGltfComponent.h" +#include "CesiumGltfPrimitiveComponent.h" + +// REMOVE AFTER DEPRECATION +#include "CesiumMetadataFeatureTable.h" + +static FCesiumMetadataModel EmptyModelMetadata; +static FCesiumMetadataPrimitive EmptyPrimitiveMetadata; + +const FCesiumMetadataModel& +UCesiumMetadataUtilityBlueprintLibrary::GetModelMetadata( + const UPrimitiveComponent* component) { + const UCesiumGltfPrimitiveComponent* pGltfComponent = + Cast<UCesiumGltfPrimitiveComponent>(component); + + if (!IsValid(pGltfComponent)) { + return EmptyModelMetadata; + } + + const UCesiumGltfComponent* pModel = + Cast<UCesiumGltfComponent>(pGltfComponent->GetOuter()); + if (!IsValid(pModel)) { + return EmptyModelMetadata; + } + + return pModel->Metadata; +} + +const FCesiumMetadataPrimitive& +UCesiumMetadataUtilityBlueprintLibrary::GetPrimitiveMetadata( + const UPrimitiveComponent* component) { + const UCesiumGltfPrimitiveComponent* pGltfComponent = + Cast<UCesiumGltfPrimitiveComponent>(component); + if (!IsValid(pGltfComponent)) { + return EmptyPrimitiveMetadata; + } + + return pGltfComponent->Metadata; +} + +TMap<FString, FCesiumMetadataGenericValue> +UCesiumMetadataUtilityBlueprintLibrary::GetMetadataValuesForFace( + const UPrimitiveComponent* component, + int64 faceID) { + const UCesiumGltfPrimitiveComponent* pGltfComponent = + Cast<UCesiumGltfPrimitiveComponent>(component); + if (!IsValid(pGltfComponent)) { + return TMap<FString, FCesiumMetadataGenericValue>(); + } + + const UCesiumGltfComponent* pModel = + Cast<UCesiumGltfComponent>(pGltfComponent->GetOuter()); + if (!IsValid(pModel)) { + return TMap<FString, FCesiumMetadataGenericValue>(); + } + + const FCesiumMetadataModel& modelMetadata = pModel->Metadata; + const FCesiumMetadataPrimitive& primitiveMetadata = pGltfComponent->Metadata; + const TArray<FCesiumFeatureIdAttribute>& featureIdAttributes = + UCesiumMetadataPrimitiveBlueprintLibrary::GetFeatureIdAttributes( + primitiveMetadata); + if (featureIdAttributes.Num() == 0) { + return TMap<FString, FCesiumMetadataGenericValue>(); + } + + // For now, only considers the first feature + // TODO: expand to arbitrary number of features once testing data is + // available + const TMap<FString, FCesiumFeatureTable>& featureTables = + UCesiumMetadataModelBlueprintLibrary::GetFeatureTables(modelMetadata); + const FString& featureTableName = + UCesiumFeatureIdAttributeBlueprintLibrary::GetFeatureTableName( + featureIdAttributes[0]); + const FCesiumFeatureTable* pFeatureTable = + featureTables.Find(featureTableName); + if (!pFeatureTable) { + return TMap<FString, FCesiumMetadataGenericValue>(); + } + + int64 featureID = + GetFeatureIDFromFaceID(primitiveMetadata, featureIdAttributes[0], faceID); + if (featureID < 0) { + return TMap<FString, FCesiumMetadataGenericValue>(); + } + + return UCesiumFeatureTableBlueprintLibrary::GetMetadataValuesForFeatureID( + *pFeatureTable, + featureID); +} + +TMap<FString, FString> +UCesiumMetadataUtilityBlueprintLibrary::GetMetadataValuesAsStringForFace( + const UPrimitiveComponent* component, + int64 faceID) { + const UCesiumGltfPrimitiveComponent* pGltfComponent = + Cast<UCesiumGltfPrimitiveComponent>(component); + if (!IsValid(pGltfComponent)) { + return TMap<FString, FString>(); + } + + const UCesiumGltfComponent* pModel = + Cast<UCesiumGltfComponent>(pGltfComponent->GetOuter()); + if (!IsValid(pModel)) { + return TMap<FString, FString>(); + } + + const FCesiumMetadataModel& modelMetadata = pModel->Metadata; + const FCesiumMetadataPrimitive& primitiveMetadata = pGltfComponent->Metadata; + const TArray<FCesiumFeatureIdAttribute>& featureIdAttributes = + UCesiumMetadataPrimitiveBlueprintLibrary::GetFeatureIdAttributes( + primitiveMetadata); + if (featureIdAttributes.Num() == 0) { + return TMap<FString, FString>(); + } + + // For now, only considers the first feature + // TODO: expand to arbitrary number of features once testing data is + // available + const TMap<FString, FCesiumFeatureTable>& featureTables = + UCesiumMetadataModelBlueprintLibrary::GetFeatureTables(modelMetadata); + const FString& featureTableName = + UCesiumFeatureIdAttributeBlueprintLibrary::GetFeatureTableName( + featureIdAttributes[0]); + const FCesiumFeatureTable* pFeatureTable = + featureTables.Find(featureTableName); + if (!pFeatureTable) { + return TMap<FString, FString>(); + } + + int64 featureID = + GetFeatureIDFromFaceID(primitiveMetadata, featureIdAttributes[0], faceID); + if (featureID < 0) { + return TMap<FString, FString>(); + } + + return UCesiumFeatureTableBlueprintLibrary:: + GetMetadataValuesAsStringForFeatureID(*pFeatureTable, featureID); +} + +int64 UCesiumMetadataUtilityBlueprintLibrary::GetFeatureIDFromFaceID( + UPARAM(ref) const FCesiumMetadataPrimitive& Primitive, + UPARAM(ref) const FCesiumFeatureIdAttribute& FeatureIdAttribute, + int64 faceID) { + return UCesiumFeatureIdAttributeBlueprintLibrary::GetFeatureIDForVertex( + FeatureIdAttribute, + UCesiumMetadataPrimitiveBlueprintLibrary::GetFirstVertexIDFromFaceID( + Primitive, + faceID)); +} + +PRAGMA_DISABLE_DEPRECATION_WARNINGS +int64 UCesiumMetadataUtilityBlueprintLibrary::GetFeatureIDForFace( + UPARAM(ref) const FCesiumMetadataPrimitive& Primitive, + UPARAM(ref) const FCesiumMetadataFeatureTable& FeatureTable, + int64 faceID) { + return UCesiumMetadataFeatureTableBlueprintLibrary::GetFeatureIDForVertex( + FeatureTable, + UCesiumMetadataPrimitiveBlueprintLibrary::GetFirstVertexIDFromFaceID( + Primitive, + faceID)); +} +PRAGMA_ENABLE_DEPRECATION_WARNINGS diff --git a/Plugins/CesiumForUnreal/Source/CesiumRuntime/Private/CesiumPolygonRasterOverlay.cpp b/Plugins/CesiumForUnreal/Source/CesiumRuntime/Private/CesiumPolygonRasterOverlay.cpp new file mode 100644 index 0000000000000000000000000000000000000000..289071a10af496c4599e74a452ab947f39f50dc3 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/CesiumRuntime/Private/CesiumPolygonRasterOverlay.cpp @@ -0,0 +1,69 @@ +// Copyright 2020-2021 CesiumGS, Inc. and Contributors + +#include "CesiumPolygonRasterOverlay.h" +#include "Cesium3DTilesSelection/RasterizedPolygonsOverlay.h" +#include "Cesium3DTilesSelection/RasterizedPolygonsTileExcluder.h" +#include "Cesium3DTilesSelection/Tileset.h" +#include "CesiumBingMapsRasterOverlay.h" +#include "CesiumCartographicPolygon.h" + +using namespace CesiumGeospatial; +using namespace Cesium3DTilesSelection; + +UCesiumPolygonRasterOverlay::UCesiumPolygonRasterOverlay() + : UCesiumRasterOverlay() { + this->MaterialLayerKey = TEXT("Clipping"); +} + +std::unique_ptr<Cesium3DTilesSelection::RasterOverlay> +UCesiumPolygonRasterOverlay::CreateOverlay( + const Cesium3DTilesSelection::RasterOverlayOptions& options) { + std::vector<CartographicPolygon> polygons; + polygons.reserve(this->Polygons.Num()); + + for (ACesiumCartographicPolygon* pPolygon : this->Polygons) { + if (!pPolygon) { + continue; + } + + CartographicPolygon polygon = pPolygon->CreateCartographicPolygon(); + polygons.emplace_back(std::move(polygon)); + } + + return std::make_unique<Cesium3DTilesSelection::RasterizedPolygonsOverlay>( + TCHAR_TO_UTF8(*this->MaterialLayerKey), + polygons, + this->InvertSelection, + CesiumGeospatial::Ellipsoid::WGS84, + CesiumGeospatial::GeographicProjection(), + 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<RasterizedPolygonsOverlay*>(pOverlay); + assert(this->_pExcluder == nullptr); + this->_pExcluder = + std::make_shared<RasterizedPolygonsTileExcluder>(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/CesiumRasterOverlay.cpp b/Plugins/CesiumForUnreal/Source/CesiumRuntime/Private/CesiumRasterOverlay.cpp new file mode 100644 index 0000000000000000000000000000000000000000..517377f62a5a82da3a24cc9fe44368ea479d86ed --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/CesiumRuntime/Private/CesiumRasterOverlay.cpp @@ -0,0 +1,208 @@ +// Copyright 2020-2021 CesiumGS, Inc. and Contributors + +#include "CesiumRasterOverlay.h" +#include "Async/Async.h" +#include "Cesium3DTilesSelection/RasterOverlayLoadFailureDetails.h" +#include "Cesium3DTilesSelection/Tileset.h" +#include "Cesium3DTileset.h" +#include "CesiumAsync/IAssetResponse.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; + + // ... +} + +#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; + } + + Cesium3DTilesSelection::RasterOverlayOptions options{}; + 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 Cesium3DTilesSelection::RasterOverlayLoadFailureDetails& + details) { + static_assert( + uint8_t(ECesiumRasterOverlayLoadType::CesiumIon) == + uint8_t(Cesium3DTilesSelection::RasterOverlayLoadType::CesiumIon)); + static_assert( + uint8_t(ECesiumRasterOverlayLoadType::TileProvider) == + uint8_t( + Cesium3DTilesSelection::RasterOverlayLoadType::TileProvider)); + static_assert( + uint8_t(ECesiumRasterOverlayLoadType::Unknown) == + uint8_t(Cesium3DTilesSelection::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<Cesium3DTilesSelection::RasterOverlay> 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(); + 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<ACesium3DTileset>(); + 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 0000000000000000000000000000000000000000..ae58e07bfe5c8c4357709f10271f9a1c53979552 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/CesiumRuntime/Private/CesiumRasterOverlays.h @@ -0,0 +1,12 @@ +// Copyright 2020-2021 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<int32_t, maximumOverlayTextureCoordinateIDs>; diff --git a/Plugins/CesiumForUnreal/Source/CesiumRuntime/Private/CesiumRuntime.cpp b/Plugins/CesiumForUnreal/Source/CesiumRuntime/Private/CesiumRuntime.cpp new file mode 100644 index 0000000000000000000000000000000000000000..9bf40bfe5dcb0839b42b8d48a59c452c9c5e1cf8 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/CesiumRuntime/Private/CesiumRuntime.cpp @@ -0,0 +1,101 @@ +// Copyright 2020-2021 CesiumGS, Inc. and Contributors + +#include "CesiumRuntime.h" +#include "Cesium3DTilesSelection/registerAllTileContentTypes.h" +#include "CesiumAsync/CachingAssetAccessor.h" +#include "CesiumAsync/SqliteCache.h" +#include "CesiumUtility/Tracing.h" +#include "HAL/FileManager.h" +#include "HttpModule.h" +#include "Misc/Paths.h" +#include "SpdlogUnrealLoggerSink.h" +#include "UnrealAssetAccessor.h" +#include "UnrealTaskProcessor.h" +#include <CesiumAsync/AsyncSystem.h> +#include <CesiumAsync/IAssetAccessor.h> +#include <Modules/ModuleManager.h> +#include <spdlog/spdlog.h> + +#if CESIUM_TRACING_ENABLED +#include <chrono> +#endif + +#define LOCTEXT_NAMESPACE "FCesiumRuntimeModule" + +DEFINE_LOG_CATEGORY(LogCesium); + +void FCesiumRuntimeModule::StartupModule() { + Cesium3DTilesSelection::registerAllTileContentTypes(); + + std::shared_ptr<spdlog::logger> pLogger = spdlog::default_logger(); + pLogger->sinks() = {std::make_shared<SpdlogUnrealLoggerSink>()}; + + FModuleManager::Get().LoadModuleChecked(TEXT("HTTP")); + + CESIUM_TRACE_INIT( + "cesium-trace-" + + std::to_string(std::chrono::time_point_cast<std::chrono::microseconds>( + std::chrono::steady_clock::now()) + .time_since_epoch() + .count()) + + ".json"); +} + +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<UnrealTaskProcessor>()); + 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 + +const std::shared_ptr<CesiumAsync::IAssetAccessor>& getAssetAccessor() { + static std::shared_ptr<CesiumAsync::IAssetAccessor> pAssetAccessor = + std::make_shared<CesiumAsync::CachingAssetAccessor>( + spdlog::default_logger(), + std::make_shared<UnrealAssetAccessor>(), + std::make_shared<CesiumAsync::SqliteCache>( + spdlog::default_logger(), + getCacheDatabaseName())); + 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 0000000000000000000000000000000000000000..849d266bd6b18e20d2d4dd6ae8e30321e6d83337 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/CesiumRuntime/Private/CesiumRuntimeSettings.cpp @@ -0,0 +1,9 @@ +// Copyright 2020-2021 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/CesiumSunSky.cpp b/Plugins/CesiumForUnreal/Source/CesiumRuntime/Private/CesiumSunSky.cpp new file mode 100644 index 0000000000000000000000000000000000000000..e3d9dfa9b19d9c84e3fb29e63f3f486001bad290 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/CesiumRuntime/Private/CesiumSunSky.cpp @@ -0,0 +1,519 @@ +// Copyright 2020-2021 CesiumGS, Inc. and Contributors + +#include "CesiumSunSky.h" +#include "CesiumCustomVersion.h" +#include "CesiumGlobeAnchorComponent.h" +#include "CesiumRuntime.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 WGS84 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, a WGS84 +// 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 into 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() { + PrimaryActorTick.bCanEverTick = true; + + Scene = CreateDefaultSubobject<USceneComponent>(TEXT("Scene")); + SetRootComponent(Scene); + + DirectionalLight = CreateDefaultSubobject<UDirectionalLightComponent>( + TEXT("DirectionalLight")); + DirectionalLight->SetupAttachment(Scene); + DirectionalLight->Intensity = 111000.f; + DirectionalLight->LightSourceAngle = 0.5; + DirectionalLight->DynamicShadowCascades = 5; + DirectionalLight->CascadeDistributionExponent = 2.0; + DirectionalLight->DynamicShadowDistanceMovableLight = 500000.f; + +#if ENGINE_MAJOR_VERSION >= 5 + // 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); +#else + DirectionalLight->bUsedAsAtmosphereSunLight = true; +#endif + + // The location of the DirectionalLight should never matter, but by making it + // absolute we do less math when the Actor moves as a result of the + // GlobeAnchorComponent. + DirectionalLight->SetUsingAbsoluteLocation(true); + DirectionalLight->SetWorldLocation(FVector(0, 0, 0)); + + if (!SkySphereClass) { + ConstructorHelpers::FClassFinder<AActor> 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<USkyLightComponent>(TEXT("SkyLight")); + SkyLight->SetupAttachment(Scene); + SkyLight->SetMobility(EComponentMobility::Movable); + SkyLight->bRealTimeCapture = true; + SkyLight->bLowerHemisphereIsBlack = false; + SkyLight->bTransmission = true; + SkyLight->SamplesPerPixel = 2; + +#if ENGINE_MAJOR_VERSION >= 5 + SkyLight->CastRaytracedShadow = ECastRayTracedShadow::Enabled; +#else + SkyLight->bCastRaytracedShadow = true; +#endif + + // The Sky Light is fixed at the Georeference origin. + // TODO: should it follow the player? + 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<USkyAtmosphereComponent>(TEXT("SkyAtmosphere")); + SkyAtmosphere->SetupAttachment(Scene); + SkyAtmosphere->TransformMode = + ESkyAtmosphereTransformMode::PlanetCenterAtComponentTransform; + + this->GlobeAnchor = + CreateDefaultSubobject<UCesiumGlobeAnchorComponent>(TEXT("GlobeAnchor")); + this->GlobeAnchor->AdjustOrientationForGlobeWhenMoving = 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()); + + this->GlobeAnchor->MoveToECEF(glm::dvec3(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() { + if (!UseMobileRendering || !IsValid(GetWorld())) { + return; + } + + if (!IsValid(this->GetGeoreference())) { + return; + } + + // Create a new Sky Sphere Actor and anchor it to the center of the Earth. + this->SkySphereActor = GetWorld()->SpawnActor<AActor>(SkySphereClass); + + // Anchor it to the center of the Earth. + UCesiumGlobeAnchorComponent* GlobeAnchorComponent = + NewObject<UCesiumGlobeAnchorComponent>( + SkySphereActor, + TEXT("GlobeAnchor")); + this->SkySphereActor->AddInstanceComponent(GlobeAnchorComponent); + GlobeAnchorComponent->AdjustOrientationForGlobeWhenMoving = false; + GlobeAnchorComponent->SetGeoreference(this->GlobeAnchor->GetGeoreference()); + GlobeAnchorComponent->MoveToECEF(glm::dvec3(0.0, 0.0, 0.0)); + + _wantsSpawnMobileSkySphere = false; + + _setSkySphereDirectionalLight(); +} + +void ACesiumSunSky::UpdateSkySphere() { + if (!UseMobileRendering || !SkySphereActor) { + return; + } + UFunction* UpdateSkySphere = + this->SkySphereActor->FindFunction(TEXT("RefreshMaterial")); + if (UpdateSkySphere) { + this->SkySphereActor->ProcessEvent(UpdateSkySphere, NULL); + } +} + +void ACesiumSunSky::BeginPlay() { + Super::BeginPlay(); + + this->GlobeAnchor->MoveToECEF(glm::dvec3(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(); + } +} + +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(); + } +} + +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<FProperty> PropertyIterator(SkySphereClass); + PropertyIterator; + ++PropertyIterator) { + FProperty* prop = *PropertyIterator; + FName const propName = prop->GetFName(); + if (propName == TEXT("DirectionalLightComponent")) { + FObjectProperty* objectProp = CastField<FObjectProperty>(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() { + 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()->OriginLatitude, + this->GetGeoreference()->OriginLongitude, + 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); + + // Orient sun / directional light + if (this->UseLevelDirectionalLight && IsValid(this->LevelDirectionalLight) && + IsValid(this->LevelDirectionalLight->GetRootComponent())) { + this->LevelDirectionalLight->GetRootComponent()->SetWorldRotation( + newRotation); + } else { + this->DirectionalLight->SetWorldRotation(newRotation); + } + + // 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<FEditorViewportClient*>& viewportClients = + GEditor->GetAllViewportClients(); + for (FEditorViewportClient* pEditorViewportClient : viewportClients) { + if (pEditorViewportClient && + 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() { + FVector location = getViewLocation(this->GetWorld()); + glm::dvec3 llh = + this->GetGeoreference()->TransformUnrealToLongitudeLatitudeHeight( + VecMath::createVector3D(location)); + + // An atmosphere of this radius should circumscribe all Earth terrain. + double maxRadius = 6387000.0; + + if (llh.z / 1000.0 > this->CircumscribedGroundThreshold) { + this->SetSkyAtmosphereGroundRadius(this->SkyAtmosphere, maxRadius / 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 = this->GetGeoreference() + ->GetGeoTransforms() + .TransformLongitudeLatitudeHeightToEcef( + glm::dvec3(llh.x, llh.y, -100.0)); + double minRadius = glm::length(ecef); + + if (llh.z / 1000.0 < this->InscribedGroundThreshold) { + this->SetSkyAtmosphereGroundRadius( + this->SkyAtmosphere, + minRadius / 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 / 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 + if (Sky && FMath::Abs(Sky->BottomRadius - Radius) > 0.1) { + Sky->BottomRadius = Radius; + Sky->MarkRenderStateDirty(); + UE_LOG(LogCesium, Verbose, TEXT("GroundRadius now %f"), Sky->BottomRadius); + } +} diff --git a/Plugins/CesiumForUnreal/Source/CesiumRuntime/Private/CesiumTextureUtility.cpp b/Plugins/CesiumForUnreal/Source/CesiumRuntime/Private/CesiumTextureUtility.cpp new file mode 100644 index 0000000000000000000000000000000000000000..67fce22a80fdd46b961bb9453ffc5743de60ef0f --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/CesiumRuntime/Private/CesiumTextureUtility.cpp @@ -0,0 +1,855 @@ +// Copyright 2020-2021 CesiumGS, Inc. and Contributors + +#include "CesiumTextureUtility.h" +#include "Async/Async.h" +#include "Async/Future.h" +#include "Async/TaskGraphInterfaces.h" +#include "CesiumLifetime.h" +#include "CesiumRuntime.h" +#include "Containers/ResourceArray.h" +#include "DynamicRHI.h" +#include "GenericPlatform/GenericPlatformProcess.h" +#include "PixelFormat.h" +#include "RHIDefinitions.h" +#include "RHIResources.h" +#include "RenderUtils.h" +#include "Runtime/Launch/Resources/Version.h" +#include "TextureResource.h" +#include <CesiumGltf/ExtensionKhrTextureBasisu.h> +#include <CesiumGltf/ExtensionTextureWebp.h> +#include <CesiumGltf/ImageCesium.h> +#include <CesiumGltf/Ktx2TranscodeTargets.h> +#include <CesiumGltfReader/GltfReader.h> +#include <CesiumUtility/Tracing.h> +#include <memory> +#include <stb_image_resize.h> +#include <variant> + +#define LEGACY_TEXTURE_CREATION 0 + +using namespace CesiumGltf; + +namespace { +#if LEGACY_TEXTURE_CREATION +// Legacy texture creation code path. Only for testing, no safety checks are +// done. + +void legacy_populateMips( + FTexturePlatformData& platformData, + const CesiumGltf::ImageCesium& image, + bool generateMipMaps) { + uint32 width = static_cast<uint32>(image.width); + uint32 height = static_cast<uint32>(image.height); + for (const CesiumGltf::ImageCesiumMipPosition& mipPos : image.mipPositions) { + FTexture2DMipMap* pMip = new FTexture2DMipMap(); + platformData.Mips.Add(pMip); + pMip->SizeX = width; + pMip->SizeY = height; + + pMip->BulkData.Lock(LOCK_READ_WRITE); + void* pDest = pMip->BulkData.Realloc(static_cast<int64>(mipPos.byteSize)); + + FMemory::Memcpy( + pDest, + &image.pixelData[mipPos.byteOffset], + mipPos.byteSize); + + pMip->BulkData.Unlock(); + + if (!generateMipMaps) { + // Only populate mip 0 if we don't want the full mip chain. + return; + } + + if (width > 1) { + width >>= 1; + } + + if (height > 1) { + height >>= 1; + } + } +} +#endif + +struct GetImageFromSource { + CesiumGltf::ImageCesium* + operator()(CesiumTextureUtility::GltfImagePtr& imagePtr) { + return imagePtr.pImage; + } + + CesiumGltf::ImageCesium* + operator()(CesiumTextureUtility::EmbeddedImageSource& embeddedImage) { + return &embeddedImage.image; + } + + template <typename TSource> + CesiumGltf::ImageCesium* operator()(TSource& /*source*/) { + return nullptr; + } +}; + +/** + * @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, + const CesiumGltf::ImageCesium& src, + uint32 mipIndex) { + const CesiumGltf::ImageCesiumMipPosition& mipPos = src.mipPositions[mipIndex]; + uint32 mipWidth = + FMath::Max<uint32>(static_cast<uint32>(src.width) >> mipIndex, 1); + uint32 mipHeight = + FMath::Max<uint32>(static_cast<uint32>(src.height) >> mipIndex, 1); + + const void* pSrcData = + static_cast<const void*>(&src.pixelData[mipPos.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, mipPos.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<uint32>(numColumns, 2); + numRows = FMath::Max<uint32>(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); + } +} + +/** + * @brief A wrapper for CesiumGltf::ImageCesium that allows it to be used as + * bulk data for RHI texture creation. This prevents having to copy texture + * data to an intermediary, Unreal-specific CPU buffer before being copied to + * the GPU (in particular FTexture2DMipMap). + */ +class FCesiumTextureData : public FResourceBulkDataInterface { +public: + FCesiumTextureData(const CesiumGltf::ImageCesium& image) + : _textureData(image.pixelData.data()), + _textureDataSize( + (!image.mipPositions.empty()) + ? static_cast<uint32>(image.mipPositions[0].byteSize) + : static_cast<uint32>(image.pixelData.size())) {} + + const void* GetResourceBulkData() const override { + return static_cast<const void*>(this->_textureData); + } + + uint32 GetResourceBulkDataSize() const override { + return this->_textureDataSize; + } + + void Discard() override {} + +private: + const std::byte* _textureData; + uint32 _textureDataSize; +}; + +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 An RHI resource that creates and destroys RHI textures. If a non-null + * FTexture2DRHIRef is given, ownership of it is assumed and it will be + * destroyed in ReleaseResource. Otherwise, the RHI texture will be created + * from the in-memory Cesium glTF image in InitRHI (on the render thread). + * + */ +class FCesiumTextureResource : public FTextureResource { +public: + FCesiumTextureResource( + UTexture* pTexture, + CesiumTextureUtility::CesiumTextureSource&& textureSource, + uint32 width, + uint32 height, + EPixelFormat format, + TextureFilter filter, + TextureAddress addressX, + TextureAddress addressY, + bool sRGB, + uint32 extData) + : _pTexture(pTexture), + _textureSource(std::move(textureSource)), + _width(width), + _height(height), + _format(format), + _filter(convertFilter(filter)), + _addressX(convertAddressMode(addressX)), + _addressY(convertAddressMode(addressY)), + _platformExtData(extData) { + this->bGreyScaleFormat = (_format == PF_G8) || (_format == PF_BC4); + this->bSRGB = sRGB; + + CesiumTextureUtility::AsyncCreatedTexture* pAsyncTexture = + std::get_if<CesiumTextureUtility::AsyncCreatedTexture>( + &this->_textureSource); + if (pAsyncTexture) { + this->TextureRHI = pAsyncTexture->rhiTextureRef; + pAsyncTexture->rhiTextureRef.SafeRelease(); + } + } + + virtual ~FCesiumTextureResource() { + check(this->_pTexture != nullptr); +#if ENGINE_MAJOR_VERSION == 4 && ENGINE_MINOR_VERSION < 27 + this->_pTexture->Resource = nullptr; +#else + this->_pTexture->SetResource(nullptr); +#endif + } + + uint32 GetSizeX() const override { return this->_width; } + + uint32 GetSizeY() const override { return this->_height; } + + virtual void InitRHI() override { + FSamplerStateInitializerRHI samplerStateInitializer( + this->_filter, + this->_addressX, + this->_addressY, + AM_Wrap, + 0.0f, + 0, + 0.0f, + FLT_MAX); + 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 + 2.0f); + this->DeferredPassSamplerStateRHI = + GetOrCreateSamplerState(deferredSamplerStateInitializer); + + if (!this->TextureRHI) { + // Asynchronous RHI texture creation was not available. So create it now + // directly from the in-memory cesium mips. + CesiumGltf::ImageCesium* pImage = + std::visit(GetImageFromSource{}, this->_textureSource); + + check(pImage != nullptr); + + // Wrap mip0 as a bulk data source. + FCesiumTextureData bulkData(*pImage); + + FRHIResourceCreateInfo createInfo{TEXT("CesiumTextureUtility")}; + createInfo.BulkData = &bulkData; + createInfo.ExtData = _platformExtData; + + ETextureCreateFlags textureFlags = TexCreate_ShaderResource; + + if (this->bSRGB) { + textureFlags |= TexCreate_SRGB; + } + + uint32 mipCount = + FMath::Max(1, static_cast<int32>(pImage->mipPositions.size())); + + FTexture2DRHIRef rhiTexture; + + // Copies over mip0, allocates the rest of the mips if needed. + + // 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. + rhiTexture = RHICreateTexture2D( + this->_width, + this->_height, + this->_format, + mipCount, + 1, + textureFlags, + createInfo); + + // Copies over rest of the mips + for (uint32 i = 1; i < mipCount; ++i) { + uint32 DestPitch; + void* pDestination = + RHILockTexture2D(rhiTexture, i, RLM_WriteOnly, DestPitch, false); + CopyMip(pDestination, DestPitch, _format, *pImage, i); + RHIUnlockTexture2D(rhiTexture, i, false); + } + + this->TextureRHI = std::move(rhiTexture); + } + + RHIUpdateTextureReference(TextureReferenceRHI, this->TextureRHI); + } + + virtual void ReleaseRHI() override { + RHIUpdateTextureReference(TextureReferenceRHI, nullptr); + + FTextureResource::ReleaseRHI(); + } + +private: + UTexture* _pTexture; + CesiumTextureUtility::CesiumTextureSource _textureSource; + + uint32 _width; + uint32 _height; + EPixelFormat _format; + ESamplerFilter _filter; + ESamplerAddressMode _addressX; + ESamplerAddressMode _addressY; + + uint32 _platformExtData; +}; + +/** + * @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 generateMipMaps Whether the RHI texture should have a mipmap. + * @param Whether to use a sRGB color-space. + * @return The RHI texture reference. + */ +FTexture2DRHIRef CreateRHITexture2D_Async( + const CesiumGltf::ImageCesium& image, + EPixelFormat format, + bool generateMipMaps, + bool sRGB) { + check(GRHISupportsAsyncTextureCreation); + + ETextureCreateFlags textureFlags = TexCreate_ShaderResource; + if (sRGB) { + textureFlags |= TexCreate_SRGB; + } + + if (generateMipMaps) { + // Here 16 is a generously large (but arbitrary) hard limit for number of + // mips. + uint32 mipCount = static_cast<uint32>(image.mipPositions.size()); + if (mipCount > 16) { + mipCount = 16; + } + + void* mipsData[16]; + for (size_t i = 0; i < mipCount; ++i) { + const CesiumGltf::ImageCesiumMipPosition& mipPos = image.mipPositions[i]; + mipsData[i] = (void*)(&image.pixelData[mipPos.byteOffset]); + } + + return RHIAsyncCreateTexture2D( + static_cast<uint32>(image.width), + static_cast<uint32>(image.height), + format, + mipCount, + textureFlags, + mipsData, + mipCount); + } else { + void* pTextureData = (void*)(image.pixelData.data()); + return RHIAsyncCreateTexture2D( + static_cast<uint32>(image.width), + static_cast<uint32>(image.height), + format, + 1, + textureFlags, + &pTextureData, + 1); + } +} +} // namespace + +namespace CesiumTextureUtility { + +GltfImagePtr +GltfImageIndex::resolveImage(const CesiumGltf::Model& model) const { + // Almost certainly a developer error otherwise. + assert(this->imageIndex >= 0 && this->imageIndex < model.images.size()); + + // It's not worth making const-specializations of CesiumTextureSource, so we + // just const-cast. + CesiumGltf::ImageCesium* pImage = const_cast<CesiumGltf::ImageCesium*>( + &model.images[static_cast<size_t>(this->index)].cesium); + + return GltfImagePtr{pImage}; +} + +TUniquePtr<FTexturePlatformData> +createTexturePlatformData(int32 sizeX, int32 sizeY, EPixelFormat format) { + if (sizeX > 0 && sizeY > 0 && + (sizeX % GPixelFormats[format].BlockSizeX) == 0 && + (sizeY % GPixelFormats[format].BlockSizeY) == 0) { + TUniquePtr<FTexturePlatformData> pTexturePlatformData = + MakeUnique<FTexturePlatformData>(); + pTexturePlatformData->SizeX = sizeX; + pTexturePlatformData->SizeY = sizeY; + pTexturePlatformData->PixelFormat = format; + + return pTexturePlatformData; + } else { + return nullptr; + } +} + +static UTexture2D* CreateTexture2D(LoadedTextureResult* pHalfLoadedTexture) { + if (!pHalfLoadedTexture) { + return nullptr; + } + + UTexture2D* pTexture = pHalfLoadedTexture->pTexture.Get(); + if (!pTexture && pHalfLoadedTexture->pTextureData) { + pTexture = NewObject<UTexture2D>( + GetTransientPackage(), + MakeUniqueObjectName( + GetTransientPackage(), + UTexture2D::StaticClass(), + "CesiumRuntimeTexture"), + RF_Transient | RF_DuplicateTransient | RF_TextExportTransient); + +#if ENGINE_MAJOR_VERSION >= 5 + pTexture->SetPlatformData(pHalfLoadedTexture->pTextureData.Release()); +#else + pTexture->PlatformData = pHalfLoadedTexture->pTextureData.Release(); +#endif + 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 = pTexture; + } + + return pTexture; +} + +TUniquePtr<LoadedTextureResult> loadTextureAnyThreadPart( + CesiumTextureSource&& imageSource, + const TextureAddress& addressX, + const TextureAddress& addressY, + const TextureFilter& filter, + const TextureGroup& group, + bool generateMipMaps, + bool sRGB) { + + CesiumGltf::ImageCesium* pImage = + std::visit(GetImageFromSource{}, imageSource); + + assert(pImage != nullptr); + CesiumGltf::ImageCesium& image = *pImage; + + if (image.pixelData.empty() || image.width == 0 || image.height == 0) { + return nullptr; + } + + if (generateMipMaps) { + std::optional<std::string> errorMessage = + CesiumGltfReader::GltfReader::generateMipMaps(image); + if (errorMessage) { + UE_LOG( + LogCesium, + Warning, + TEXT("%s"), + UTF8_TO_TCHAR(errorMessage->c_str())); + } + } + + EPixelFormat pixelFormat; + if (image.compressedPixelFormat != GpuCompressedPixelFormat::NONE) { + switch (image.compressedPixelFormat) { + case GpuCompressedPixelFormat::ETC1_RGB: + pixelFormat = EPixelFormat::PF_ETC1; + break; + case GpuCompressedPixelFormat::ETC2_RGBA: + pixelFormat = EPixelFormat::PF_ETC2_RGBA; + break; + case GpuCompressedPixelFormat::BC1_RGB: + pixelFormat = EPixelFormat::PF_DXT1; + break; + case GpuCompressedPixelFormat::BC3_RGBA: + pixelFormat = EPixelFormat::PF_DXT5; + break; + case GpuCompressedPixelFormat::BC4_R: + pixelFormat = EPixelFormat::PF_BC4; + break; + case GpuCompressedPixelFormat::BC5_RG: + pixelFormat = EPixelFormat::PF_BC5; + break; + case GpuCompressedPixelFormat::BC7_RGBA: + pixelFormat = EPixelFormat::PF_BC7; + break; + case GpuCompressedPixelFormat::ASTC_4x4_RGBA: + pixelFormat = EPixelFormat::PF_ASTC_4x4; + break; + case GpuCompressedPixelFormat::PVRTC2_4_RGBA: + pixelFormat = EPixelFormat::PF_PVRTC2; + break; + case GpuCompressedPixelFormat::ETC2_EAC_R11: + pixelFormat = EPixelFormat::PF_ETC2_R11_EAC; + break; + case GpuCompressedPixelFormat::ETC2_EAC_RG11: + pixelFormat = EPixelFormat::PF_ETC2_RG11_EAC; + break; + default: + // Unsupported compressed texture format. + return nullptr; + }; + } else { + switch (image.channels) { + case 1: + pixelFormat = PF_R8; + break; + case 2: + pixelFormat = PF_R8G8; + break; + case 3: + case 4: + default: + pixelFormat = PF_R8G8B8A8; + }; + } + + TUniquePtr<LoadedTextureResult> pResult = MakeUnique<LoadedTextureResult>(); + pResult->pTextureData = + createTexturePlatformData(image.width, image.height, pixelFormat); + + if (!pResult->pTextureData) { + return nullptr; + } + + pResult->addressX = addressX; + pResult->addressY = addressY; + pResult->filter = filter; + pResult->group = group; + pResult->sRGB = sRGB; + pResult->generateMipMaps = generateMipMaps; + +#if LEGACY_TEXTURE_CREATION + // Legacy texture creation copies mip data into the FTexturePlatformData. + legacy_populateMips(*pResult->pTextureData, image, generateMipMaps); + // Mark the image source as legacy, so we later know where to look for image + // data. + pResult->textureSource = LegacyTextureSource{}; +#else + if (GRHISupportsAsyncTextureCreation) { + // Create RHI texture resource asynchronously. + TRACE_CPUPROFILER_EVENT_SCOPE(Cesium::CreateRHITexture2D) + + pResult->textureSource = AsyncCreatedTexture{ + CreateRHITexture2D_Async(image, pixelFormat, generateMipMaps, sRGB)}; + } else { + // The RHI texture will be created later on the render thread, directly + // from this texture source. + pResult->textureSource = std::move(imageSource); + } +#endif + + return pResult; +} + +TUniquePtr<LoadedTextureResult> loadTextureAnyThreadPart( + CesiumGltf::Model& model, + const CesiumGltf::Texture& texture, + bool sRGB) { + + TRACE_CPUPROFILER_EVENT_SCOPE(Cesium::LoadTexture) + + const CesiumGltf::ExtensionKhrTextureBasisu* pKtxExtension = + texture.getExtension<CesiumGltf::ExtensionKhrTextureBasisu>(); + const CesiumGltf::ExtensionTextureWebp* pWebpExtension = + texture.getExtension<CesiumGltf::ExtensionTextureWebp>(); + + 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 nullptr; + } + source = 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 nullptr; + } + source = 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 nullptr; + } + source = texture.source; + } + + CesiumGltf::ImageCesium& image = model.images[source].cesium; + const CesiumGltf::Sampler* pSampler = + CesiumGltf::Model::getSafe(&model.samplers, texture.sampler); + + // glTF spec: "When undefined, a sampler with repeat wrapping and auto + // filtering should be used." + TextureAddress addressX = TextureAddress::TA_Wrap; + TextureAddress addressY = TextureAddress::TA_Wrap; + + TextureFilter filter = TextureFilter::TF_Default; + bool useMipMaps = false; + + if (pSampler) { + switch (pSampler->wrapS) { + case CesiumGltf::Sampler::WrapS::CLAMP_TO_EDGE: + addressX = TextureAddress::TA_Clamp; + break; + case CesiumGltf::Sampler::WrapS::MIRRORED_REPEAT: + addressX = TextureAddress::TA_Mirror; + break; + case CesiumGltf::Sampler::WrapS::REPEAT: + addressX = TextureAddress::TA_Wrap; + break; + } + + switch (pSampler->wrapT) { + case CesiumGltf::Sampler::WrapT::CLAMP_TO_EDGE: + addressY = TextureAddress::TA_Clamp; + break; + case CesiumGltf::Sampler::WrapT::MIRRORED_REPEAT: + addressY = TextureAddress::TA_Mirror; + break; + case CesiumGltf::Sampler::WrapT::REPEAT: + addressY = TextureAddress::TA_Wrap; + break; + } + + // 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 (pSampler->magFilter && !pSampler->minFilter) { + // Only a magnification filter is specified, so use it. + filter = + pSampler->magFilter.value() == CesiumGltf::Sampler::MagFilter::NEAREST + ? TextureFilter::TF_Nearest + : TextureFilter::TF_Default; + } else if (pSampler->minFilter) { + // Use specified minFilter. + switch (pSampler->minFilter.value()) { + case CesiumGltf::Sampler::MinFilter::NEAREST: + case CesiumGltf::Sampler::MinFilter::NEAREST_MIPMAP_NEAREST: + filter = TextureFilter::TF_Nearest; + break; + case CesiumGltf::Sampler::MinFilter::LINEAR: + case CesiumGltf::Sampler::MinFilter::LINEAR_MIPMAP_NEAREST: + filter = TextureFilter::TF_Bilinear; + break; + default: + filter = TextureFilter::TF_Default; + break; + } + } else { + // No filtering specified at all, let the texture group decide. + filter = TextureFilter::TF_Default; + } + + switch (pSampler->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: + useMipMaps = true; + break; + default: // LINEAR and NEAREST + useMipMaps = false; + break; + } + } + + TUniquePtr<LoadedTextureResult> result = loadTextureAnyThreadPart( + GltfImagePtr{&image}, + addressX, + addressY, + filter, + TextureGroup::TEXTUREGROUP_World, + useMipMaps, + sRGB); + + // Replace the image pointer with an index, in case the pointer gets + // invalidated before the main thread loading continues. + if (result && std::get_if<GltfImagePtr>(&result->textureSource)) { + result->textureSource = GltfImageIndex{source}; + } + + return result; +} + +UTexture2D* loadTextureGameThreadPart(LoadedTextureResult* pHalfLoadedTexture) { + TRACE_CPUPROFILER_EVENT_SCOPE(Cesium::LoadTexture) + + if (!pHalfLoadedTexture) { + return nullptr; + } + + if (pHalfLoadedTexture->pTexture.Get()) { + return pHalfLoadedTexture->pTexture.Get(); + } + + UTexture2D* pTexture = CreateTexture2D(pHalfLoadedTexture); + + if (std::get_if<LegacyTextureSource>(&pHalfLoadedTexture->textureSource)) { + pTexture->UpdateResource(); + return pTexture; + } + + FCesiumTextureResource* pCesiumTextureResource = new FCesiumTextureResource( + pTexture, + std::move(pHalfLoadedTexture->textureSource), + static_cast<uint32>(pTexture->GetSizeX()), + static_cast<uint32>(pTexture->GetSizeY()), + pTexture->GetPixelFormat(), + pHalfLoadedTexture->filter, + pHalfLoadedTexture->addressX, + pHalfLoadedTexture->addressY, + pHalfLoadedTexture->sRGB, + pTexture->PlatformData->GetExtData()); + +#if ENGINE_MAJOR_VERSION == 4 && ENGINE_MINOR_VERSION < 27 + pTexture->Resource = pCesiumTextureResource; +#else + pTexture->SetResource(pCesiumTextureResource); +#endif + + ENQUEUE_RENDER_COMMAND(Cesium_InitResource) + ([pTexture, pCesiumTextureResource](FRHICommandListImmediate& RHICmdList) { + pCesiumTextureResource->SetTextureReference( + pTexture->TextureReference.TextureReferenceRHI); + pCesiumTextureResource->InitResource(); + }); + + return pTexture; +} + +UTexture2D* loadTextureGameThreadPart( + const CesiumGltf::Model& model, + LoadedTextureResult* pHalfLoadedTexture) { + if (!pHalfLoadedTexture) { + return nullptr; + } + + GltfImageIndex* pImageIndex = + std::get_if<GltfImageIndex>(&pHalfLoadedTexture->textureSource); + if (pImageIndex) { + pHalfLoadedTexture->textureSource = pImageIndex->resolveImage(model); + } + + return loadTextureGameThreadPart(pHalfLoadedTexture); +} + +void destroyHalfLoadedTexture(LoadedTextureResult& halfLoaded) { + AsyncCreatedTexture* pAsyncCreatedTexture = + std::get_if<AsyncCreatedTexture>(&halfLoaded.textureSource); + if (pAsyncCreatedTexture) { + // An RHI texture was asynchronously created and must now be destroyed. + ENQUEUE_RENDER_COMMAND(Cesium_ReleaseHalfLoadedTexture) + ([rhiTextureRef = pAsyncCreatedTexture->rhiTextureRef]( + FRHICommandListImmediate& RHICmdList) mutable { + rhiTextureRef.SafeRelease(); + }); + + pAsyncCreatedTexture->rhiTextureRef.SafeRelease(); + } +} + +void destroyTexture(UTexture* pTexture) { + check(pTexture != nullptr); + CesiumLifetime::destroy(pTexture); +} +} // 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 0000000000000000000000000000000000000000..a7858fcf8fedd8bb4d13d1ed46ed253e639d49ec --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/CesiumRuntime/Private/CesiumTextureUtility.h @@ -0,0 +1,163 @@ +// Copyright 2020-2021 CesiumGS, Inc. and Contributors + +#pragma once + +#include "CesiumGltf/Model.h" +#include "CesiumMetadataValueType.h" +#include "Engine/Texture.h" +#include "Engine/Texture2D.h" +#include "Engine/TextureDefines.h" +#include "Templates/UniquePtr.h" +#include <optional> +#include <variant> + +namespace CesiumGltf { +struct ImageCesium; +struct Texture; +} // namespace CesiumGltf + +namespace CesiumTextureUtility { +/** + * @brief A texture that has already been asynchronously created. + */ +struct AsyncCreatedTexture { + FTexture2DRHIRef rhiTextureRef{}; +}; + +/** + * @brief A pointer to a glTF image. This image will be cached and used on the + * game thread and render thread during texture creation. + * + * WARNING: Do not use this form of texture creation if the given pointer will + * be invalidated before the render-thread texture preparation work is done. + */ +struct GltfImagePtr { + CesiumGltf::ImageCesium* pImage; +}; + +/** + * @brief An index to an image that can be looked up later in the corresponding + * glTF. + */ +struct GltfImageIndex { + int32_t index = -1; + GltfImagePtr resolveImage(const CesiumGltf::Model& model) const; +}; + +/** + * @brief An embedded image resource. + */ +struct EmbeddedImageSource { + CesiumGltf::ImageCesium image; +}; + +/** + * @brief This indicates that the image mips are stored in the + * FTexturePlatformData and expect a standard, Unreal texture construction. + * + * WARNING: Unreal's default texture creation method (via + * UTexture::UpdateResource) requires an extra memcpy on the game thread and + * synchronous texture creation on the render thread. + */ +struct LegacyTextureSource {}; + +/** + * @brief The texture source that should be used to create or finalize an + * Unreal texture. + */ +typedef std::variant< + AsyncCreatedTexture, + GltfImagePtr, + GltfImageIndex, + EmbeddedImageSource, + LegacyTextureSource> + CesiumTextureSource; + +/** + * @brief Half-loaded Unreal texture with info on how to finish loading the + * texture on the game thread and render thread. + */ +struct LoadedTextureResult { + TUniquePtr<FTexturePlatformData> pTextureData; + TextureAddress addressX; + TextureAddress addressY; + TextureFilter filter; + TextureGroup group; + bool generateMipMaps; + bool sRGB{true}; + TWeakObjectPtr<UTexture2D> pTexture; + CesiumTextureSource textureSource; +}; + +TUniquePtr<FTexturePlatformData> +createTexturePlatformData(int32 sizeX, int32 sizeY, EPixelFormat format); + +/** + * @brief Does the asynchronous part of renderer resource preparation for this + * image. Should be called in a background thread. May generate mip-maps for + * this image within the given glTF, if needed. + * + * @param imageSource The source for this image. This function may add mip-maps + * to the image if needed. + * @param addressX The X addressing mode. + * @param addressY The Y addressing mode. + * @param filter The sampler filtering to use for this texture. + * @param group The texture group of this texture. + * @param generateMipMaps Whether to generate a mipmap for this image. + * @param sRGB Whether this texture uses a sRGB color space. + * @return The loaded texture. + */ +TUniquePtr<LoadedTextureResult> loadTextureAnyThreadPart( + CesiumTextureSource&& imageSource, + const TextureAddress& addressX, + const TextureAddress& addressY, + const TextureFilter& filter, + const TextureGroup& group, + bool generateMipMaps, + bool sRGB); + +/** + * @brief Does the asynchronous part of renderer resource preparation for this + * image. Should be called in a background thread. May generate mip-maps for + * this image within the given glTF, if needed. + * + * @param model The model. + * @param texture The texture to load. + * @param sRGB Whether this texture uses a sRGB color space. + * @return The loaded texture. + */ +TUniquePtr<LoadedTextureResult> loadTextureAnyThreadPart( + CesiumGltf::Model& model, + const CesiumGltf::Texture& texture, + bool sRGB); + +/** + * @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. + * + * NOTE: Assumes LoadedTextureResult::textureSource is not GltfImageIndex. + * Use GltfImageIndex::resolve(...) to convert to a GltfImagePtr. + * + * @param pHalfLoadedTexture The half-loaded renderer texture. + * @return The Unreal texture result. + */ +UTexture2D* loadTextureGameThreadPart(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. Resolves the textureSource to a GltfImagePtr, if it is currently + * GltfImageIndex. + * + * @param model The glTF model, containing the image. + * @param pHalfLoadedTexture The half-loaded renderer texture. + * @return The Unreal texture result. + */ +UTexture2D* loadTextureGameThreadPart( + const CesiumGltf::Model& model, + LoadedTextureResult* pHalfLoadedTexture); + +void destroyHalfLoadedTexture(LoadedTextureResult& halfLoaded); +void destroyTexture(UTexture* pTexture); +} // namespace CesiumTextureUtility diff --git a/Plugins/CesiumForUnreal/Source/CesiumRuntime/Private/CesiumTileMapServiceRasterOverlay.cpp b/Plugins/CesiumForUnreal/Source/CesiumRuntime/Private/CesiumTileMapServiceRasterOverlay.cpp new file mode 100644 index 0000000000000000000000000000000000000000..474e095fa270743605de7b936cf482e7f49bb3ab --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/CesiumRuntime/Private/CesiumTileMapServiceRasterOverlay.cpp @@ -0,0 +1,21 @@ +// Copyright 2020-2021 CesiumGS, Inc. and Contributors + +#include "CesiumTileMapServiceRasterOverlay.h" +#include "Cesium3DTilesSelection/TileMapServiceRasterOverlay.h" +#include "CesiumRuntime.h" + +std::unique_ptr<Cesium3DTilesSelection::RasterOverlay> +UCesiumTileMapServiceRasterOverlay::CreateOverlay( + const Cesium3DTilesSelection::RasterOverlayOptions& options) { + Cesium3DTilesSelection::TileMapServiceRasterOverlayOptions tmsOptions; + if (MaximumLevel > MinimumLevel && bSpecifyZoomLevels) { + tmsOptions.minimumLevel = MinimumLevel; + tmsOptions.maximumLevel = MaximumLevel; + } + return std::make_unique<Cesium3DTilesSelection::TileMapServiceRasterOverlay>( + TCHAR_TO_UTF8(*this->MaterialLayerKey), + TCHAR_TO_UTF8(*this->Url), + std::vector<CesiumAsync::IAssetAccessor::THeader>(), + 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 0000000000000000000000000000000000000000..02acd5fda8e76debc09e10ce2d2196e088521a25 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/CesiumRuntime/Private/CesiumTransforms.cpp @@ -0,0 +1,30 @@ +// Copyright 2020-2021 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 0000000000000000000000000000000000000000..d4ad25fbbf3603057df835b76d7b9b2f4e4fe06a --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/CesiumRuntime/Private/CesiumTransforms.h @@ -0,0 +1,39 @@ +// Copyright 2020-2021 CesiumGS, Inc. and Contributors + +#pragma once + +#include <glm/mat4x4.hpp> + +/** + * 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 0000000000000000000000000000000000000000..26711fd9bcc6059c32c1c8a8e7f892280edc4bd8 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/CesiumRuntime/Private/CesiumViewExtension.cpp @@ -0,0 +1,185 @@ + +#include "CesiumViewExtension.h" + +#include "Cesium3DTileset.h" + +using namespace Cesium3DTilesSelection; + +CesiumViewExtension::CesiumViewExtension(const FAutoRegister& autoRegister) + : FSceneViewExtensionBase(autoRegister) {} + +CesiumViewExtension::~CesiumViewExtension() {} + +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(); + } +} + +void CesiumViewExtension::PreRenderViewFamily_RenderThread( + FRHICommandListImmediate& RHICmdList, + FSceneViewFamily& InViewFamily) {} + +void CesiumViewExtension::PreRenderView_RenderThread( + FRHICommandListImmediate& RHICmdList, + FSceneView& InView) {} + +void CesiumViewExtension::PostRenderViewFamily_RenderThread( + FRHICommandListImmediate& RHICmdList, + 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 && pViewState->PrimitiveOcclusionHistorySet.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( + pViewState->PrimitiveOcclusionHistorySet.Num()); + for (const auto& element : pViewState->PrimitiveOcclusionHistorySet) { + 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<const FViewInfo*>(pView); + const FSceneBitArray& visibility = pViewInfo->PrimitiveVisibilityMap; + auto& occlusion = occlusionResults.PrimitiveOcclusionResults; + + const uint32 PrimitiveCount = pScene->Primitives.Num(); + for (uint32 i = 0; i < PrimitiveCount; ++i) { + // We're only concerned with primitives that are not visible + if (visibility[i]) + continue; + + FPrimitiveSceneInfo* pSceneInfo = pScene->Primitives[i]; + if (pSceneInfo == nullptr) + continue; + + 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, + 0.0f, + true, + true)); + } + } + } + } + } +} + +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 0000000000000000000000000000000000000000..16645e97b272b651124acb1ef5b96b4adc9c51ac --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/CesiumRuntime/Private/CesiumViewExtension.h @@ -0,0 +1,121 @@ + +#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 <Cesium3DTilesSelection/TileOcclusionRendererProxy.h> +#include <cstdint> +#include <unordered_set> + +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<PrimitiveOcclusionResult, FPrimitiveComponentId> { + 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<PrimitiveOcclusionResult, PrimitiveOcclusionResultKeyFuncs> + PrimitiveOcclusionResults{}; + }; + + // A collection of occlusion results by view. + struct AggregatedOcclusionUpdate { + std::vector<SceneViewOcclusionResults> 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<AggregatedOcclusionUpdate, EQueueMode::Spsc> _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<PrimitiveOcclusionResult, PrimitiveOcclusionResultKeyFuncs>, + 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<bool> _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 PreRenderViewFamily_RenderThread( + FRHICommandListImmediate& RHICmdList, + FSceneViewFamily& InViewFamily) override; + void PreRenderView_RenderThread( + FRHICommandListImmediate& RHICmdList, + FSceneView& InView) override; + void PostRenderViewFamily_RenderThread( + FRHICommandListImmediate& RHICmdList, + 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 0000000000000000000000000000000000000000..41e83575cdedc24b24037acd31d9dfed2265eae7 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/CesiumRuntime/Private/CesiumWebMapServiceRasterOverlay.cpp @@ -0,0 +1,26 @@ +// Copyright 2020-2021 CesiumGS, Inc. and Contributors + +#include "CesiumWebMapServiceRasterOverlay.h" +#include "Algo/Transform.h" +#include "Cesium3DTilesSelection/WebMapServiceRasterOverlay.h" +#include "CesiumRuntime.h" + +std::unique_ptr<Cesium3DTilesSelection::RasterOverlay> +UCesiumWebMapServiceRasterOverlay::CreateOverlay( + const Cesium3DTilesSelection::RasterOverlayOptions& options) { + + Cesium3DTilesSelection::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<Cesium3DTilesSelection::WebMapServiceRasterOverlay>( + TCHAR_TO_UTF8(*this->MaterialLayerKey), + TCHAR_TO_UTF8(*this->BaseUrl), + std::vector<CesiumAsync::IAssetAccessor::THeader>(), + wmsOptions, + options); +} diff --git a/Plugins/CesiumForUnreal/Source/CesiumRuntime/Private/CreateGltfOptions.h b/Plugins/CesiumForUnreal/Source/CesiumRuntime/Private/CreateGltfOptions.h new file mode 100644 index 0000000000000000000000000000000000000000..402f0b105fd006e57b5665ffe8ec798db4fde0e9 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/CesiumRuntime/Private/CreateGltfOptions.h @@ -0,0 +1,38 @@ +// Copyright 2020-2021 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 { + CesiumGltf::Model* pModel = nullptr; + const FMetadataDescription* pEncodedMetadataDescription = nullptr; + bool alwaysIncludeTangents = false; + bool createPhysicsMeshes = true; +}; + +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; + const CesiumGltf::Mesh* pMesh = nullptr; +}; + +struct CreatePrimitiveOptions { + const CreateMeshOptions* pMeshOptions = nullptr; + const LoadGltfResult::LoadMeshResult* pHalfConstructedMeshResult = nullptr; + const CesiumGltf::MeshPrimitive* pPrimitive = nullptr; +}; +} // namespace CreateGltfOptions diff --git a/Plugins/CesiumForUnreal/Source/CesiumRuntime/Private/GeoTransforms.cpp b/Plugins/CesiumForUnreal/Source/CesiumRuntime/Private/GeoTransforms.cpp new file mode 100644 index 0000000000000000000000000000000000000000..1ccf53960cbc379cd39273da10427cd783562171 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/CesiumRuntime/Private/GeoTransforms.cpp @@ -0,0 +1,171 @@ +// Copyright 2020-2021 CesiumGS, Inc. and Contributors + +#include "GeoTransforms.h" + +#include "CesiumGeospatial/Transforms.h" +#include "CesiumTransforms.h" +#include "VecMath.h" + +// ONLY used for logging! +#include "CesiumRuntime.h" + +#include "GeoTransforms.h" +#include <glm/glm.hpp> +#include <glm/gtc/matrix_inverse.hpp> +#include <glm/gtx/quaternion.hpp> + +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->_georeferencedToEcef = + CesiumGeospatial::Transforms::eastNorthUpToFixedFrame( + _center, + _ellipsoid); + this->_ecefToGeoreferenced = glm::affineInverse(this->_georeferencedToEcef); + this->_ueAbsToEcef = this->_georeferencedToEcef * + CesiumTransforms::scaleToCesium * + CesiumTransforms::unrealToOrFromCesium; + this->_ecefToUeAbs = CesiumTransforms::unrealToOrFromCesium * + CesiumTransforms::scaleToUnrealWorld * + this->_ecefToGeoreferenced; + + 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<CesiumGeospatial::Cartographic> 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 { + glm::dvec3 ueAbs = glm::dvec3(this->_ecefToUeAbs * glm::dvec4(ecef, 1.0)); + return ueAbs - origin; +} + +glm::dvec3 GeoTransforms::TransformUnrealToEcef( + const glm::dvec3& origin, + const glm::dvec3& ue) const noexcept { + + glm::dvec3 ueAbs = ue + origin; + return glm::dvec3(this->_ueAbsToEcef * glm::dvec4(ueAbs, 1.0)); +} + +glm::dquat GeoTransforms::TransformRotatorUnrealToEastSouthUp( + const glm::dvec3& origin, + const glm::dquat& UERotator, + const glm::dvec3& ueLocation) const noexcept { + glm::dmat3 esuToUe = 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 = this->ComputeEastSouthUpToUnreal(origin, ueLocation); + glm::dquat esuToUeQuat = glm::quat_cast(esuToUe); + return esuToUeQuat * ESURotator; +} + +glm::dmat3 GeoTransforms::ComputeEastSouthUpToUnreal( + const glm::dvec3& origin, + const glm::dvec3& ue) const noexcept { + glm::dvec3 ecef = this->TransformUnrealToEcef(origin, ue); + glm::dmat3 enuToEcef = this->ComputeEastNorthUpToEcef(ecef); + + glm::dmat3 rotationCesium = + glm::dmat3(this->_ecefToGeoreferenced) * enuToEcef; + + return glm::dmat3(CesiumTransforms::unrealToOrFromCesium) * rotationCesium * + glm::dmat3(CesiumTransforms::unrealToOrFromCesium); +} + +glm::dmat3 +GeoTransforms::ComputeEastNorthUpToEcef(const glm::dvec3& ecef) const noexcept { + return glm::dmat3( + CesiumGeospatial::Transforms::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 0000000000000000000000000000000000000000..b8f89d42a69335bea7001f79b4148c26c830f18a --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/CesiumRuntime/Private/GlmLogging.cpp @@ -0,0 +1,54 @@ +// Copyright 2020-2021 CesiumGS, Inc. and Contributors + +#include "GlmLogging.h" +#include "CesiumRuntime.h" + +#include <glm/glm.hpp> +#include <string> + +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 0000000000000000000000000000000000000000..3b15355c050e36ed8158039cdb5a7254bcb708a1 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/CesiumRuntime/Private/GlmLogging.h @@ -0,0 +1,30 @@ +// Copyright 2020-2021 CesiumGS, Inc. and Contributors + +#pragma once + +#include <glm/glm.hpp> +#include <string> + +/** + * @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 0000000000000000000000000000000000000000..dbeff1a814dfc21ccb3357767076490a4031b971 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/CesiumRuntime/Private/GlobeAwareDefaultPawn.cpp @@ -0,0 +1,398 @@ +// Copyright 2020-2021 CesiumGS, Inc. and Contributors + +#include "GlobeAwareDefaultPawn.h" +#include "Camera/CameraComponent.h" +#include "CesiumActors.h" +#include "CesiumCustomVersion.h" +#include "CesiumGeoreference.h" +#include "CesiumGeospatial/Ellipsoid.h" +#include "CesiumGeospatial/Transforms.h" +#include "CesiumGlobeAnchorComponent.h" +#include "CesiumRuntime.h" +#include "CesiumTransforms.h" +#include "CesiumUtility/Math.h" +#include "DrawDebugHelpers.h" +#include "Engine/World.h" +#include "GameFramework/PlayerController.h" +#include "VecMath.h" +#include <glm/ext/matrix_transform.hpp> +#include <glm/ext/vector_double3.hpp> +#include <glm/glm.hpp> +#include <glm/gtc/matrix_inverse.hpp> +#include <glm/gtx/quaternion.hpp> +#include <glm/gtx/rotate_vector.hpp> + +AGlobeAwareDefaultPawn::AGlobeAwareDefaultPawn() : ADefaultPawn() { + PrimaryActorTick.bCanEverTick = true; + + this->GlobeAnchor = + CreateDefaultSubobject<UCesiumGlobeAnchorComponent>(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 || !IsValid(this->GlobeAnchor)) { + return; + } + + glm::dvec4 upEcef( + CesiumGeospatial::Ellipsoid::WGS84.geodeticSurfaceNormal( + VecMath::createVector3D(this->GlobeAnchor->GetECEF())), + 0.0); + glm::dvec4 up = this->GlobeAnchor->ResolveGeoreference() + ->GetGeoTransforms() + .GetEllipsoidCenteredToAbsoluteUnrealWorldTransform() * + upEcef; + + this->_moveAlongVector(FVector(up.x, up.y, up.z), Val); +} + +FRotator AGlobeAwareDefaultPawn::GetViewRotation() const { + if (!Controller) { + 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(); + + // Transform the rotation in the ESU frame to the Unreal world frame. + FMatrix esuAdjustmentMatrix = + this->GetGeoreference()->ComputeEastSouthUpToUnreal( + this->GetPawnViewLocation()); + + return FRotator(esuAdjustmentMatrix.ToQuat() * localRotation.Quaternion()); +} + +FRotator AGlobeAwareDefaultPawn::GetBaseAimRotation() const { + return this->GetViewRotation(); +} + +void AGlobeAwareDefaultPawn::FlyToLocationECEF( + const glm::dvec3& ECEFDestination, + double YawAtDestination, + double PitchAtDestination, + bool CanInterruptByMoving) { + + if (this->_bFlyingToLocation) { + return; + } + + PitchAtDestination = glm::clamp(PitchAtDestination, -89.99, 89.99); + // Compute source location in ECEF + glm::dvec3 ECEFSource = VecMath::createVector3D(this->GlobeAnchor->GetECEF()); + + // The source and destination rotations are expressed in East-South-Up + // coordinates. + this->_flyToSourceRotation = Controller->GetControlRotation().Quaternion(); + this->_flyToDestinationRotation = + FRotator(PitchAtDestination, YawAtDestination, 0).Quaternion(); + + // Compute axis/Angle transform and initialize key points + glm::dquat flyQuat = glm::rotation( + glm::normalize(ECEFSource), + glm::normalize(ECEFDestination)); + double flyTotalAngle = glm::angle(flyQuat); + glm::dvec3 flyRotationAxis = glm::axis(flyQuat); + int steps = glm::max( + int(flyTotalAngle / glm::radians(this->FlyToGranularityDegrees)) - 1, + 0); + this->_keypoints.clear(); + this->_currentFlyTime = 0.0; + + if (flyTotalAngle == 0.0 && + this->_flyToSourceRotation == this->_flyToDestinationRotation) { + return; + } + + // We will not create a curve projected along the ellipsoid as we want to take + // altitude while flying. The radius of the current point will evolve as + // follow + // - Project the point on the ellipsoid - Will give a default radius + // depending on ellipsoid location. + // - Interpolate the altitudes : get source/destination altitude, and make a + // linear interpolation between them. This will allow for flying from/to any + // point smoothly. + // - Add as flightProfile offset /-\ defined by a curve. + + // Compute global radius at source and destination points + double sourceRadius = glm::length(ECEFSource); + glm::dvec3 sourceUpVector = ECEFSource; + + // Compute actual altitude at source and destination points by scaling on + // ellipsoid. + double sourceAltitude = 0.0, destinationAltitude = 0.0; + const CesiumGeospatial::Ellipsoid& ellipsoid = + CesiumGeospatial::Ellipsoid::WGS84; + if (auto scaled = ellipsoid.scaleToGeodeticSurface(ECEFSource)) { + sourceAltitude = glm::length(ECEFSource - *scaled); + } + if (auto scaled = ellipsoid.scaleToGeodeticSurface(ECEFDestination)) { + destinationAltitude = glm::length(ECEFDestination - *scaled); + } + + // Get distance between source and destination points to compute a wanted + // altitude from curve + double flyToDistance = glm::length(ECEFDestination - ECEFSource); + + // Add first keypoint + this->_keypoints.push_back(ECEFSource); + + for (int step = 1; step <= steps; step++) { + double percentage = (double)step / (steps + 1); + double altitude = glm::mix(sourceAltitude, destinationAltitude, percentage); + double phi = + glm::radians(this->FlyToGranularityDegrees * static_cast<double>(step)); + + glm::dvec3 rotated = glm::rotate(sourceUpVector, phi, flyRotationAxis); + if (auto scaled = ellipsoid.scaleToGeodeticSurface(rotated)) { + glm::dvec3 upVector = glm::normalize(*scaled); + + // Add an altitude if we have a profile curve for it + double offsetAltitude = 0; + if (this->FlyToAltitudeProfileCurve != NULL) { + double maxAltitude = 30000; + if (this->FlyToMaximumAltitudeCurve != NULL) { + maxAltitude = + this->FlyToMaximumAltitudeCurve->GetFloatValue(flyToDistance); + } + offsetAltitude = + maxAltitude * + this->FlyToAltitudeProfileCurve->GetFloatValue(percentage); + } + + glm::dvec3 point = *scaled + upVector * (altitude + offsetAltitude); + this->_keypoints.push_back(point); + } + } + + this->_keypoints.push_back(ECEFDestination); + + // Tell the tick we will be flying from now + this->_bFlyingToLocation = true; + this->_bCanInterruptFlight = CanInterruptByMoving; +} + +void AGlobeAwareDefaultPawn::FlyToLocationECEF( + const FVector& ECEFDestination, + double YawAtDestination, + double PitchAtDestination, + bool CanInterruptByMoving) { + + this->FlyToLocationECEF( + glm::dvec3(ECEFDestination.X, ECEFDestination.Y, ECEFDestination.Z), + YawAtDestination, + PitchAtDestination, + CanInterruptByMoving); +} + +void AGlobeAwareDefaultPawn::FlyToLocationLongitudeLatitudeHeight( + const glm::dvec3& LongitudeLatitudeHeightDestination, + double YawAtDestination, + double PitchAtDestination, + bool CanInterruptByMoving) { + + if (!IsValid(this->GetGeoreference())) { + UE_LOG( + LogCesium, + Warning, + TEXT("GlobeAwareDefaultPawn %s does not have a valid Georeference"), + *this->GetName()); + } + const glm::dvec3& ecef = + this->GetGeoreference()->TransformLongitudeLatitudeHeightToEcef( + LongitudeLatitudeHeightDestination); + this->FlyToLocationECEF( + ecef, + YawAtDestination, + PitchAtDestination, + CanInterruptByMoving); +} + +UFUNCTION(BlueprintCallable) +void AGlobeAwareDefaultPawn::FlyToLocationLongitudeLatitudeHeight( + const FVector& LongitudeLatitudeHeightDestination, + double YawAtDestination, + double PitchAtDestination, + bool CanInterruptByMoving) { + + this->FlyToLocationLongitudeLatitudeHeight( + VecMath::createVector3D(LongitudeLatitudeHeightDestination), + YawAtDestination, + PitchAtDestination, + CanInterruptByMoving); +} + +bool AGlobeAwareDefaultPawn::ShouldTickIfViewportsOnly() const { return true; } + +void AGlobeAwareDefaultPawn::_handleFlightStep(float DeltaSeconds) { + if (!IsValid(this->GlobeAnchor)) { + UE_LOG( + LogCesium, + Warning, + TEXT( + "GlobeAwareDefaultPawn %s does not have a valid GeoreferenceComponent"), + *this->GetName()); + return; + } + + if (!this->GetWorld()->IsGameWorld() || !this->_bFlyingToLocation) { + return; + } + + if (!Controller) { + return; + } + + this->_currentFlyTime += static_cast<double>(DeltaSeconds); + + // double check that we don't have an empty list of keypoints + if (this->_keypoints.size() == 0) { + this->_bFlyingToLocation = false; + return; + } + + // If we reached the end, set actual destination location and orientation + if (this->_currentFlyTime >= this->FlyToDuration) { + const glm::dvec3& finalPoint = _keypoints.back(); + this->GlobeAnchor->MoveToECEF(finalPoint); + Controller->SetControlRotation(this->_flyToDestinationRotation.Rotator()); + this->_bFlyingToLocation = false; + this->_currentFlyTime = 0.0; + + // Trigger callback accessible from BP + UE_LOG(LogCesium, Verbose, TEXT("Broadcasting OnFlightComplete")); + OnFlightComplete.Broadcast(); + + return; + } + + // We're currently in flight. Interpolate the position and orientation: + + double rawPercentage = this->_currentFlyTime / this->FlyToDuration; + + // In order to accelerate at start and slow down at end, we use a progress + // profile curve + double flyPercentage = rawPercentage; + if (this->FlyToProgressCurve != NULL) { + flyPercentage = glm::clamp( + static_cast<double>( + this->FlyToProgressCurve->GetFloatValue(rawPercentage)), + 0.0, + 1.0); + } + + // Find the keypoint indexes corresponding to the current percentage + int lastIndex = static_cast<int>( + glm::floor(flyPercentage * (this->_keypoints.size() - 1))); + double segmentPercentage = + flyPercentage * (this->_keypoints.size() - 1) - lastIndex; + int nextIndex = lastIndex + 1; + + // Get the current position by interpolating linearly between those two points + const glm::dvec3& lastPosition = this->_keypoints[lastIndex]; + const glm::dvec3& nextPosition = this->_keypoints[nextIndex]; + glm::dvec3 currentPosition = + glm::mix(lastPosition, nextPosition, segmentPercentage); + // Set Location + this->GlobeAnchor->MoveToECEF(currentPosition); + + // 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->_flyToSourceRotation, + this->_flyToDestinationRotation, + flyPercentage); + Controller->SetControlRotation(currentQuat.Rotator()); +} + +void AGlobeAwareDefaultPawn::Tick(float DeltaSeconds) { + Super::Tick(DeltaSeconds); + + _handleFlightStep(DeltaSeconds); +} + +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); + } + } +} + +ACesiumGeoreference* AGlobeAwareDefaultPawn::GetGeoreference() const { + if (!IsValid(this->GlobeAnchor)) { + UE_LOG( + LogCesium, + Error, + TEXT("GlobeAwareDefaultPawn %s does not have a GlobeAnchorComponent"), + *this->GetName()); + return nullptr; + } + return this->GlobeAnchor->ResolveGeoreference(); +} + +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); + + if (this->_bFlyingToLocation && this->_bCanInterruptFlight) { + this->_interruptFlight(); + } +} + +void AGlobeAwareDefaultPawn::_interruptFlight() { + if (!Controller) { + return; + } + + this->_bFlyingToLocation = false; + + // fix camera roll to 0.0 + FRotator currentRotator = Controller->GetControlRotation(); + currentRotator.Roll = 0.0; + Controller->SetControlRotation(currentRotator); + + // Trigger callback accessible from BP + UE_LOG(LogCesium, Verbose, TEXT("Broadcasting OnFlightInterrupt")); + OnFlightInterrupt.Broadcast(); +} diff --git a/Plugins/CesiumForUnreal/Source/CesiumRuntime/Private/LoadGltfResult.h b/Plugins/CesiumForUnreal/Source/CesiumRuntime/Private/LoadGltfResult.h new file mode 100644 index 0000000000000000000000000000000000000000..7b4f5cb085ca22e4af9ccbba16c39807a81cdf4a --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/CesiumRuntime/Private/LoadGltfResult.h @@ -0,0 +1,72 @@ +// Copyright 2020-2021 CesiumGS, Inc. and Contributors + +#pragma once + +#include "CesiumEncodedMetadataUtility.h" +#include "CesiumGltf/Material.h" +#include "CesiumGltf/MeshPrimitive.h" +#include "CesiumGltf/Model.h" +#include "CesiumMetadataModel.h" +#include "CesiumMetadataPrimitive.h" +#include "CesiumRasterOverlays.h" +#include "CesiumTextureUtility.h" +#include "Chaos/TriangleMeshImplicitObject.h" +#include "Containers/Map.h" +#include "Containers/UnrealString.h" +#include "StaticMeshResources.h" +#include "Templates/SharedPointer.h" +#include <cstdint> +#include <glm/mat4x4.hpp> +#include <optional> +#include <string> +#include <unordered_map> + +// TODO: internal documentation +namespace LoadGltfResult { +struct LoadPrimitiveResult { + FCesiumMetadataPrimitive Metadata{}; + CesiumEncodedMetadataUtility::EncodedMetadataPrimitive EncodedMetadata{}; + TMap<FString, uint32_t> metadataTextureCoordinateParameters; + TUniquePtr<FStaticMeshRenderData> RenderData = nullptr; + const CesiumGltf::Model* pModel = nullptr; + const CesiumGltf::MeshPrimitive* pMeshPrimitive = nullptr; + const CesiumGltf::Material* pMaterial = nullptr; + glm::dmat4x4 transform{1.0}; + TSharedPtr<Chaos::FTriangleMeshImplicitObject, ESPMode::ThreadSafe> + pCollisionMesh = nullptr; + std::string name{}; + + TUniquePtr<CesiumTextureUtility::LoadedTextureResult> baseColorTexture; + TUniquePtr<CesiumTextureUtility::LoadedTextureResult> + metallicRoughnessTexture; + TUniquePtr<CesiumTextureUtility::LoadedTextureResult> normalTexture; + TUniquePtr<CesiumTextureUtility::LoadedTextureResult> emissiveTexture; + TUniquePtr<CesiumTextureUtility::LoadedTextureResult> occlusionTexture; + TUniquePtr<CesiumTextureUtility::LoadedTextureResult> waterMaskTexture; + std::unordered_map<std::string, uint32_t> textureCoordinateParameters; + + bool onlyLand = true; + bool onlyWater = false; + + double waterMaskTranslationX = 0.0; + double waterMaskTranslationY = 0.0; + double waterMaskScale = 1.0; + + OverlayTextureCoordinateIDMap overlayTextureCoordinateIDToUVIndex{}; + std::unordered_map<uint32_t, uint32_t> textureCoordinateMap; +}; + +struct LoadMeshResult { + std::vector<LoadPrimitiveResult> primitiveResults{}; +}; + +struct LoadNodeResult { + std::optional<LoadMeshResult> meshResult = std::nullopt; +}; + +struct LoadModelResult { + std::vector<LoadNodeResult> nodeResults{}; + FCesiumMetadataModel Metadata{}; + CesiumEncodedMetadataUtility::EncodedMetadata EncodedMetadata{}; +}; +} // namespace LoadGltfResult diff --git a/Plugins/CesiumForUnreal/Source/CesiumRuntime/Private/PCH.h b/Plugins/CesiumForUnreal/Source/CesiumRuntime/Private/PCH.h new file mode 100644 index 0000000000000000000000000000000000000000..2829f03f5f4810e15ce6ecf977f2ad531542c059 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/CesiumRuntime/Private/PCH.h @@ -0,0 +1,20 @@ +// Copyright 2020-2021 CesiumGS, Inc. and Contributors + +#pragma once + +#define _SILENCE_CXX17_CODECVT_HEADER_DEPRECATION_WARNING +#include "CoreMinimal.h" + +// Workaround for an unhelpful warning (that gets treated as an error) in +// VS2017. See https://github.com/akrzemi1/Optional/issues/57 and +// https://answers.unrealengine.com/questions/607946/anonymous-union-with-none-trivial-type.html +#ifdef _MSC_VER +#if _MSC_VER < 1920 +#pragma warning(push) +#pragma warning(disable : 4583) +#pragma warning(disable : 4582) +#include <optional> +#include <variant> +#pragma warning(pop) +#endif +#endif diff --git a/Plugins/CesiumForUnreal/Source/CesiumRuntime/Private/ScreenCreditsWidget.cpp b/Plugins/CesiumForUnreal/Source/CesiumRuntime/Private/ScreenCreditsWidget.cpp new file mode 100644 index 0000000000000000000000000000000000000000..070caecaf8022e5db4f6f95f9b6de82c8dbc4dec --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/CesiumRuntime/Private/ScreenCreditsWidget.cpp @@ -0,0 +1,294 @@ +// Copyright 2020-2021 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 <string> +#include <vector> + +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<FSlateHyperlinkRun::FWidgetViewModel> 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<SWidget> 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<ITextDecorator> +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<UFont> 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<UCreditsDecorator*>(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<UCreditsDecorator*>( + RichTextPopup->GetDecoratorByClass(UCreditsDecorator::StaticClass())); + + _decoratorPopup->CreditsWidget = this; + } +} + +void UScreenCreditsWidget::HandleImageRequest( + FHttpRequestPtr HttpRequest, + FHttpResponsePtr HttpResponse, + bool bSucceeded, + int32 id) { + if (bSucceeded && HttpResponse.IsValid() && + HttpResponse->GetContentLength() > 0) { + UTexture2D* texture = + FImageUtils::ImportBufferAsTexture2D(HttpResponse->GetContent()); + texture->SRGB = true; + texture->UpdateResource(); + _textures.Add(texture); +#if ENGINE_MAJOR_VERSION >= 5 + FTexturePlatformData* pPlatformData = texture->GetPlatformData(); + int32 SizeX = pPlatformData->SizeX; + int32 SizeY = pPlatformData->SizeY; +#else + int32 SizeX = texture->PlatformData->SizeX; + int32 SizeY = texture->PlatformData->SizeY; +#endif + _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); + } + return; + } else { + --_numImagesLoading; + } +} + +std::string UScreenCreditsWidget::LoadImage(const std::string& url) { + const std::string base64Prefix = "data:image/png;base64,"; + if (url.rfind(base64Prefix, 0) == 0) { + TArray<uint8> 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); +#if ENGINE_MAJOR_VERSION >= 5 + FTexturePlatformData* pPlatformData = texture->GetPlatformData(); + int32 SizeX = pPlatformData->SizeX; + int32 SizeY = pPlatformData->SizeY; +#else + int32 SizeX = texture->PlatformData->SizeX; + int32 SizeY = texture->PlatformData->SizeY; +#endif + _creditImages.Add(new FSlateImageBrush(texture, FVector2D(SizeX, SizeY))); + } + } else { + ++_numImagesLoading; + TSharedRef<IHttpRequest, ESPMode::ThreadSafe> 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 0000000000000000000000000000000000000000..fc5810bf88bca679430e34f24ce261201bb46c32 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/CesiumRuntime/Private/ScreenCreditsWidget.h @@ -0,0 +1,77 @@ +// Copyright 2020-2021 CesiumGS, Inc. and Contributors + +#pragma once + +#include "Blueprint/UserWidget.h" +#include "Components/RichTextBlockDecorator.h" +#include "CoreMinimal.h" +#include "Interfaces/IHttpRequest.h" +#include <memory> +#include <string> +#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<UTexture2D*> _textures; + + FString _credits = ""; + FString _onScreenCredits = ""; + bool _showPopup = false; + class UCreditsDecorator* _decoratorOnScreen; + class UCreditsDecorator* _decoratorPopup; + int32 _numImagesLoading; + FSlateFontInfo _font; + TArray<FSlateBrush*> _creditImages; + friend class UCreditsDecorator; +}; + +UCLASS() +class UCreditsDecorator : public URichTextBlockDecorator { + GENERATED_BODY() + +public: + UCreditsDecorator(const FObjectInitializer& ObjectInitializer); + + virtual TSharedPtr<ITextDecorator> + 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 0000000000000000000000000000000000000000..45f2f36b04ff2925e836e9e58f28e3554a662902 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/CesiumRuntime/Private/SpdlogUnrealLoggerSink.cpp @@ -0,0 +1,44 @@ +// Copyright 2020-2021 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<std::mutex> 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 0000000000000000000000000000000000000000..6a7e1bed567becba5377c8f4e867f1834e11103f --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/CesiumRuntime/Private/SpdlogUnrealLoggerSink.h @@ -0,0 +1,25 @@ +// Copyright 2020-2021 CesiumGS, Inc. and Contributors + +#pragma once + +#include "CoreMinimal.h" +#include <memory> +#include <mutex> +#include <spdlog/details/null_mutex.h> +#include <spdlog/sinks/base_sink.h> + +/** + * @brief Internal implementation of a spdlog sink that forwards the messages + * to Unreal log macros. + */ +class SpdlogUnrealLoggerSink + : public spdlog::sinks::base_sink<spdlog::details::null_mutex> { +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/UnrealAssetAccessor.cpp b/Plugins/CesiumForUnreal/Source/CesiumRuntime/Private/UnrealAssetAccessor.cpp new file mode 100644 index 0000000000000000000000000000000000000000..e8b35bbe29c7eefc2948b6fcc7ed18270264ab9d --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/CesiumRuntime/Private/UnrealAssetAccessor.cpp @@ -0,0 +1,227 @@ +// Copyright 2020-2021 CesiumGS, Inc. and Contributors + +#include "UnrealAssetAccessor.h" +#include "CesiumAsync/AsyncSystem.h" +#include "CesiumAsync/IAssetRequest.h" +#include "CesiumAsync/IAssetResponse.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 <cstddef> +#include <optional> +#include <set> + +static CesiumAsync::HttpHeaders +parseHeaders(const TArray<FString>& 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<uint16_t>(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 gsl::span<const std::byte> data() const override { + const TArray<uint8>& content = this->_pResponse->GetContent(); + return gsl::span( + reinterpret_cast<const std::byte*>(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<UnrealAssetResponse>(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<UnrealAssetResponse> _pResponse; + std::string _url; + std::string _method; + CesiumAsync::HttpHeaders _headers; +}; + +UnrealAssetAccessor::UnrealAssetAccessor() : _userAgent() { + FString OsVersion, OsSubVersion; + FPlatformMisc::GetOSVersions(OsVersion, OsSubVersion); + + IPluginManager& PluginManager = IPluginManager::Get(); + TSharedPtr<IPlugin> pCesiumPlugin = + PluginManager.FindPlugin("CesiumForUnreal"); + + FString version = "unknown"; + if (pCesiumPlugin) { + version = pCesiumPlugin->GetDescriptor().VersionName; + } + + this->_userAgent = TEXT("Mozilla/5.0 ("); + this->_userAgent += OsVersion; + this->_userAgent += " "; + this->_userAgent += FPlatformMisc::GetOSVersion(); + this->_userAgent += TEXT(") Cesium For Unreal/"); + this->_userAgent += version; + this->_userAgent += TEXT(" (Project "); + this->_userAgent += FApp::GetProjectName(); + this->_userAgent += " Engine "; + this->_userAgent += FEngineVersion::Current().ToString(); + this->_userAgent += TEXT(")"); +} + +CesiumAsync::Future<std::shared_ptr<CesiumAsync::IAssetRequest>> +UnrealAssetAccessor::get( + const CesiumAsync::AsyncSystem& asyncSystem, + const std::string& url, + const std::vector<CesiumAsync::IAssetAccessor::THeader>& headers) { + + CESIUM_TRACE_BEGIN_IN_TRACK("requestAsset"); + + const FString& userAgent = this->_userAgent; + + return asyncSystem.createFuture<std::shared_ptr<CesiumAsync::IAssetRequest>>( + [&url, &headers, &userAgent](const auto& promise) { + FHttpModule& httpModule = FHttpModule::Get(); + TSharedRef<IHttpRequest, ESPMode::ThreadSafe> pRequest = + httpModule.CreateRequest(); + pRequest->SetURL(UTF8_TO_TCHAR(url.c_str())); + + for (const CesiumAsync::IAssetAccessor::THeader& header : headers) { + pRequest->SetHeader( + UTF8_TO_TCHAR(header.first.c_str()), + UTF8_TO_TCHAR(header.second.c_str())); + } + + 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<UnrealAssetRequest>(pRequest, pResponse)); + } else { + switch (pRequest->GetStatus()) { + case EHttpRequestStatus::Failed_ConnectionError: + promise.reject(std::runtime_error("Connection failed.")); + default: + promise.reject(std::runtime_error("Request failed.")); + } + } + }); + + pRequest->ProcessRequest(); + }); +} + +CesiumAsync::Future<std::shared_ptr<CesiumAsync::IAssetRequest>> +UnrealAssetAccessor::request( + const CesiumAsync::AsyncSystem& asyncSystem, + const std::string& verb, + const std::string& url, + const std::vector<CesiumAsync::IAssetAccessor::THeader>& headers, + const gsl::span<const std::byte>& contentPayload) { + + const FString& userAgent = this->_userAgent; + + return asyncSystem.createFuture<std::shared_ptr<CesiumAsync::IAssetRequest>>( + [&verb, &url, &headers, &userAgent, &contentPayload]( + const auto& promise) { + FHttpModule& httpModule = FHttpModule::Get(); + TSharedRef<IHttpRequest, ESPMode::ThreadSafe> pRequest = + httpModule.CreateRequest(); + pRequest->SetVerb(UTF8_TO_TCHAR(verb.c_str())); + pRequest->SetURL(UTF8_TO_TCHAR(url.c_str())); + + for (const CesiumAsync::IAssetAccessor::THeader& header : headers) { + pRequest->SetHeader( + UTF8_TO_TCHAR(header.first.c_str()), + UTF8_TO_TCHAR(header.second.c_str())); + } + + pRequest->AppendToHeader(TEXT("User-Agent"), userAgent); + + pRequest->SetContent(TArray<uint8>( + reinterpret_cast<const uint8*>(contentPayload.data()), + contentPayload.size())); + + pRequest->OnProcessRequestComplete().BindLambda( + [promise]( + FHttpRequestPtr pRequest, + FHttpResponsePtr pResponse, + bool connectedSuccessfully) { + if (connectedSuccessfully) { + promise.resolve( + std::make_unique<UnrealAssetRequest>(pRequest, pResponse)); + } else { + switch (pRequest->GetStatus()) { + case EHttpRequestStatus::Failed_ConnectionError: + promise.reject(std::runtime_error("Connection failed.")); + default: + promise.reject(std::runtime_error("Request failed.")); + } + } + }); + + pRequest->ProcessRequest(); + }); +} + +void UnrealAssetAccessor::tick() noexcept { + FHttpManager& manager = FHttpModule::Get().GetHttpManager(); + manager.Tick(0.0f); +} diff --git a/Plugins/CesiumForUnreal/Source/CesiumRuntime/Private/UnrealTaskProcessor.cpp b/Plugins/CesiumForUnreal/Source/CesiumRuntime/Private/UnrealTaskProcessor.cpp new file mode 100644 index 0000000000000000000000000000000000000000..872e6137d9a3dc40e00a528d3f90ca2df5b216c5 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/CesiumRuntime/Private/UnrealTaskProcessor.cpp @@ -0,0 +1,12 @@ +// Copyright 2020-2021 CesiumGS, Inc. and Contributors + +#include "UnrealTaskProcessor.h" +#include "Async/Async.h" +#include "Misc/QueuedThreadPool.h" + +void UnrealTaskProcessor::startTask(std::function<void()> 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 0000000000000000000000000000000000000000..1e87ec4064c8046e2e768e3d8627a1549968c61c --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/CesiumRuntime/Private/VecMath.cpp @@ -0,0 +1,225 @@ +// Copyright 2020-2021 CesiumGS, Inc. and Contributors + +#include "VecMath.h" + +#include "CesiumUtility/Math.h" +#include "Math/Quat.h" +#include "Math/RotationMatrix.h" +#include <CesiumGeometry/AxisTransforms.h> +#include <glm/detail/type_quat.hpp> +#include <glm/gtc/quaternion.hpp> +#include <glm/gtx/rotate_vector.hpp> +#include <glm/gtx/transform.hpp> + +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<double>(i.X) + f.X, + static_cast<double>(i.Y) + f.Y, + static_cast<double>(i.Z) + f.Z); +} + +glm::dvec3 VecMath::add3D(const FVector& f, const FIntVector& i) noexcept { + return glm::dvec3( + static_cast<double>(f.X) + i.X, + static_cast<double>(f.Y) + i.Y, + static_cast<double>(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<double>(f.X) - i.X, + static_cast<double>(f.Y) - i.Y, + static_cast<double>(f.Z) - i.Z); +} + +glm::dvec3 VecMath::subtract3D(const FIntVector& i, const FVector& f) noexcept { + return glm::dvec3( + static_cast<double>(i.X) - f.X, + static_cast<double>(i.Y) - f.Y, + static_cast<double>(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 0000000000000000000000000000000000000000..48b25adde024fd4b0247d3a5e7c5d223e398a9b7 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/CesiumRuntime/Private/VecMath.h @@ -0,0 +1,333 @@ +// Copyright 2020-2021 CesiumGS, Inc. and Contributors + +#pragma once + +#include "Math/Matrix.h" +#include <glm/glm.hpp> + +/** + * @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; +}; diff --git a/Plugins/CesiumForUnreal/Source/CesiumRuntime/Public/Cesium3DTileset.h b/Plugins/CesiumForUnreal/Source/CesiumRuntime/Public/Cesium3DTileset.h new file mode 100644 index 0000000000000000000000000000000000000000..cadff7126d6f91b9b18774c3d5938f0712ec12e0 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/CesiumRuntime/Public/Cesium3DTileset.h @@ -0,0 +1,1115 @@ +// Copyright 2020-2021 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 "CesiumExclusionZone.h" +#include "CesiumGeoreference.h" +#include "CoreMinimal.h" +#include "CustomDepthParameters.h" +#include "Engine/EngineTypes.h" +#include "GameFramework/Actor.h" +#include "Interfaces/IHttpRequest.h" +#include "PrimitiveSceneProxy.h" +#include <PhysicsEngine/BodyInstance.h> +#include <atomic> +#include <chrono> +#include <glm/mat4x4.hpp> +#include <unordered_map> +#include <vector> +#include "Cesium3DTileset.generated.h" + +class UMaterialInterface; +class ACesiumCartographicSelection; +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&); + +/** + * 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") +}; + +UENUM(BlueprintType) +enum class EApplyDpiScaling : uint8 { Yes, No, UseProjectDefault }; + +UCLASS() +class CESIUMRUNTIME_API ACesium3DTileset : public AActor { + GENERATED_BODY() + +public: + ACesium3DTileset(); + virtual ~ACesium3DTileset(); + +private: + /** + * The component mobility to use for the tileset. + */ + UPROPERTY( + EditAnywhere, + BlueprintReadWrite, + BlueprintGetter = "GetMobility", + BlueprintSetter = "SetMobility", + Category = "Cesium", + Meta = (AllowPrivateAccess)) + TEnumAsByte<EComponentMobility::Type> Mobility = EComponentMobility::Static; + +public: + /** + * Set a component mobility to use for this tileset. + */ + UFUNCTION(BlueprintCallable, Category = "Cesium") + EComponentMobility::Type GetMobility() const { + return (EComponentMobility::Type)Mobility; + } + + /** + * Set a component mobility to use for this tileset. + */ + UFUNCTION(BlueprintCallable, Category = "Cesium") + void SetMobility(EComponentMobility::Type NewMobility); + +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)) + ACesiumGeoreference* 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, + BlueprintReadOnly, + Category = "Cesium", + Meta = (AllowPrivateAccess)) + ACesiumGeoreference* ResolvedGeoreference = nullptr; + +public: + /** @copydoc ACesium3DTileset::Georeference */ + UFUNCTION(BlueprintCallable, Category = "Cesium") + ACesiumGeoreference* GetGeoreference() const; + + /** @copydoc ACesium3DTileset::Georeference */ + UFUNCTION(BlueprintCallable, Category = "Cesium") + void SetGeoreference(ACesiumGeoreference* 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)) + ACesiumCreditSystem* 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 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, ESPMode::ThreadSafe> _cesiumViewExtension = + nullptr; + +public: + /** @copydoc ACesium3DTileset::CreditSystem */ + UFUNCTION(BlueprintCallable, Category = "Cesium") + ACesiumCreditSystem* GetCreditSystem() const; + + /** @copydoc ACesium3DTileset::CreditSystem */ + UFUNCTION(BlueprintCallable, Category = "Cesium") + void SetCreditSystem(ACesiumCreditSystem* 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; + + /** + * 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, + BlueprintReadWrite, + 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; + + PRAGMA_DISABLE_DEPRECATION_WARNINGS + + /** + * A list of rectangles that are excluded from this tileset. Any tiles that + * overlap any of these rectangles are not shown. This is a crude method to + * avoid overlapping geometry coming from different tilesets. For example, to + * exclude Cesium OSM Buildings where there are photogrammetry assets. + * + * Note that in the current version, excluded tiles are still loaded, they're + * just not displayed. Also, because the tiles shown when zoomed out cover a + * large area, using an exclusion zone often means the tileset won't be shown + * at all when zoomed out. + * + * This property is currently only supported for 3D Tiles that use "region" + * for their bounding volumes. For other tilesets it is silently ignored. + * + * This is an experimental feature and may change in future versions. + */ + UPROPERTY( + meta = + (DeprecatedProperty, + DeprecationMessage = + "Exclusion Zones have been deprecated. Please use Cartographic Polygon actor instead.")) + TArray<FCesiumExclusionZone> ExclusionZones_DEPRECATED; + + PRAGMA_ENABLE_DEPRECATION_WARNINGS + + /** + * 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; + + /** + * 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; + + /** + * The URL of the ion asset endpoint. Defaults to Cesium ion but a custom + * endpoint can be specified. + */ + UPROPERTY( + EditAnywhere, + BlueprintGetter = GetIonAssetEndpointUrl, + BlueprintSetter = SetIonAssetEndpointUrl, + Category = "Cesium", + AdvancedDisplay, + meta = (EditCondition = "TilesetSource==ETilesetSource::FromCesiumIon")) + FString IonAssetEndpointUrl; + + /** + * 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. + */ + UPROPERTY( + EditAnywhere, + BlueprintGetter = GetCreatePhysicsMeshes, + BlueprintSetter = SetCreatePhysicsMeshes, + Category = "Cesium|Physics") + bool CreatePhysicsMeshes = true; + + /** + * 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 = "PlatformName != TEXT(\"Mac\")")) + bool EnableWaterMask = 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; + +protected: + UPROPERTY() + FString PlatformName; + +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") + FString GetIonAssetEndpointUrl() const { return IonAssetEndpointUrl; } + + UFUNCTION(BlueprintSetter, Category = "Cesium") + void SetIonAssetEndpointUrl(const FString& InIonAssetEndpointUrl); + + 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|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") + 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(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. + * + * See {@link + * Cesium3DTilesetRoot::GetCesiumTilesetToUnrealRelativeWorldTransform}. + */ + const glm::dmat4& GetCesiumTilesetToUnrealRelativeWorldTransform() const; + + Cesium3DTilesSelection::Tileset* GetTileset() { + return this->_pTileset.Get(); + } + const Cesium3DTilesSelection::Tileset* GetTileset() const { + return this->_pTileset.Get(); + } + + // 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 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); + + std::vector<FCesiumCamera> GetCameras() const; + std::vector<FCesiumCamera> GetPlayerCameras() const; + std::vector<FCesiumCamera> 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: + /** + * 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<Cesium3DTilesSelection::Tile*>& 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<FCesiumCamera> 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<Cesium3DTilesSelection::Tileset> _pTileset; + + FMetadataDescription _encodedMetadataDescription; + + // For debug output + uint32_t _lastTilesRendered; + uint32_t _lastTilesLoadingLowPriority; + uint32_t _lastTilesLoadingMediumPriority; + uint32_t _lastTilesLoadingHighPriority; + bool _activeLoading; + + 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<Cesium3DTilesSelection::Tile*> _tilesToHideNextFrame; + + int32 _tilesetsBeingDestroyed; + + friend class UnrealResourcePreparer; +}; diff --git a/Plugins/CesiumForUnreal/Source/CesiumRuntime/Public/Cesium3DTilesetLoadFailureDetails.h b/Plugins/CesiumForUnreal/Source/CesiumRuntime/Public/Cesium3DTilesetLoadFailureDetails.h new file mode 100644 index 0000000000000000000000000000000000000000..2189a21507450e03f3def3a9e597c8deafb42de6 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/CesiumRuntime/Public/Cesium3DTilesetLoadFailureDetails.h @@ -0,0 +1,58 @@ +// Copyright 2020-2021 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<ACesium3DTileset> 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 0000000000000000000000000000000000000000..94c42584300ee909b79ec8687547d016d90f47aa --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/CesiumRuntime/Public/CesiumBingMapsRasterOverlay.h @@ -0,0 +1,47 @@ +// Copyright 2020-2021 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<Cesium3DTilesSelection::RasterOverlay> CreateOverlay( + const Cesium3DTilesSelection::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 0000000000000000000000000000000000000000..fbd47859c65865a8bed646c22446745d959acf81 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/CesiumRuntime/Public/CesiumCamera.h @@ -0,0 +1,93 @@ +// Copyright 2020-2021 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 Cesium3DTileset}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 0000000000000000000000000000000000000000..b1577b0304768b08a9785b347000e4b5639b50e9 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/CesiumRuntime/Public/CesiumCameraManager.h @@ -0,0 +1,69 @@ +// Copyright 2020-2021 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 Cesium3DTileset}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 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<int32, FCesiumCamera>& GetCameras() const; + + virtual bool ShouldTickIfViewportsOnly() const override; + + virtual void Tick(float DeltaTime) override; + +private: + int32 _currentCameraId = 0; + TMap<int32, FCesiumCamera> _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 0000000000000000000000000000000000000000..4121cf60fe1a5a916d6b27bf8c423556617f364f --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/CesiumRuntime/Public/CesiumCartographicPolygon.h @@ -0,0 +1,54 @@ +// Copyright 2020-2021 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 <vector> + +#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. + */ + CesiumGeospatial::CartographicPolygon CreateCartographicPolygon() const; + +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 0000000000000000000000000000000000000000..7d155bea4aeaab92c802d66f4a0787dee2bdaadf --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/CesiumRuntime/Public/CesiumCommon.h @@ -0,0 +1,17 @@ +// Copyright 2020-2022 CesiumGS, Inc. and Contributors + +#pragma once + +#include "Runtime/Launch/Resources/Version.h" + +#if ENGINE_MAJOR_VERSION >= 5 +#define CESIUM_UNREAL_ENGINE_DOUBLE 1 +#else +#define CESIUM_UNREAL_ENGINE_DOUBLE 0 +#endif + +#if CESIUM_UNREAL_ENGINE_DOUBLE +using CesiumReal = double; +#else +using CesiumReal = float; +#endif diff --git a/Plugins/CesiumForUnreal/Source/CesiumRuntime/Public/CesiumCreditSystem.h b/Plugins/CesiumForUnreal/Source/CesiumRuntime/Public/CesiumCreditSystem.h new file mode 100644 index 0000000000000000000000000000000000000000..229b08803e24ad8a37ecea0270897260156bbc3b --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/CesiumRuntime/Public/CesiumCreditSystem.h @@ -0,0 +1,73 @@ +// Copyright 2020-2021 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 <memory> +#include <unordered_map> + +#include "CesiumCreditSystem.generated.h" + +namespace Cesium3DTilesSelection { +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(); + + void BeginPlay() override; + + UPROPERTY(EditDefaultsOnly, Category = "Cesium") + TSubclassOf<UUserWidget> CreditsWidgetClass; + + /** + * Whether the credit string has changed since last frame. + */ + UPROPERTY(BlueprintReadOnly, Category = "Cesium") + bool CreditsUpdated = false; + + UPROPERTY(BlueprintReadOnly, Category = "Cesium") + class UScreenCreditsWidget* CreditsWidget; + + // Called every frame + virtual bool ShouldTickIfViewportsOnly() const override; + virtual void Tick(float DeltaTime) override; + + const std::shared_ptr<Cesium3DTilesSelection::CreditSystem>& + GetExternalCreditSystem() const { + return _pCreditSystem; + } + +private: + static UClass* 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<Cesium3DTilesSelection::CreditSystem> _pCreditSystem; + + size_t _lastCreditsCount; + + FString ConvertHtmlToRtf(std::string html); + std::unordered_map<std::string, FString> _htmlToRtf; +}; diff --git a/Plugins/CesiumForUnreal/Source/CesiumRuntime/Public/CesiumCustomVersion.h b/Plugins/CesiumForUnreal/Source/CesiumRuntime/Public/CesiumCustomVersion.h new file mode 100644 index 0000000000000000000000000000000000000000..9e69865564f616b29ec1926c14dc069dea75dcda --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/CesiumRuntime/Public/CesiumCustomVersion.h @@ -0,0 +1,26 @@ +// Copyright 2020-2021 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, + + 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 0000000000000000000000000000000000000000..c2c49fff1a85ca17a20eea977b9406909c7267cf --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/CesiumRuntime/Public/CesiumDebugColorizeTilesRasterOverlay.h @@ -0,0 +1,26 @@ +// Copyright 2020-2021 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<Cesium3DTilesSelection::RasterOverlay> CreateOverlay( + const Cesium3DTilesSelection::RasterOverlayOptions& options = {}) + override; +}; diff --git a/Plugins/CesiumForUnreal/Source/CesiumRuntime/Public/CesiumEncodedMetadataComponent.h b/Plugins/CesiumForUnreal/Source/CesiumRuntime/Public/CesiumEncodedMetadataComponent.h new file mode 100644 index 0000000000000000000000000000000000000000..930b88f98c2a8c80ce1a86398178840f862a3ebc --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/CesiumRuntime/Public/CesiumEncodedMetadataComponent.h @@ -0,0 +1,290 @@ +// Copyright 2020-2021 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" + +/** + * @brief The GPU component type to coerce this property to. + * + */ +UENUM() +enum class ECesiumPropertyComponentType : uint8 { Uint8, Float }; + +/** + * @brief The property type. + */ +UENUM() +enum class ECesiumPropertyType : uint8 { Scalar, Vec2, Vec3, Vec4 }; + +/** + * @brief Describes how this feature table is accessed. Either through feature + * id textures, feature id attributes, mixed, or neither. + */ +UENUM() +enum class ECesiumFeatureTableAccessType : uint8 { + Unknown, + Texture, + Attribute, + Mixed +}; + +// 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. + +/** + * @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 ComponentType = + ECesiumPropertyComponentType::Float; + + /** + * @brief The property type. + */ + UPROPERTY(EditAnywhere, Category = "Cesium") + ECesiumPropertyType Type = ECesiumPropertyType::Scalar; + + /** + * @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::Uint8")) + bool Normalized = false; +}; + +/** + * @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 AccessType = + ECesiumFeatureTableAccessType::Unknown; + + /** + * @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::Texture")) + FString Channel; + + /** + * @brief Descriptions of the properties to upload to the GPU. + */ + UPROPERTY(EditAnywhere, Category = "Cesium", Meta = (TitleProperty = "Name")) + TArray<FPropertyDescription> Properties; +}; + +/** + * @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 Type = ECesiumPropertyType::Scalar; + + /** + * @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; +}; + +/** + * @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<FFeatureTexturePropertyDescription> Properties; +}; + +/** + * @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<FFeatureTableDescription> FeatureTables; + + /** + * @brief Descriptions of feature textures to upload to the GPU. + */ + UPROPERTY( + EditAnywhere, + Category = "EncodeMetadata", + Meta = (TitleProperty = "Name")) + TArray<FFeatureTextureDescription> 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(ClassGroup = (Cesium), Meta = (BlueprintSpawnableComponent)) +class CESIUMRUNTIME_API UCesiumEncodedMetadataComponent + : public UActorComponent { + GENERATED_BODY() + +public: + /** + * @brief This button can be used to pre-populate the description of metadata + * to encode based on the existing metadata in the current tiles. + * + * 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 = "EncodeMetadata") + void AutoFill(); + +#if WITH_EDITOR + /** + * @brief 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 metada will be added to TargetMaterialLayer if it + * exists. Otherwise a new material layer will be created in the /Game/ + * folder and TargetMaterialLayer will be set to the new material layer. + */ + UFUNCTION(CallInEditor, Category = "EncodeMetadata") + void GenerateMaterial(); +#endif + +#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") + 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")) + TArray<FFeatureTableDescription> FeatureTables; + + /** + * @brief Descriptions of feature textures to upload to the GPU. + */ + UPROPERTY( + EditAnywhere, + Category = "EncodeMetadata", + Meta = (TitleProperty = "Name")) + TArray<FFeatureTextureDescription> FeatureTextures; +}; diff --git a/Plugins/CesiumForUnreal/Source/CesiumRuntime/Public/CesiumExclusionZone.h b/Plugins/CesiumForUnreal/Source/CesiumRuntime/Public/CesiumExclusionZone.h new file mode 100644 index 0000000000000000000000000000000000000000..2ab7fdfe6852f2764529574302426bd016d18601 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/CesiumRuntime/Public/CesiumExclusionZone.h @@ -0,0 +1,78 @@ +// Copyright 2020-2021 CesiumGS, Inc. and Contributors + +#pragma once + +#include "CoreMinimal.h" + +#include "CesiumExclusionZone.generated.h" + +struct UE_DEPRECATED( + 4.26, + "Exclusion Zones have been deprecated. Please use Cartographic Polygon actor instead.") + FCesiumExclusionZone; + +/** + * A region that should be excluded from a tileset. + * + * This is **experimental**, and may change in future releases. + */ +USTRUCT() +struct CESIUMRUNTIME_API FCesiumExclusionZone { + GENERATED_BODY() + + /** + * The southernmost latitude, in degrees, in the range [-90, 90] + */ + UPROPERTY( + EditAnywhere, + Category = "Cesium", + meta = + (Deprecated, + DeprecationMessage = + "Exclusion Zones have been deprecated. Please use Cartographic Polygon actor instead.", + ClampMin = -90.0, + ClampMax = 90.0)) + double South = 0.0; + + /** + * The westernmost longitude, in degrees, in the range [-180, 180] + */ + UPROPERTY( + EditAnywhere, + Category = "Cesium", + meta = + (Deprecated, + DeprecationMessage = + "Exclusion Zones have been deprecated. Please use Cartographic Polygon actor instead.", + ClampMin = -180.0, + ClampMax = 180.0)) + double West = 0.0; + + /** + * The northernmost latitude, in degrees, in the range [-90, 90] + */ + UPROPERTY( + EditAnywhere, + Category = "Cesium", + meta = + (Deprecated, + DeprecationMessage = + "Exclusion Zones have been deprecated. Please use Cartographic Polygon actor instead.", + ClampMin = -90.0, + ClampMax = 90.0)) + double North = 0.0; + + /** + * The easternmost longitude, in degrees, in the range [-180, 180] + */ + UPROPERTY( + EditAnywhere, + Category = "Cesium", + meta = + (Deprecated, + DeprecationMessage = + "Exclusion Zones have been deprecated. Please use Cartographic Polygon actor instead.", + ClampMin = -180.0, + ClampMax = 180.0)) + double East = 0.0; +}; diff --git a/Plugins/CesiumForUnreal/Source/CesiumRuntime/Public/CesiumFeatureIdAttribute.h b/Plugins/CesiumForUnreal/Source/CesiumRuntime/Public/CesiumFeatureIdAttribute.h new file mode 100644 index 0000000000000000000000000000000000000000..163a83fe0e495d3901f5a6a7e2c6b0150efe3152 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/CesiumRuntime/Public/CesiumFeatureIdAttribute.h @@ -0,0 +1,94 @@ +// Copyright 2020-2021 CesiumGS, Inc. and Contributors + +#pragma once + +#include "CesiumFeatureTable.h" +#include "CesiumGltf/AccessorView.h" +#include "Kismet/BlueprintFunctionLibrary.h" +#include "CesiumFeatureIdAttribute.generated.h" + +namespace CesiumGltf { +struct Model; +struct Accessor; +struct FeatureTable; +} // namespace CesiumGltf + +/** + * @brief A blueprint-accessible wrapper for a feature id attribute from a glTF + * primitive. Provides access to per-vertex feature IDs which can be used with + * the corresponding {@link FCesiumFeatureTable} to access per-vertex metadata. + */ +USTRUCT(BlueprintType) +struct CESIUMRUNTIME_API FCesiumFeatureIdAttribute { + GENERATED_USTRUCT_BODY() + + using FeatureIDAccessorType = std::variant< + std::monostate, + CesiumGltf::AccessorView<CesiumGltf::AccessorTypes::SCALAR<int8_t>>, + CesiumGltf::AccessorView<CesiumGltf::AccessorTypes::SCALAR<uint8_t>>, + CesiumGltf::AccessorView<CesiumGltf::AccessorTypes::SCALAR<int16_t>>, + CesiumGltf::AccessorView<CesiumGltf::AccessorTypes::SCALAR<uint16_t>>, + CesiumGltf::AccessorView<CesiumGltf::AccessorTypes::SCALAR<uint32_t>>, + CesiumGltf::AccessorView<CesiumGltf::AccessorTypes::SCALAR<float>>>; + +public: + FCesiumFeatureIdAttribute() {} + + FCesiumFeatureIdAttribute( + const CesiumGltf::Model& Model, + const CesiumGltf::Accessor& FeatureIDAccessor, + const int32 attributeIndex, + const FString& FeatureTableName); + + int32 getAttributeIndex() const { return this->_attributeIndex; } + +private: + FeatureIDAccessorType _featureIDAccessor; + FString _featureTableName; + int32 _attributeIndex; + + friend class UCesiumFeatureIdAttributeBlueprintLibrary; +}; + +UCLASS() +class CESIUMRUNTIME_API UCesiumFeatureIdAttributeBlueprintLibrary + : public UBlueprintFunctionLibrary { + GENERATED_BODY() +public: + /** + * @brief Get the name of the feature table corresponding to this feature ID + * attribute. The name can be used to fetch the appropriate + * {@link FCesiumFeatureTable} from the {@link FCesiumMetadataModel}. + */ + UFUNCTION( + BlueprintCallable, + BlueprintPure, + Category = "Cesium|Metadata|FeatureIdAttribute") + static const FString& + GetFeatureTableName(UPARAM(ref) + const FCesiumFeatureIdAttribute& FeatureIdAttribute); + + /** + * @brief Get the number of vertices this primitive has. + */ + UFUNCTION( + BlueprintCallable, + BlueprintPure, + Category = "Cesium|Metadata|FeatureIdAttribute") + static int64 + GetVertexCount(UPARAM(ref) + const FCesiumFeatureIdAttribute& FeatureIdAttribute); + + /** + * Gets the feature ID associated with a given vertex. The feature ID can be + * used with a {@link FCesiumFeatureTable} to retrieve the per-vertex + * metadata. + */ + UFUNCTION( + BlueprintCallable, + BlueprintPure, + Category = "Cesium|Metadata|FeatureIdAttribute") + static int64 GetFeatureIDForVertex( + UPARAM(ref) const FCesiumFeatureIdAttribute& FeatureIdAttribute, + int64 VertexIndex); +}; diff --git a/Plugins/CesiumForUnreal/Source/CesiumRuntime/Public/CesiumFeatureIdTexture.h b/Plugins/CesiumForUnreal/Source/CesiumRuntime/Public/CesiumFeatureIdTexture.h new file mode 100644 index 0000000000000000000000000000000000000000..002244e35ecdbb7813f66de7952a6c2005a80097 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/CesiumRuntime/Public/CesiumFeatureIdTexture.h @@ -0,0 +1,89 @@ +// Copyright 2020-2021 CesiumGS, Inc. and Contributors + +#pragma once + +#include "CesiumFeatureTable.h" +#include "CesiumGltf/FeatureIDTextureView.h" +#include "Containers/UnrealString.h" +#include "Kismet/BlueprintFunctionLibrary.h" +#include "CesiumFeatureIdTexture.generated.h" + +namespace CesiumGltf { +struct Model; +struct FeatureIDTexture; +} // namespace CesiumGltf + +/** + * @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 FCesiumFeatureTable} to access per-pixel metadata. + */ +USTRUCT(BlueprintType) +struct CESIUMRUNTIME_API FCesiumFeatureIdTexture { + GENERATED_USTRUCT_BODY() + +public: + FCesiumFeatureIdTexture() {} + + FCesiumFeatureIdTexture( + const CesiumGltf::Model& model, + const CesiumGltf::FeatureIDTexture& featureIdTexture); + + constexpr const CesiumGltf::FeatureIDTextureView& + getFeatureIdTextureView() const { + return this->_featureIdTextureView; + } + +private: + CesiumGltf::FeatureIDTextureView _featureIdTextureView; + FString _featureTableName; + + friend class UCesiumFeatureIdTextureBlueprintLibrary; +}; + +UCLASS() +class CESIUMRUNTIME_API UCesiumFeatureIdTextureBlueprintLibrary + : public UBlueprintFunctionLibrary { + GENERATED_BODY() + +public: + /** + * @brief Get the name of the feature table corresponding to this feature ID + * texture. The name can be used to fetch the appropriate + * {@link FCesiumFeatureTable} from the {@link FCesiumMetadataModel}. + */ + UFUNCTION( + BlueprintCallable, + BlueprintPure, + Category = "Cesium|Metadata|FeatureIdTexture") + static const FString& + GetFeatureTableName(UPARAM(ref) + const FCesiumFeatureIdTexture& featureIdTexture); + + /** + * @brief Get the index of the texture coordinate set that corresponds to the + * feature id texture. + */ + UFUNCTION( + BlueprintCallable, + BlueprintPure, + Category = "Cesium|Metadata|FeatureIdTexture") + static int64 GetTextureCoordinateIndex( + const UPrimitiveComponent* component, + UPARAM(ref) const FCesiumFeatureIdTexture& featureIdTexture); + + /** + * @brief Given texture coordinates from the appropriate texture coordinate + * set (as indicated by GetTextureCoordinateIndex), returns a feature ID + * corresponding the pixel. The feature ID can be used with a + * {@link FCesiumFeatureTable} to retrieve the per-vertex metadata. + */ + UFUNCTION( + BlueprintCallable, + BlueprintPure, + Category = "Cesium|Metadata|FeatureIdTexture") + static int64 GetFeatureIdForTextureCoordinates( + UPARAM(ref) const FCesiumFeatureIdTexture& featureIdTexture, + float u, + float v); +}; diff --git a/Plugins/CesiumForUnreal/Source/CesiumRuntime/Public/CesiumFeatureTable.h b/Plugins/CesiumForUnreal/Source/CesiumRuntime/Public/CesiumFeatureTable.h new file mode 100644 index 0000000000000000000000000000000000000000..dd64852331d3ff2f42e615a9c96839fc26737b8d --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/CesiumRuntime/Public/CesiumFeatureTable.h @@ -0,0 +1,100 @@ +// Copyright 2020-2021 CesiumGS, Inc. and Contributors + +#pragma once + +#include "CesiumMetadataGenericValue.h" +#include "CesiumMetadataProperty.h" +#include "Kismet/BlueprintFunctionLibrary.h" +#include "UObject/ObjectMacros.h" +#include "CesiumFeatureTable.generated.h" + +namespace CesiumGltf { +struct Model; +struct FeatureTable; +} // namespace CesiumGltf + +/** + * A Blueprint-accessible wrapper for a glTF feature table. A feature table is a + * collection of properties for each feature ID in the mesh. It also knows how + * to look up the feature ID associated with a given mesh vertex. + */ +USTRUCT(BlueprintType) +struct CESIUMRUNTIME_API FCesiumFeatureTable { + GENERATED_USTRUCT_BODY() + +public: + /** + * Construct an empty feature table. + */ + FCesiumFeatureTable(){}; + + /** + * Constructs a feature table from a glTF Feature Table. + * + * @param Model The model that stores EXT_feature_metadata. + * @param FeatureTable The feature table that is paired with the feature ID. + */ + FCesiumFeatureTable( + const CesiumGltf::Model& Model, + const CesiumGltf::FeatureTable& FeatureTable); + +private: + TMap<FString, FCesiumMetadataProperty> _properties; + + friend class UCesiumFeatureTableBlueprintLibrary; +}; + +UCLASS() +class CESIUMRUNTIME_API UCesiumFeatureTableBlueprintLibrary + : public UBlueprintFunctionLibrary { + GENERATED_BODY() + +public: + /** + * Gets the number of features in the feature table. + */ + UFUNCTION( + BlueprintCallable, + BlueprintPure, + Category = "Cesium|Metadata|FeatureTable") + static int64 GetNumberOfFeatures(UPARAM(ref) + const FCesiumFeatureTable& FeatureTable); + + /** + * Gets a map of property name to property value for a given feature. + * + * @param featureID The ID of the feature. + */ + UFUNCTION( + BlueprintCallable, + BlueprintPure, + Category = "Cesium|Metadata|FeatureTable") + static TMap<FString, FCesiumMetadataGenericValue> + GetMetadataValuesForFeatureID( + UPARAM(ref) const FCesiumFeatureTable& FeatureTable, + int64 FeatureID); + + /** + * Gets a map of property name to property value for a given feature, where + * the value is converted to a string regardless of the underlying type. + * + * @param FeatureID The ID of the feature. + */ + UFUNCTION( + BlueprintCallable, + BlueprintPure, + Category = "Cesium|Metadata|FeatureTable") + static TMap<FString, FString> GetMetadataValuesAsStringForFeatureID( + UPARAM(ref) const FCesiumFeatureTable& featureTable, + int64 FeatureID); + + /** + * Gets all the properties of the feature table. + */ + UFUNCTION( + BlueprintCallable, + BlueprintPure, + Category = "Cesium|Metadata|FeatureTable") + static const TMap<FString, FCesiumMetadataProperty>& + GetProperties(UPARAM(ref) const FCesiumFeatureTable& FeatureTable); +}; diff --git a/Plugins/CesiumForUnreal/Source/CesiumRuntime/Public/CesiumFeatureTexture.h b/Plugins/CesiumForUnreal/Source/CesiumRuntime/Public/CesiumFeatureTexture.h new file mode 100644 index 0000000000000000000000000000000000000000..5e4d952ff4a3de9d56e194e984ce25f0704332ef --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/CesiumRuntime/Public/CesiumFeatureTexture.h @@ -0,0 +1,74 @@ +// Copyright 2020-2021 CesiumGS, Inc. and Contributors + +#pragma once + +#include "CesiumFeatureTextureProperty.h" +#include "CesiumGltf/FeatureTextureView.h" +#include "Containers/Array.h" +#include "Kismet/BlueprintFunctionLibrary.h" +#include "CesiumFeatureTexture.generated.h" + +namespace CesiumGltf { +struct Model; +struct FeatureTexture; +}; // namespace CesiumGltf + +/** + * @brief A blueprint-accessible wrapper of a feature texture from a glTF. + * Provides access to {@link FCesiumFeatureTextureProperty} views of texture + * metadata. + */ +USTRUCT(BlueprintType) +struct CESIUMRUNTIME_API FCesiumFeatureTexture { + GENERATED_USTRUCT_BODY() + +public: + FCesiumFeatureTexture() {} + + FCesiumFeatureTexture( + const CesiumGltf::Model& model, + const CesiumGltf::FeatureTexture& featureTexture); + + const CesiumGltf::FeatureTextureView& getFeatureTextureView() const { + return this->_featureTextureView; + } + +private: + CesiumGltf::FeatureTextureView _featureTextureView; + TArray<FString> _propertyKeys; + + friend class UCesiumFeatureTextureBlueprintLibrary; +}; + +UCLASS() +class CESIUMRUNTIME_API UCesiumFeatureTextureBlueprintLibrary + : public UBlueprintFunctionLibrary { + GENERATED_BODY() + +public: + /** + * @brief Gets an array of property names corresponding to + * {@link FCesiumFeatureTextureProperty} views. These property names can be + * used with FindProperty to retrieve the corresponding + * {@link FCesiumFeatureTextureProperty} views. + */ + UFUNCTION( + BlueprintCallable, + BlueprintPure, + Category = "Cesium|Metadata|FeatureTexture") + static const TArray<FString>& + GetPropertyKeys(UPARAM(ref) const FCesiumFeatureTexture& FeatureTexture); + + /** + * @brief Retrieve a {@link FCesiumFeatureTextureProperty} by name. Use + * GetPropertyKeys to get a list of names for existing feature texture + * properties. + */ + UFUNCTION( + BlueprintCallable, + BlueprintPure, + Category = "Cesium|Metadata|FeatureTexture") + static FCesiumFeatureTextureProperty FindProperty( + UPARAM(ref) const FCesiumFeatureTexture& FeatureTexture, + const FString& PropertyName); +}; diff --git a/Plugins/CesiumForUnreal/Source/CesiumRuntime/Public/CesiumFeatureTextureProperty.h b/Plugins/CesiumForUnreal/Source/CesiumRuntime/Public/CesiumFeatureTextureProperty.h new file mode 100644 index 0000000000000000000000000000000000000000..d8b2f6f69b76eaac54541c97ea77983bf91cd999 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/CesiumRuntime/Public/CesiumFeatureTextureProperty.h @@ -0,0 +1,159 @@ +// Copyright 2020-2021 CesiumGS, Inc. and Contributors + +#pragma once + +#include "CesiumGltf/FeatureTexturePropertyView.h" +#include "GenericPlatform/GenericPlatform.h" +#include "Kismet/BlueprintFunctionLibrary.h" +#include "CesiumFeatureTextureProperty.generated.h" + +/** + * @brief An integer color retrieved from a + * {@link FCesiumFeatureTextureProperty}. + */ +USTRUCT(BlueprintType) +struct CESIUMRUNTIME_API FCesiumIntegerColor { + GENERATED_USTRUCT_BODY() + +public: + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Cesium") + int32 r = 0; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Cesium") + int32 g = 0; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Cesium") + int32 b = 0; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Cesium") + int32 a = 0; +}; + +/** + * @brief An float color retrieved from a + * {@link FCesiumFeatureTextureProperty}. + */ +USTRUCT(BlueprintType) +struct CESIUMRUNTIME_API FCesiumFloatColor { + GENERATED_USTRUCT_BODY() + +public: + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Cesium") + float r = 0.0f; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Cesium") + float g = 0.0f; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Cesium") + float b = 0.0f; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Cesium") + float a = 0.0f; +}; + +/** + * @brief A blueprint-accessible wrapper for a feature texture property from a + * glTF. Provides per-pixel access to metadata encoded as pixel color. + */ +USTRUCT(BlueprintType) +struct CESIUMRUNTIME_API FCesiumFeatureTextureProperty { + GENERATED_USTRUCT_BODY() + +public: + FCesiumFeatureTextureProperty() {} + + FCesiumFeatureTextureProperty( + const CesiumGltf::FeatureTexturePropertyView& property) + : _pProperty(&property) {} + +private: + const CesiumGltf::FeatureTexturePropertyView* _pProperty; + + friend class UCesiumFeatureTexturePropertyBlueprintLibrary; +}; + +UCLASS() +class CESIUMRUNTIME_API UCesiumFeatureTexturePropertyBlueprintLibrary + : public UBlueprintFunctionLibrary { + GENERATED_BODY() + +public: + /** + * @brief Get the index of the texture coordinate set that corresponds to the + * feature texture property. + */ + UFUNCTION( + BlueprintCallable, + BlueprintPure, + Category = "Cesium|Metadata|FeatureTextureProperty") + static int64 GetTextureCoordinateIndex( + const UPrimitiveComponent* component, + UPARAM(ref) const FCesiumFeatureTextureProperty& 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. + */ + UFUNCTION( + BlueprintCallable, + BlueprintPure, + Category = "Cesium|Metadata|FeatureTextureProperty") + static int64 + GetComponentCount(UPARAM(ref) const FCesiumFeatureTextureProperty& property); + + /** + * @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. + */ + UFUNCTION( + BlueprintCallable, + BlueprintPure, + Category = "Cesium|Metadata|FeatureTextureProperty") + static FString GetSwizzle(UPARAM(ref) + const FCesiumFeatureTextureProperty& property); + + /** + * @brief Whether the metadata components are to be interpreted as + * normalized. This only applies when the metadata components have an integer + * type. + */ + UFUNCTION( + BlueprintCallable, + BlueprintPure, + Category = "Cesium|Metadata|FeatureTextureProperty") + static bool IsNormalized(UPARAM(ref) + const FCesiumFeatureTextureProperty& property); + + /** + * @brief Given texture coordinates from the appropriate texture coordinate + * set (as indicated by GetTextureCoordinateIndex), returns an integer-based + * metadata value for the pixel. This automatically unswizzles the pixel + * color as needed. Only the first GetComponentCount channels are to be used. + */ + UFUNCTION( + BlueprintCallable, + BlueprintPure, + Category = "Cesium|Metadata|FeatureTextureProperty") + static FCesiumIntegerColor GetIntegerColorFromTextureCoordinates( + UPARAM(ref) const FCesiumFeatureTextureProperty& property, + float u, + float v); + + /** + * @brief Given texture coordinates from the appropriate texture coordinate + * set (as indicated by GetTextureCoordinateIndex), returns an float-based + * metadata value for the pixel. This automatically unswizzles the pixel + * color as needed and normalizes it if needed. Only the first + * GetComponentCount channels are to be used. + */ + UFUNCTION( + BlueprintCallable, + BlueprintPure, + Category = "Cesium|Metadata|FeatureTextureProperty") + static FCesiumFloatColor GetFloatColorFromTextureCoordinates( + UPARAM(ref) const FCesiumFeatureTextureProperty& property, + float u, + float v); +}; diff --git a/Plugins/CesiumForUnreal/Source/CesiumRuntime/Public/CesiumGeoreference.h b/Plugins/CesiumForUnreal/Source/CesiumRuntime/Public/CesiumGeoreference.h new file mode 100644 index 0000000000000000000000000000000000000000..588511fdae97edb94f2d417497f2903df2c02258 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/CesiumRuntime/Public/CesiumGeoreference.h @@ -0,0 +1,585 @@ +// Copyright 2020-2021 CesiumGS, Inc. and Contributors + +#pragma once + +#include "CesiumSubLevel.h" +#include "Components/ActorComponent.h" +#include "Containers/UnrealString.h" +#include "CoreMinimal.h" +#include "GameFramework/Actor.h" +#include "GeoTransforms.h" +#include "OriginPlacement.h" +#include "UObject/WeakInterfacePtr.h" +#include <glm/mat3x3.hpp> +#include "CesiumGeoreference.generated.h" + +class APlayerCameraManager; +class FLevelCollectionModel; + +/** + * The delegate for the ACesiumGeoreference::OnGeoreferenceUpdated, + * which is triggered from UpdateGeoreference + */ +DECLARE_DYNAMIC_MULTICAST_DELEGATE(FGeoreferenceUpdated); + +/** + * 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: + /* + * Finds and returns the actor labeled `CesiumGeoreferenceDefault` in the + * persistent level of the calling object's world. If not found, it creates a + * new default Georeference. + * @param WorldContextObject Any `UObject`. + */ + UFUNCTION( + BlueprintCallable, + Category = "CesiumGeoreference", + meta = (WorldContext = "WorldContextObject")) + static ACesiumGeoreference* + GetDefaultGeoreference(const UObject* WorldContextObject); + + ACesiumGeoreference(); + + /* + * Whether to visualize the level loading radii in the editor. Helpful for + * initially positioning the level and choosing a load radius. + */ + UPROPERTY(EditAnywhere, Category = "Cesium|Cesium Sublevels") + bool ShowLoadRadii = true; + + /* + * Switches to the specified level. Sets the georeference origin to the given + * level's origin, shows the given level, and hides all other levels. + * + * If Index is negative or otherwise outside the range of valid indices, all + * levels other than the PersistentLevel are deactivated. + * + * This function is meant to be called from within the game, not in the + * Editor. + * + * @returns true if a new sub-level is active, or false if the Index was + * outside the valid range and so no sub-level is active. + */ + UFUNCTION(BlueprintCallable, Category = "Cesium|Cesium Sublevels") + bool SwitchToLevel(int32 Index); + + /* + * The list of georeferenced sublevels. Each of these has a corresponding + * world location that can be jumped to. Only one level can be worked on in + * the editor at a time. + * + * New levels added in the Editor should appear in this list automatically. If + * any are missing, check that "World Composition" is enabled in World + * Settings and that the level is in a Layer with Distance Based Streaming + * DISABLED. + */ + UPROPERTY( + EditAnywhere, + Category = "Cesium|Cesium Sublevels", + Meta = + (TitleProperty = "LevelName", + DisplayName = "Georeferenced Sublevels")) + TArray<FCesiumSubLevel> CesiumSubLevels; + + /** + * 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(EditAnywhere, BlueprintReadOnly, Category = "Cesium") + EOriginPlacement OriginPlacement = EOriginPlacement::CartographicOrigin; + + /** + * The latitude of the custom origin placement in degrees, in the range [-90, + * 90] + */ + UPROPERTY( + EditAnywhere, + Category = "Cesium", + meta = + (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( + EditAnywhere, + Category = "Cesium", + meta = + (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( + EditAnywhere, + Category = "Cesium", + meta = + (EditCondition = + "OriginPlacement==EOriginPlacement::CartographicOrigin")) + double OriginHeight = 2250.0; + + /** + * TODO: Once point-and-click georeference placement is in place, restore this + * as a UPROPERTY + */ + // UPROPERTY(EditAnywhere, Category = "Cesium", AdvancedDisplay) + bool EditOriginInViewport = false; + +#if WITH_EDITOR + /** + * 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 Unreal origin. + * + * 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 sublevels. + */ + UFUNCTION(CallInEditor, Category = "Cesium") + void PlaceGeoreferenceOriginHere(); +#endif + + /** + * The camera to use to determine which sub-level is closest, so that one can + * be activated and all others deactivated. + */ + UPROPERTY(EditAnywhere, Category = "CesiumSublevels") + APlayerCameraManager* SubLevelCamera; + + // TODO: Allow user to select/configure the ellipsoid. + // Yeah, we're working on that... + + /** + * 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(BlueprintCallable, Category = "Cesium") + FVector GetGeoreferenceOriginLongitudeLatitudeHeight() const; + + /** + * This aligns the specified longitude in degrees (x), latitude in + * degrees (y), and height above the ellipsoid in meters (z) to Unreal's world + * origin. I.e. it moves the globe so that these coordinates exactly fall on + * the origin. + * + * When the SubLevelCamera of this instance is currently contained in + * the bounds of a sublevel, then this call has no effect. + */ + void SetGeoreferenceOriginLongitudeLatitudeHeight( + const glm::dvec3& TargetLongitudeLatitudeHeight); + + /** + * This function is here for backwards compatibility. The function + * SetGeoreferenceOriginLongitudeLatitudeHeight should be used instead. + */ + void SetGeoreferenceOrigin(const glm::dvec3& TargetLongitudeLatitudeHeight); + + /** + * This aligns the specified Earth-Centered, Earth-Fixed (ECEF) coordinates to + * Unreal's world origin. I.e. it moves the globe so that these coordinates + * exactly fall on the origin. + * + * When the SubLevelCamera of this instance is currently contained in + * the bounds of a sublevel, then this call has no effect. + */ + void SetGeoreferenceOriginEcef(const glm::dvec3& TargetEcef); + + /** + * This aligns the specified longitude in degrees (X), latitude in + * degrees (Y), and height above the ellipsoid in meters (Z) to Unreal's world + * origin. I.e. it moves the globe so that these coordinates exactly fall on + * the origin. + * + * When the SubLevelCamera of this instance is currently contained in + * the bounds of a sublevel, then this call has no effect. + */ + UFUNCTION(BlueprintCallable, Category = "Cesium") + void SetGeoreferenceOriginLongitudeLatitudeHeight( + const FVector& TargetLongitudeLatitudeHeight); + + /** + * This aligns the specified Earth-Centered, Earth-Fixed (ECEF) coordinates to + * Unreal's world origin. I.e. it moves the globe so that these coordinates + * exactly fall on the origin. + * + * When the SubLevelCamera of this instance is currently contained in + * the bounds of a sublevel, then this call has no effect. + */ + UFUNCTION(BlueprintCallable, Category = "Cesium") + void SetGeoreferenceOriginEcef(const FVector& TargetEcef); + + /* + * USEFUL CONVERSION FUNCTIONS + */ + + /** + * 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; + + /** + * 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. + * + * This function peforms the computation in single-precision. When using + * the C++ API, corresponding double-precision function + * TransformLongitudeLatitudeHeightToEcef can be used. + */ + UFUNCTION(BlueprintCallable, Category = "Cesium") + FVector TransformLongitudeLatitudeHeightToEcef( + const FVector& LongitudeLatitudeHeight) const; + + /** + * Transforms the given Earth-Centered, Earth-Fixed (ECEF) coordinates into + * WGS84 longitude in degrees (x), latitude in degrees (y), and height above + * the ellipsoid in meters (z). + */ + glm::dvec3 + TransformEcefToLongitudeLatitudeHeight(const glm::dvec3& Ecef) const; + + /** + * Transforms the given Earth-Centered, Earth-Fixed (ECEF) coordinates into + * WGS84 longitude in degrees (x), latitude in degrees (y), and height above + * the ellipsoid in meters (z). + */ + UFUNCTION(BlueprintCallable, Category = "Cesium") + FVector TransformEcefToLongitudeLatitudeHeight(const FVector& Ecef) const; + + /** + * Transforms the given longitude in degrees (x), latitude in + * degrees (y), and height above the ellipsoid in meters (z) into Unreal world + * coordinates (relative to the floating origin). + */ + glm::dvec3 TransformLongitudeLatitudeHeightToUnreal( + const glm::dvec3& longitudeLatitudeHeight) const; + + /** + * Transforms the given longitude in degrees (x), latitude in + * degrees (y), and height above the ellipsoid in meters (z) into Unreal world + * coordinates (relative to the floating origin). + */ + UFUNCTION(BlueprintCallable, Category = "Cesium") + FVector TransformLongitudeLatitudeHeightToUnreal( + const FVector& LongitudeLatitudeHeight) const; + + /** + * Transforms Unreal world coordinates (relative to the floating origin) into + * longitude in degrees (x), latitude in degrees (y), and height above the + * ellipsoid in meters (z). + */ + glm::dvec3 + TransformUnrealToLongitudeLatitudeHeight(const glm::dvec3& unreal) const; + + /** + * Transforms Unreal world coordinates (relative to the floating origin) into + * longitude in degrees (x), latitude in degrees (y), and height above the + * ellipsoid in meters (z). + */ + UFUNCTION(BlueprintCallable, Category = "Cesium") + FVector TransformUnrealToLongitudeLatitudeHeight(const FVector& Unreal) const; + + /** + * Transforms the given point from Earth-Centered, Earth-Fixed (ECEF) into + * Unreal relative world (relative to the floating origin). + */ + glm::dvec3 TransformEcefToUnreal(const glm::dvec3& ecef) const; + + /** + * Transforms the given point from Earth-Centered, Earth-Fixed (ECEF) into + * Unreal relative world (relative to the floating origin). + */ + UFUNCTION(BlueprintCallable, Category = "Cesium") + FVector TransformEcefToUnreal(const FVector& Ecef) const; + + /** + * Transforms the given point from Unreal relative world (relative to the + * floating origin) to Earth-Centered, Earth-Fixed (ECEF). + */ + glm::dvec3 TransformUnrealToEcef(const glm::dvec3& unreal) const; + + /** + * Transforms the given point from Unreal relative world (relative to the + * floating origin) to Earth-Centered, Earth-Fixed (ECEF). + */ + UFUNCTION(BlueprintCallable, Category = "Cesium") + FVector TransformUnrealToEcef(const FVector& Unreal) const; + + /** + * Transforms a rotator from Unreal world to East-South-Up at the given + * Unreal world location (relative to the floating origin). + */ + glm::dquat TransformRotatorUnrealToEastSouthUp( + const glm::dquat& UnrealRotator, + const glm::dvec3& UnrealLocation) const; + + /** + * Transforms a rotator from Unreal world to East-South-Up at the given + * Unreal world location (relative to the floating origin). + */ + UFUNCTION(BlueprintCallable, Category = "Cesium") + FRotator TransformRotatorUnrealToEastSouthUp( + const FRotator& UnrealRotator, + const FVector& UnrealLocation) const; + + /** + * 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::dquat& EsuRotator, + const glm::dvec3& UnrealLocation) const; + + /** + * Transforms a rotator from East-South-Up to Unreal world at the given + * Unreal world location (relative to the floating origin). + */ + UFUNCTION(BlueprintCallable, Category = "Cesium") + FRotator TransformRotatorEastSouthUpToUnreal( + const FRotator& EsuRotator, + const FVector& UnrealLocation) const; + + /** + * 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::dmat3 ComputeEastSouthUpToUnreal(const glm::dvec3& unreal) const; + + /** + * 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. + */ + UFUNCTION(BlueprintCallable, Category = "Cesium") + FMatrix ComputeEastSouthUpToUnreal(const FVector& Unreal) const; + + /** + * 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; + + /** + * Computes the rotation matrix from the local East-North-Up to + * Earth-Centered, Earth-Fixed (ECEF) at the specified ECEF location. + */ + UFUNCTION(BlueprintCallable, Category = "Cesium") + FMatrix ComputeEastNorthUpToEcef(const FVector& Ecef) const; + + /** + * @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 _geoTransforms.ComputeGeodeticSurfaceNormal(position); + } + /** + * A delegate that will be called whenever the Georeference is + * modified in a way that affects its computations. + */ + UPROPERTY(BlueprintAssignable, Category = "Cesium") + FGeoreferenceUpdated OnGeoreferenceUpdated; + + /** + * Recomputes all world georeference transforms. Usually there is no need to + * explicitly call this from external code. + */ + void UpdateGeoreference(); + + /** + * @brief Returns whether `Tick` should be called in viewports-only mode. + * + * "If `true`, actor is ticked even if TickType==LEVELTICK_ViewportsOnly." + * (The TickType is determined by the unreal engine internally). + */ + virtual bool ShouldTickIfViewportsOnly() const override; + + /** + * @brief Function called every frame on this Actor. + * + * @param DeltaTime Game time elapsed during last frame modified by the time + * dilation + */ + virtual void Tick(float DeltaTime) override; + + /** + * 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; + + /** + * Returns the GeoTransforms that offers the same conversion + * functions as this class, but performs the computations + * in double precision. + */ + const GeoTransforms& GetGeoTransforms() const noexcept { + return _geoTransforms; + } + +protected: + // Called when the game starts or when spawned + virtual void BeginPlay() override; + virtual void EndPlay(const EEndPlayReason::Type EndPlayReason) override; + virtual void OnConstruction(const FTransform& Transform) override; + virtual void BeginDestroy() override; + +#if WITH_EDITOR + virtual void + PostEditChangeProperty(FPropertyChangedEvent& PropertyChangedEvent) override; +#endif + +private: + /** + * A tag that is assigned to Georeferences when they are created + * as the "default" Georeference for a certain world. + */ + static FName DEFAULT_GEOREFERENCE_TAG; + + /** + * The radii, in x-, y-, and z-direction, of the ellipsoid that + * should be used in this instance. + */ + UPROPERTY() + double _ellipsoidRadii[3]; + + GeoTransforms _geoTransforms; + + bool _insideSublevel; + +#if WITH_EDITOR + FDelegateHandle _newCurrentLevelSubscription; +#endif + + // TODO: add option to set georeference directly from ECEF + void _setGeoreferenceOrigin( + double targetLongitude, + double targetLatitude, + double targetHeight); + void _jumpToLevel(const FCesiumSubLevel& level); + +#if WITH_EDITOR + /** + * Will make sure that the `CesiumSubLevels` array contains all + * of the current streaming levels of the world. + */ + void _updateCesiumSubLevels(); +#endif + +#if WITH_EDITOR + void _lineTraceViewportMouse( + const bool ShowTrace, + bool& Success, + FHitResult& HitResult) const; + + /** + * @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; + + /** + * @brief Allow editing the origin with the mouse. + * + * If `EditOriginInViewport` is true, this will trace the mouse + * position, and update the origin based on the point that was + * hit. + */ + void _handleViewportOriginEditing(); + +#endif + + /** + * @brief Updates the load state of sublevels. + * + * This checks all sublevels whether their load radius contains the + * `SubLevelCamera`, in ECEF coordinates. The sublevels that + * contain the camera will be loaded. All others will be unloaded. + * + * @return Whether the camera is contained in *any* sublevel. + */ + bool _updateSublevelState(); + + /** + * Updates _geoTransforms based on the current ellipsoid and center, and + * returns the old transforms. + */ + void _updateGeoTransforms(); + + /** + * @brief Finds the ULevelStreaming with given name. + * + * @returns The ULevelStreaming, or nullptr if the provided name does not + * exist. + */ + ULevelStreaming* _findLevelStreamingByName(const FString& name); + + FCesiumSubLevel* _findCesiumSubLevelByName( + const FName& packageName, + bool createIfDoesNotExist); + +#if WITH_EDITOR + void _onNewCurrentLevel(); + void _enableAndGeoreferenceCurrentSubLevel(); +#endif + + /** + * Determines if this Georeference should manage sub-level switching. + * + * A Georeference inside a sub-level should not manage sub-level switching, + * so this function returns true the Georeference is in the world's + * PersistentLevel. + */ + bool _shouldManageSubLevels() const; +}; diff --git a/Plugins/CesiumForUnreal/Source/CesiumRuntime/Public/CesiumGlobeAnchorComponent.h b/Plugins/CesiumForUnreal/Source/CesiumRuntime/Public/CesiumGlobeAnchorComponent.h new file mode 100644 index 0000000000000000000000000000000000000000..c62486a589a18e90ca37c657a9632f99d194e617 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/CesiumRuntime/Public/CesiumGlobeAnchorComponent.h @@ -0,0 +1,436 @@ +// Copyright 2020-2021 CesiumGS, Inc. and Contributors + +#pragma once + +#include "Components/ActorComponent.h" +#include "Delegates/IDelegateInstance.h" +#include <glm/gtx/quaternion.hpp> +#include <glm/vec3.hpp> +#include <optional> +#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, Eath-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() + +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. + */ + UPROPERTY( + EditAnywhere, + BlueprintReadWrite, + BlueprintGetter = GetGeoreference, + BlueprintSetter = SetGeoreference, + Category = "Cesium|Georeference", + Meta = (AllowPrivateAccess)) + ACesiumGeoreference* 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 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, which + * happens automatically when the component is registered. + */ + UPROPERTY( + Transient, + BlueprintReadOnly, + Category = "Cesium", + Meta = (AllowPrivateAccess)) + ACesiumGeoreference* ResolvedGeoreference = nullptr; + +public: + /** @copydoc UCesiumGlobeAnchorComponent::Georeference */ + UFUNCTION(BlueprintCallable, Category = "Cesium") + ACesiumGeoreference* GetGeoreference() const; + + /** @copydoc UCesiumGlobeAnchorComponent::Georeference */ + UFUNCTION(BlueprintCallable, Category = "Cesium") + void SetGeoreference(ACesiumGeoreference* NewGeoreference); + + /** + * 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. + */ + 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 latitude in degrees of this component, in the range [-90, 90] + */ + UPROPERTY( + EditAnywhere, + Category = "Cesium|Georeference", + Meta = (AllowPrivateAccess, ClampMin = -90.0, ClampMax = 90.0)) + double Latitude = 0.0; + + /** + * The longitude in degrees of this component, in the range [-180, 180] + */ + UPROPERTY( + EditAnywhere, + Category = "Cesium|Georeference", + meta = (AllowPrivateAccess, ClampMin = -180.0, ClampMax = 180.0)) + double Longitude = 0.0; + + /** + * The height in meters above the ellipsoid (usually WGS84) of this component. + * Do not confuse this 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|Georeference", + Meta = (AllowPrivateAccess)) + double Height = 0.0; + +public: + /** + * Returns the longitude in degrees (X), latitude in degrees (Y), + * and height in meters (Z) of the actor. + * + * Returns a zero vector if the component is not yet registered. + */ + UFUNCTION(BlueprintCallable, Category = "Cesium") + FVector GetLongitudeLatitudeHeight() const; + + /** + * Move the actor to the specified longitude in degrees (x), latitude + * in degrees (y), and height in meters (z). + * + * If `AdjustOrientationForGlobeWhenMoving` is enabled, the Actor's + * orientation will also be adjusted to account for globe curvature. + */ + void MoveToLongitudeLatitudeHeight( + const glm::dvec3& TargetLongitudeLatitudeHeight); + + /** + * Move the actor to the specified longitude in degrees (x), latitude + * in degrees (y), and height in meters (z). + * + * 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& TargetLongitudeLatitudeHeight); + +private: + /** + * The Earth-Centered Earth-Fixed X-coordinate of this component in meters. + */ + UPROPERTY( + EditAnywhere, + Category = "Cesium|Georeference", + Meta = (AllowPrivateAccess)) + double ECEF_X = 0.0; + + /** + * The Earth-Centered Earth-Fixed Y-coordinate of this component in meters. + */ + UPROPERTY( + EditAnywhere, + Category = "Cesium|Georeference", + Meta = (AllowPrivateAccess)) + double ECEF_Y = 0.0; + + /** + * The Earth-Centered Earth-Fixed Z-coordinate of this component in meters. + */ + UPROPERTY( + EditAnywhere, + Category = "Cesium|Georeference", + Meta = (AllowPrivateAccess)) + double ECEF_Z = 0.0; + +public: + /** + * Returns the Earth-Centered, Earth-Fixed (ECEF) coordinates of the actor in + * meters, downcasted to a single-precision floating point vector. + * + * Returns a zero vector if the component is not yet registered. + */ + UFUNCTION(BlueprintCallable, Category = "Cesium") + FVector GetECEF() 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 newPosition The new position. + */ + void MoveToECEF(const glm::dvec3& newPosition); + + /** + * 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 newPosition The new position. + */ + UFUNCTION(BlueprintCallable, Category = "Cesium") + void MoveToECEF(const FVector& TargetEcef); + + /** + * Rotates the Actor so that its local +Z axis is aligned with the ellipsoid + * surface normal at its current location. + */ + UFUNCTION(BlueprintCallable, CallInEditor, 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, CallInEditor, Category = "Cesium") + void SnapToEastSouthUp(); + +public: + /** + * 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, Category = "Cesium|Georeference") + bool TeleportWhenUpdatingTransform = true; + + /** + * 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, Category = "Cesium|Georeference") + bool AdjustOrientationForGlobeWhenMoving = true; + + // + // Base class overrides + // + + /** + * Called by the owner actor when the world's OriginLocation changes (i.e. + * during origin rebasing). The Component will recompute the Actor's + * transform based on the new OriginLocation and on this component's + * globe transform. The Actor's orientation is unaffected. + */ + virtual void + ApplyWorldOffset(const FVector& InOffset, bool bWorldShift) override; + + /** + * 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 + +protected: + /** + * 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; + +private: + /** + * The current Actor to ECEF transformation expressed as a simple array of + * doubles so that Unreal Engine can serialize it. + */ + UPROPERTY() + double _actorToECEF_Array[16]; + + static_assert(sizeof(_actorToECEF_Array) == sizeof(glm::dmat4)); + + /** + * The _actorToECEF_Array cast as a glm::dmat4 for convenience. + */ + glm::dmat4& _actorToECEF = *reinterpret_cast<glm::dmat4*>(_actorToECEF_Array); + + /** + * 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; + + /** + * 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); + + FDelegateHandle _onTransformChangedWhileUnregistered; + + /** + * 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() + void _onGeoreferenceChanged(); + + /** + * Updates the globe-relative (ECEF) transform from the current Actor + * transform. + * + * @returns The new globe position. + */ + const glm::dmat4& _updateGlobeTransformFromActorTransform(); + + /** + * Updates the Unreal world Actor position from the current globe position. + * + * @param newWorldOrigin The new world OriginLocation to use when computing + * the Actor transform. If std::nullopt, the true world OriginLocation is + * used. + * @return The new Actor position. + */ + FTransform _updateActorTransformFromGlobeTransform( + const std::optional<glm::dvec3>& newWorldOrigin = std::nullopt); + + /** + * Sets a new globe transform and updates the Actor transform to match. If + * `AdjustOrientationForGlobeWhenMoving` is enabled, the orientation is also + * adjusted for globe curvature. + * + * This function does not update the Longitude, Latitude, Height, ECEF_X, + * ECEF_Y, or ECEF_Z properties. To do that, call `_updateCartesianProperties` + * and `_updateCartographicProperties`. + * + * @param newTransform The new transform, before it is adjusted for globe + * curvature. + * @returns The new globe transform, which may be different from + * `newTransform` if the orientation has been adjusted for globe curvature. + */ + const glm::dmat4& _setGlobeTransform(const glm::dmat4& newTransform); + + /** + * Applies the current values of the ECEF_X, ECEF_Y, and ECEF_Z properties, + * updating the Longitude, Latitude, and Height properties, the globe + * transform, and the Actor transform. If + * `AdjustOrientationForGlobeWhenMoving` is enabled, the orientation is also + * adjusted for globe curvature. + */ + void _applyCartesianProperties(); + + /** + * Updates the ECEF_X, ECEF_Y, and ECEF_Z properties from the current globe + * transform. + */ + void _updateCartesianProperties(); + + /** + * Applies the current values of the Longitude, Latitude, and Height + * properties, updating the ECEF_X, ECEF_Y, and ECEF_Z properties, the globe + * transform, and the Actor transform. If + * `AdjustOrientationForGlobeWhenMoving` is enabled, the orientation is also + * adjusted for globe curvature. + */ + void _applyCartographicProperties(); + + /** + * Updates the Longitude, Latitude, and Height properties from the current + * globe transform. + */ + void _updateCartographicProperties(); +}; diff --git a/Plugins/CesiumForUnreal/Source/CesiumRuntime/Public/CesiumIonRasterOverlay.h b/Plugins/CesiumForUnreal/Source/CesiumRuntime/Public/CesiumIonRasterOverlay.h new file mode 100644 index 0000000000000000000000000000000000000000..1771f398c0dd9c2e19686224c3a6f6ce1e2be35f --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/CesiumRuntime/Public/CesiumIonRasterOverlay.h @@ -0,0 +1,46 @@ +// Copyright 2020-2021 CesiumGS, Inc. and Contributors + +#pragma once + +#include "CesiumRasterOverlay.h" +#include "CoreMinimal.h" +#include "CesiumIonRasterOverlay.generated.h" + +/** + * 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; + + /** + * 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(); + +protected: + virtual std::unique_ptr<Cesium3DTilesSelection::RasterOverlay> CreateOverlay( + const Cesium3DTilesSelection::RasterOverlayOptions& options = {}) + override; +}; diff --git a/Plugins/CesiumForUnreal/Source/CesiumRuntime/Public/CesiumMetadataArray.h b/Plugins/CesiumForUnreal/Source/CesiumRuntime/Public/CesiumMetadataArray.h new file mode 100644 index 0000000000000000000000000000000000000000..dc8dc2e396394545da0786edcf1e4ef31ca2bdab --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/CesiumRuntime/Public/CesiumMetadataArray.h @@ -0,0 +1,328 @@ +// Copyright 2020-2021 CesiumGS, Inc. and Contributors + +#pragma once + +#include "CesiumGltf/MetadataArrayView.h" +#include "CesiumGltf/PropertyTypeTraits.h" +#include "CesiumMetadataValueType.h" +#include "Kismet/BlueprintFunctionLibrary.h" +#include "UObject/ObjectMacros.h" +#include <string_view> +#include <variant> +#include "CesiumMetadataArray.generated.h" + +/** + * A Blueprint-accessible wrapper for an array property in glTF metadata. + */ +USTRUCT(BlueprintType) +struct CESIUMRUNTIME_API FCesiumMetadataArray { + GENERATED_USTRUCT_BODY() + +private: + using ArrayType = std::variant< + CesiumGltf::MetadataArrayView<int8_t>, + CesiumGltf::MetadataArrayView<uint8_t>, + CesiumGltf::MetadataArrayView<int16_t>, + CesiumGltf::MetadataArrayView<uint16_t>, + CesiumGltf::MetadataArrayView<int32_t>, + CesiumGltf::MetadataArrayView<uint32_t>, + CesiumGltf::MetadataArrayView<int64_t>, + CesiumGltf::MetadataArrayView<uint64_t>, + CesiumGltf::MetadataArrayView<float>, + CesiumGltf::MetadataArrayView<double>, + CesiumGltf::MetadataArrayView<bool>, + CesiumGltf::MetadataArrayView<std::string_view>>; + +public: + /** + * Construct an empty array with unknown type. + */ + FCesiumMetadataArray() : _value(), _type(ECesiumMetadataTrueType::None) {} + + /** + * Construct a non-empty array. + * @param value The metadata array view that will be stored in this struct + */ + template <typename T> + FCesiumMetadataArray(CesiumGltf::MetadataArrayView<T> value) + : _value(value), _type(ECesiumMetadataTrueType::None) { + _type = + ECesiumMetadataTrueType(CesiumGltf::TypeToPropertyType< + CesiumGltf::MetadataArrayView<T>>::component); + } + +private: + template <typename T, typename... VariantType> + static bool + holdsArrayAlternative(const std::variant<VariantType...>& variant) { + return std::holds_alternative<CesiumGltf::MetadataArrayView<T>>(variant); + } + + ArrayType _value; + ECesiumMetadataTrueType _type; + + friend class UCesiumMetadataArrayBlueprintLibrary; +}; + +UCLASS() +class CESIUMRUNTIME_API UCesiumMetadataArrayBlueprintLibrary + : public UBlueprintFunctionLibrary { + GENERATED_BODY() + +public: + /** + * Gets best-fitting Blueprints type for the elements of this array. + */ + UFUNCTION( + BlueprintCallable, + BlueprintPure, + Category = "Cesium|Metadata|Array") + static ECesiumMetadataBlueprintType + GetBlueprintComponentType(UPARAM(ref) const FCesiumMetadataArray& 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. + */ + UFUNCTION( + BlueprintCallable, + BlueprintPure, + Category = "Cesium|Metadata|Array") + static ECesiumMetadataTrueType + GetTrueComponentType(UPARAM(ref) const FCesiumMetadataArray& array); + + /** + * Queries the number of elements in the array. + * This method returns 0 if component type is ECesiumMetadataValueType::None + * + * @return The number of elements in the array. + */ + UFUNCTION( + BlueprintCallable, + BlueprintPure, + Category = "Cesium|Metadata|Array") + static int64 GetSize(UPARAM(ref) const FCesiumMetadataArray& 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 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, + Category = "Cesium|Metadata|Array") + static bool GetBoolean( + UPARAM(ref) const FCesiumMetadataArray& 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 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, + Category = "Cesium|Metadata|Array") + static uint8 GetByte( + UPARAM(ref) const FCesiumMetadataArray& 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 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, + Category = "Cesium|Metadata|Array") + static int32 GetInteger( + UPARAM(ref) const FCesiumMetadataArray& Array, + int64 Index, + int32 DefaultValue = 0); + + /** + * 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 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, + Category = "Cesium|Metadata|Array") + static int64 GetInteger64( + UPARAM(ref) const FCesiumMetadataArray& 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 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, + Category = "Cesium|Metadata|Array") + static float GetFloat( + UPARAM(ref) const FCesiumMetadataArray& 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 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, + Category = "Cesium|Metadata|Array") + static double GetFloat64( + UPARAM(ref) const FCesiumMetadataArray& 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 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, + Category = "Cesium|Metadata|Array") + static FString GetString( + UPARAM(ref) const FCesiumMetadataArray& Array, + int64 Index, + const FString& DefaultValue = ""); +}; diff --git a/Plugins/CesiumForUnreal/Source/CesiumRuntime/Public/CesiumMetadataConversions.h b/Plugins/CesiumForUnreal/Source/CesiumRuntime/Public/CesiumMetadataConversions.h new file mode 100644 index 0000000000000000000000000000000000000000..97b8fd524dcf4bc92e3144ff8cdacd6ded217d1c --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/CesiumRuntime/Public/CesiumMetadataConversions.h @@ -0,0 +1,323 @@ +// Copyright 2020-2021 CesiumGS, Inc. and Contributors + +#pragma once + +#include "CesiumGltf/PropertyTypeTraits.h" +#include "CesiumMetadataValueType.h" +#include "CesiumUtility/JsonValue.h" +#include <cstdlib> +#include <glm/common.hpp> +#include <type_traits> + +ECesiumMetadataBlueprintType +CesiuMetadataTrueTypeToBlueprintType(ECesiumMetadataTrueType trueType); + +ECesiumMetadataPackedGpuType +CesiumMetadataTrueTypeToDefaultPackedGpuType(ECesiumMetadataTrueType trueType); + +// Default conversion, just returns the default value. +template <typename TTo, typename TFrom, typename Enable = void> +struct CesiumMetadataConversions { + static TTo convert(TFrom from, TTo defaultValue) { return defaultValue; } +}; + +// Trivially convert any type to itself. +template <typename T> struct CesiumMetadataConversions<T, T> { + static T convert(T from, T defaultValue) { return from; } +}; + +// +// Conversions to boolean +// + +// numeric -> bool +template <typename TFrom> +struct CesiumMetadataConversions< + bool, + TFrom, + std::enable_if_t<CesiumGltf::IsMetadataNumeric<TFrom>::value>> { + static bool convert(TFrom from, bool defaultValue) { + return from != static_cast<TFrom>(0); + } +}; + +// string -> bool +template <> struct CesiumMetadataConversions<bool, std::string_view> { + static bool convert(const std::string_view& from, bool defaultValue) { + FString f(from.size(), from.data()); + if (f.Compare("1", ESearchCase::IgnoreCase) == 0 || + f.Compare("true", ESearchCase::IgnoreCase) == 0 || + f.Compare("yes", ESearchCase::IgnoreCase) == 0) { + return true; + } else if ( + f.Compare("0", ESearchCase::IgnoreCase) == 0 || + f.Compare("false", ESearchCase::IgnoreCase) == 0 || + f.Compare("no", ESearchCase::IgnoreCase) == 0) { + return false; + } else { + return defaultValue; + } + } +}; + +// +// Conversions to integer +// + +// any integer -> any integer +template <typename TTo, typename TFrom> +struct CesiumMetadataConversions< + TTo, + TFrom, + std::enable_if_t< + CesiumGltf::IsMetadataInteger<TTo>::value && + CesiumGltf::IsMetadataInteger<TFrom>::value && + !std::is_same_v<TTo, TFrom>>> { + static TTo convert(TFrom from, TTo defaultValue) { + return CesiumUtility::losslessNarrowOrDefault(from, defaultValue); + } +}; + +// float/double -> any integer +template <typename TTo, typename TFrom> +struct CesiumMetadataConversions< + TTo, + TFrom, + std::enable_if_t< + CesiumGltf::IsMetadataInteger<TTo>::value && + CesiumGltf::IsMetadataFloating<TFrom>::value>> { + static TTo convert(TFrom from, TTo defaultValue) { + if (double(std::numeric_limits<TTo>::max()) < from || + double(std::numeric_limits<TTo>::lowest()) > from) { + // Floating-point number is outside the range of this integer type. + return defaultValue; + } + + return static_cast<TTo>(from); + } +}; + +// string -> any signed integer +template <typename TTo> +struct CesiumMetadataConversions< + TTo, + std::string_view, + std::enable_if_t< + CesiumGltf::IsMetadataInteger<TTo>::value && std::is_signed_v<TTo>>> { + static TTo convert(const std::string_view& from, TTo defaultValue) { + // 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. + std::string temp(from); + + char* pLastUsed; + int64_t parsedValue = std::strtoll(temp.c_str(), &pLastUsed, 10); + if (pLastUsed == temp.c_str() + temp.size()) { + // Successfully parsed the entire string as an integer of this type. + return CesiumUtility::losslessNarrowOrDefault(parsedValue, defaultValue); + } + + // Failed to parse as an integer. Maybe we can parse as a double and + // truncate it? + double parsedDouble = std::strtod(temp.c_str(), &pLastUsed); + if (pLastUsed == temp.c_str() + temp.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<int64_t>(truncated); + double roundTrip = static_cast<double>(asInteger); + if (roundTrip == truncated) { + return CesiumUtility::losslessNarrowOrDefault(asInteger, defaultValue); + } + } + + return defaultValue; + } +}; + +// string -> any unsigned integer +template <typename TTo> +struct CesiumMetadataConversions< + TTo, + std::string_view, + std::enable_if_t< + CesiumGltf::IsMetadataInteger<TTo>::value && !std::is_signed_v<TTo>>> { + static TTo convert(const std::string_view& from, TTo defaultValue) { + // 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. + std::string temp(from); + + char* pLastUsed; + uint64_t parsedValue = std::strtoull(temp.c_str(), &pLastUsed, 10); + if (pLastUsed == temp.c_str() + temp.size()) { + // Successfully parsed the entire string as an integer of this type. + return CesiumUtility::losslessNarrowOrDefault(parsedValue, defaultValue); + } + + // Failed to parse as an integer. Maybe we can parse as a double and + // truncate it? + double parsedDouble = std::strtod(temp.c_str(), &pLastUsed); + if (pLastUsed == temp.c_str() + temp.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<uint64_t>(truncated); + double roundTrip = static_cast<double>(asInteger); + if (roundTrip == truncated) { + return CesiumUtility::losslessNarrowOrDefault(asInteger, defaultValue); + } + } + + return defaultValue; + } +}; + +// bool -> any integer +template <typename TTo> +struct CesiumMetadataConversions< + TTo, + bool, + std::enable_if_t<CesiumGltf::IsMetadataInteger<TTo>::value>> { + static TTo convert(bool from, TTo defaultValue) { return from ? 1 : 0; } +}; + +// +// Conversions to string +// + +// bool -> string +template <> struct CesiumMetadataConversions<FString, bool> { + static FString convert(bool from, const FString& defaultValue) { + return from ? "true" : "false"; + } +}; + +// numeric -> string +template <typename TFrom> +struct CesiumMetadataConversions< + FString, + TFrom, + std::enable_if_t<CesiumGltf::IsMetadataNumeric<TFrom>::value>> { + static FString convert(TFrom from, const FString& defaultValue) { + return FString(std::to_string(from).c_str()); + } +}; + +// string_view -> FString +template <> struct CesiumMetadataConversions<FString, std::string_view> { + static FString + convert(const std::string_view& from, const FString& defaultValue) { + return FString(UTF8_TO_TCHAR(std::string(from.data(), from.size()).data())); + } +}; + +// +// Conversions to float +// + +// bool -> float +template <> struct CesiumMetadataConversions<float, bool> { + static float convert(bool from, float defaultValue) { + return from ? 1.0f : 0.0f; + } +}; + +// any integer -> float +template <typename TFrom> +struct CesiumMetadataConversions< + float, + TFrom, + std::enable_if_t<CesiumGltf::IsMetadataInteger<TFrom>::value>> { + static float convert(TFrom from, float defaultValue) { + return static_cast<float>(from); + } +}; + +// double -> float +template <> struct CesiumMetadataConversions<float, double> { + static float convert(double from, float defaultValue) { + if (from > std::numeric_limits<float>::max() || + from < std::numeric_limits<float>::lowest()) { + return defaultValue; + } + return static_cast<float>(from); + } +}; + +// string -> float +template <> struct CesiumMetadataConversions<float, std::string_view> { + static float convert(const std::string_view& from, float defaultValue) { + // 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. + std::string temp(from); + + char* pLastUsed; + float parsedValue = std::strtof(temp.c_str(), &pLastUsed); + if (pLastUsed == temp.c_str() + temp.size()) { + // Successfully parsed the entire string as a float. + return parsedValue; + } + + return defaultValue; + } +}; + +// +// Conversions to double +// + +// bool -> double +template <> struct CesiumMetadataConversions<double, bool> { + static double convert(bool from, double defaultValue) { + return from ? 1.0 : 0.0; + } +}; + +// any integer -> double +template <typename TFrom> +struct CesiumMetadataConversions< + double, + TFrom, + std::enable_if_t<CesiumGltf::IsMetadataInteger<TFrom>::value>> { + static double convert(TFrom from, double defaultValue) { + return static_cast<double>(from); + } +}; + +// float -> double +template <> struct CesiumMetadataConversions<double, float> { + static double convert(float from, double defaultValue) { + return static_cast<double>(from); + } +}; + +// string -> double +template <> struct CesiumMetadataConversions<double, std::string_view> { + static double convert(const std::string_view& from, double defaultValue) { + // 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. + std::string temp(from); + + char* pLastUsed; + double parsedValue = std::strtod(temp.c_str(), &pLastUsed); + if (pLastUsed == temp.c_str() + temp.size()) { + // Successfully parsed the entire string as a float. + return parsedValue; + } + + return defaultValue; + } +}; diff --git a/Plugins/CesiumForUnreal/Source/CesiumRuntime/Public/CesiumMetadataFeatureTable.h b/Plugins/CesiumForUnreal/Source/CesiumRuntime/Public/CesiumMetadataFeatureTable.h new file mode 100644 index 0000000000000000000000000000000000000000..10ea7ccebd39fb9042d69e2999f6585b013b2793 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/CesiumRuntime/Public/CesiumMetadataFeatureTable.h @@ -0,0 +1,161 @@ +// Copyright 2020-2021 CesiumGS, Inc. and Contributors + +#pragma once + +#include "CesiumGltf/AccessorView.h" +#include "CesiumMetadataGenericValue.h" +#include "CesiumMetadataProperty.h" +#include "CoreMinimal.h" +#include "Kismet/BlueprintFunctionLibrary.h" +#include "UObject/ObjectMacros.h" +#include "CesiumMetadataFeatureTable.generated.h" + +namespace CesiumGltf { +struct Model; +struct Accessor; +struct FeatureTable; +} // namespace CesiumGltf + +struct UE_DEPRECATED( + 4.26, + "FCesiumMetadataFeatureTable is deprecated, use FCesiumFeatureTable instead.") + FCesiumMetadataFeatureTable; + +/** + * A Blueprint-accessible wrapper for a glTF feature table. A feature table is a + * collection of properties for each feature ID in the mesh. It also knows how + * to look up the feature ID associated with a given mesh vertex. + */ +USTRUCT(BlueprintType) +struct CESIUMRUNTIME_API FCesiumMetadataFeatureTable { + GENERATED_USTRUCT_BODY() + + using FeatureIDAccessorType = std::variant< + std::monostate, + CesiumGltf::AccessorView<CesiumGltf::AccessorTypes::SCALAR<int8_t>>, + CesiumGltf::AccessorView<CesiumGltf::AccessorTypes::SCALAR<uint8_t>>, + CesiumGltf::AccessorView<CesiumGltf::AccessorTypes::SCALAR<int16_t>>, + CesiumGltf::AccessorView<CesiumGltf::AccessorTypes::SCALAR<uint16_t>>, + CesiumGltf::AccessorView<CesiumGltf::AccessorTypes::SCALAR<uint32_t>>, + CesiumGltf::AccessorView<CesiumGltf::AccessorTypes::SCALAR<float>>>; + +public: + /** + * Construct an empty feature table. + */ + FCesiumMetadataFeatureTable(){}; + + /** + * Constructs a feature table from a glTF Feature Table. + * + * @param Model The model that stores EXT_feature_metadata. + * @param Accessor The accessor for the feature ID. + * @param FeatureTable The feature table that is paired with the feature ID. + */ + FCesiumMetadataFeatureTable( + const CesiumGltf::Model& Model, + const CesiumGltf::Accessor& Accessor, + const CesiumGltf::FeatureTable& FeatureTable); + +private: + FeatureIDAccessorType _featureIDAccessor; + TMap<FString, FCesiumMetadataProperty> _properties; + + friend class UCesiumMetadataFeatureTableBlueprintLibrary; +}; + +class UE_DEPRECATED( + 4.26, + "UCesiumMetadataFeatureTableBlueprintLibrary is deprecated, use UCesiumFeatureTableBlueprintLibrary instead.") + UCesiumMetadataFeatureTableBlueprintLibrary; + +UCLASS() +class CESIUMRUNTIME_API UCesiumMetadataFeatureTableBlueprintLibrary + : public UBlueprintFunctionLibrary { + GENERATED_BODY() + +public: + PRAGMA_DISABLE_DEPRECATION_WARNINGS + + /** + * Gets the number of features in the feature table. + */ + UFUNCTION( + BlueprintCallable, + BlueprintPure, + Category = "Cesium|Metadata|FeatureTable", + Meta = + (DeprecatedFunction, + DeprecationMessage = + "UCesiumMetadataFeatureTableBlueprintLibrary is deprecated, use UCesiumFeatureTableBlueprintLibrary and FCesiumFeatureTable instead.")) + static int64 + GetNumberOfFeatures(UPARAM(ref) + const FCesiumMetadataFeatureTable& FeatureTable); + + /** + * Gets the feature ID associated with a given vertex. + */ + UFUNCTION( + BlueprintCallable, + BlueprintPure, + Category = "Cesium|Metadata|FeatureTable", + Meta = + (DeprecatedFunction, + DeprecationMessage = + "UCesiumMetadataFeatureTableBlueprintLibrary is deprecated, use UCesiumFeatureTableBlueprintLibrary and FCesiumFeatureTable instead.")) + static int64 GetFeatureIDForVertex( + UPARAM(ref) const FCesiumMetadataFeatureTable& FeatureTable, + int64 VertexIndex); + + /** + * Gets a map of property name to property value for a given feature. + * + * @param featureID The ID of the feature. + */ + UFUNCTION( + BlueprintCallable, + BlueprintPure, + Category = "Cesium|Metadata|FeatureTable", + Meta = + (DeprecatedFunction, + DeprecationMessage = + "UCesiumMetadataFeatureTableBlueprintLibrary is deprecated, use UCesiumFeatureTableBlueprintLibrary and FCesiumFeatureTable instead.")) + static TMap<FString, FCesiumMetadataGenericValue> + GetMetadataValuesForFeatureID( + UPARAM(ref) const FCesiumMetadataFeatureTable& FeatureTable, + int64 FeatureID); + + /** + * Gets a map of property name to property value for a given feature, where + * the value is converted to a string regardless of the underlying type. + * + * @param FeatureID The ID of the feature. + */ + UFUNCTION( + BlueprintCallable, + BlueprintPure, + Category = "Cesium|Metadata|FeatureTable", + Meta = + (DeprecatedFunction, + DeprecationMessage = + "UCesiumMetadataFeatureTableBlueprintLibrary is deprecated, use UCesiumFeatureTableBlueprintLibrary and FCesiumFeatureTable instead.")) + static TMap<FString, FString> GetMetadataValuesAsStringForFeatureID( + UPARAM(ref) const FCesiumMetadataFeatureTable& featureTable, + int64 FeatureID); + + /** + * Gets all the properties of the feature table. + */ + UFUNCTION( + BlueprintCallable, + BlueprintPure, + Category = "Cesium|Metadata|FeatureTable", + Meta = + (DeprecatedFunction, + DeprecationMessage = + "UCesiumMetadataFeatureTableBlueprintLibrary is deprecated, use UCesiumFeatureTableBlueprintLibrary and FCesiumFeatureTable instead.")) + static const TMap<FString, FCesiumMetadataProperty>& + GetProperties(UPARAM(ref) const FCesiumMetadataFeatureTable& FeatureTable); + + PRAGMA_ENABLE_DEPRECATION_WARNINGS +}; diff --git a/Plugins/CesiumForUnreal/Source/CesiumRuntime/Public/CesiumMetadataGenericValue.h b/Plugins/CesiumForUnreal/Source/CesiumRuntime/Public/CesiumMetadataGenericValue.h new file mode 100644 index 0000000000000000000000000000000000000000..aea7b91799c2034fe2b5e6fd6fa6f787e751546d --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/CesiumRuntime/Public/CesiumMetadataGenericValue.h @@ -0,0 +1,351 @@ +// Copyright 2020-2021 CesiumGS, Inc. and Contributors + +#pragma once + +#include "CesiumGltf/MetadataArrayView.h" +#include "CesiumGltf/PropertyTypeTraits.h" +#include "CesiumMetadataArray.h" +#include "CesiumMetadataValueType.h" +#include "Kismet/BlueprintFunctionLibrary.h" +#include "UObject/ObjectMacros.h" +#include "CesiumMetadataGenericValue.generated.h" + +/** + * A Blueprint-accessible wrapper for a glTF metadata value. + */ +USTRUCT(BlueprintType) +struct CESIUMRUNTIME_API FCesiumMetadataGenericValue { + GENERATED_USTRUCT_BODY() + +private: + using ValueType = std::variant< + std::monostate, + int8_t, + uint8_t, + int16_t, + uint16_t, + int32_t, + uint32_t, + int64_t, + uint64_t, + float, + double, + bool, + std::string_view, + CesiumGltf::MetadataArrayView<int8_t>, + CesiumGltf::MetadataArrayView<uint8_t>, + CesiumGltf::MetadataArrayView<int16_t>, + CesiumGltf::MetadataArrayView<uint16_t>, + CesiumGltf::MetadataArrayView<int32_t>, + CesiumGltf::MetadataArrayView<uint32_t>, + CesiumGltf::MetadataArrayView<int64_t>, + CesiumGltf::MetadataArrayView<uint64_t>, + CesiumGltf::MetadataArrayView<float>, + CesiumGltf::MetadataArrayView<double>, + CesiumGltf::MetadataArrayView<bool>, + CesiumGltf::MetadataArrayView<std::string_view>>; + +public: + /** + * Constructs an empty value with unknown type. + */ + FCesiumMetadataGenericValue() + : _value(std::monostate{}), _type(ECesiumMetadataTrueType::None) {} + + /** + * Constructs a value. + * + * @param Value The value to be stored in this struct + */ + template <typename T> + explicit FCesiumMetadataGenericValue(const T& Value) + : _value(Value), + _type(ECesiumMetadataTrueType::None), + _componentType(ECesiumMetadataTrueType::None) { + _type = ECesiumMetadataTrueType(CesiumGltf::TypeToPropertyType<T>::value); + _componentType = + ECesiumMetadataTrueType(CesiumGltf::TypeToPropertyType<T>::component); + } + +private: + ValueType _value; + ECesiumMetadataTrueType _type; + ECesiumMetadataTrueType _componentType; + + friend class UCesiumMetadataGenericValueBlueprintLibrary; +}; + +UCLASS() +class CESIUMRUNTIME_API UCesiumMetadataGenericValueBlueprintLibrary + : public UBlueprintFunctionLibrary { + GENERATED_BODY() + +public: + /** + * Gets best-fitting Blueprints type for the 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|GenericValue") + static ECesiumMetadataBlueprintType + GetBlueprintType(UPARAM(ref) const FCesiumMetadataGenericValue& Value); + + /** + * Gets best-fitting Blueprints type for the elements of this array. If this + * value is not an array, returns None. + */ + UFUNCTION( + BlueprintCallable, + BlueprintPure, + Category = "Cesium|Metadata|GenericValue") + static ECesiumMetadataBlueprintType + GetBlueprintComponentType(UPARAM(ref) + const FCesiumMetadataGenericValue& Value); + + /** + * 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, + Category = "Cesium|Metadata|GenericValue") + static ECesiumMetadataTrueType + GetTrueType(UPARAM(ref) const FCesiumMetadataGenericValue& 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, + Category = "Cesium|Metadata|GenericValue") + static ECesiumMetadataTrueType + GetTrueComponentType(UPARAM(ref) const FCesiumMetadataGenericValue& Value); + + /** + * Gets the value and attempts to convert it to a Boolean value. + * + * If the value is boolean, it is returned directly. + * + * If the value is numeric, 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. + * + * Other types of values will return the default value. + * + * @param DefaultValue The default value to use if the feature ID is invalid + * or the feature's value cannot be converted. + * @return The value. + */ + UFUNCTION( + BlueprintCallable, + BlueprintPure, + Category = "Cesium|Metadata|GenericValue") + static bool GetBoolean( + UPARAM(ref) const FCesiumMetadataGenericValue& value, + bool DefaultValue); + + /** + * Gets the value and attempts to convert it to an unsigned 8-bit integer + * value. + * + * If the value is an integer and between 0 and 255, it is returned + * directly. + * + * If the value is a floating-point number in the range `(-1, 256)`, it is + * truncated (rounded toward zero). + * + * If the value is a boolean, 0.0 is returned for false and 1.0 for true. + * + * 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 use of a comma or + * other character to group digits. + * + * Otherwise, the default value is returned. + * + * @param DefaultValue The default value to use if the feature ID is invalid + * or the feature's value cannot be converted. + * @return The property value. + */ + UFUNCTION( + BlueprintCallable, + BlueprintPure, + Category = "Cesium|Metadata|GenericValue") + static uint8 GetByte( + UPARAM(ref) const FCesiumMetadataGenericValue& Value, + uint8 DefaultValue); + + /** + * Gets the value and attempts to convert it to a signed 32-bit integer + * value. + * + * If the value is an integer and between -2,147,483,647 and 2,147,483,647, + * it is returned directly. + * + * If the value is a floating-point number in the range + * `(-2147483648, 2147483648)`, it is truncated (rounded toward zero). + * + * If the value is a boolean, 0 is returned for false and 1 for true. + * + * 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 use of a comma or other character to group digits. + * + * Otherwise, the default value is returned. + * + * @param DefaultValue The default value to use if the feature ID is invalid + * or the feature's value cannot be converted. + * @return The property value. + */ + UFUNCTION( + BlueprintCallable, + BlueprintPure, + Category = "Cesium|Metadata|GenericValue") + static int32 GetInteger( + UPARAM(ref) const FCesiumMetadataGenericValue& Value, + int32 DefaultValue); + + /** + * Gets the value and attempts to convert it to a signed 64-bit integer + * value. + * + * If the value is an integer and between -2^63-1 and 2^63-1, + * it is returned directly. + * + * If the value is a floating-point number in the range `(-2^63, 2^63)`, it is + * truncated (rounded toward zero). + * + * If the value is a boolean, 0 is returned for false and 1 for true. + * + * 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 use of a comma or other character to group digits. + * + * Otherwise, the default value is returned. + * + * @param DefaultValue The default value to use if the feature ID is invalid + * or the feature's value cannot be converted. + * @return The property value. + */ + UFUNCTION( + BlueprintCallable, + BlueprintPure, + Category = "Cesium|Metadata|GenericValue") + static int64 GetInteger64( + UPARAM(ref) const FCesiumMetadataGenericValue& Value, + int64 DefaultValue); + + /** + * Gets the value and attempts to convert it to a 32-bit floating-point + * value. + * + * If the value is a singe-precision floating-point number, is is returned. + * + * If the value is an integer or double-precision floating-point number, + * it is converted to the closest representable single-precision + * floating-point number. + * + * If the value is a boolean, 0.0 is returned for false and 1.0 for true. + * + * 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 use of a comma or other + * character to group digits. + * + * Otherwise, the default value is returned. + * + * @param DefaultValue The default value to use if the feature ID is invalid + * or the feature's value cannot be converted. + * @return The property value. + */ + UFUNCTION( + BlueprintCallable, + BlueprintPure, + Category = "Cesium|Metadata|GenericValue") + static float GetFloat( + UPARAM(ref) const FCesiumMetadataGenericValue& Value, + float DefaultValue); + + /** + * Gets the value and attempts to convert it to a 64-bit floating-point + * value. + * + * If the value is a single- or double-precision floating-point number, is is + * returned. + * + * If the value is an integer, it is converted to the closest representable + * double-precision floating-point number. + * + * If the value is a boolean, 0.0 is returned for false and 1.0 for true. + * + * 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 use of a comma or other + * character to group digits. + * + * Otherwise, the default value is returned. + * + * @param DefaultValue The default value to use if the feature ID is invalid + * or the feature's value cannot be converted. + * @return The property value. + */ + UFUNCTION( + BlueprintCallable, + BlueprintPure, + Category = "Cesium|Metadata|GenericValue") + static double GetFloat64( + UPARAM(ref) const FCesiumMetadataGenericValue& Value, + double DefaultValue); + + /** + * Gets the value and attempts to convert it to a string value. + * + * A numeric value is converted to a string with `FString::Format`, which uses + * the current locale. + * + * Boolean properties are converted to "true" or "false". + * + * Array properties return the `defaultValue`. + * + * String properties are returned directly. + * + * @param DefaultValue The default value to use if the feature ID is invalid + * or the feature's value cannot be converted. + * @return The property value. + */ + UFUNCTION( + BlueprintCallable, + BlueprintPure, + Category = "Cesium|Metadata|GenericValue") + static FString GetString( + UPARAM(ref) const FCesiumMetadataGenericValue& Value, + const FString& DefaultValue); + + /** + * Gets the value as an array. + * If the property is not an array type, this method returns an empty array. + * + * @return The property value. + */ + UFUNCTION( + BlueprintCallable, + BlueprintPure, + Category = "Cesium|Metadata|GenericValue") + static FCesiumMetadataArray + GetArray(UPARAM(ref) const FCesiumMetadataGenericValue& Value); +}; diff --git a/Plugins/CesiumForUnreal/Source/CesiumRuntime/Public/CesiumMetadataModel.h b/Plugins/CesiumForUnreal/Source/CesiumRuntime/Public/CesiumMetadataModel.h new file mode 100644 index 0000000000000000000000000000000000000000..9e2de6e66bf7c5c3ad380e62cccf3dde3c43eca6 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/CesiumRuntime/Public/CesiumMetadataModel.h @@ -0,0 +1,67 @@ +// Copyright 2020-2021 CesiumGS, Inc. and Contributors + +#pragma once + +#include "CesiumFeatureTable.h" +#include "CesiumFeatureTexture.h" + +#include "Containers/Array.h" +#include "Containers/Map.h" +#include "Containers/UnrealString.h" + +#include "CesiumMetadataModel.generated.h" + +namespace CesiumGltf { +struct ExtensionModelExtFeatureMetadata; +struct Model; +} // namespace CesiumGltf + +/** + * @brief A blueprint-accessible wrapper for metadata contained in a glTF model. + * Provides access to views of feature tables and feature textures available on + * the glTF. + */ +USTRUCT(BlueprintType) +struct CESIUMRUNTIME_API FCesiumMetadataModel { + GENERATED_USTRUCT_BODY() + +public: + FCesiumMetadataModel() {} + + FCesiumMetadataModel( + const CesiumGltf::Model& model, + const CesiumGltf::ExtensionModelExtFeatureMetadata& metadata); + +private: + TMap<FString, FCesiumFeatureTable> _featureTables; + TMap<FString, FCesiumFeatureTexture> _featureTextures; + + friend class UCesiumMetadataModelBlueprintLibrary; +}; + +UCLASS() +class CESIUMRUNTIME_API UCesiumMetadataModelBlueprintLibrary + : public UBlueprintFunctionLibrary { + GENERATED_BODY() + +public: + /** + * @brief Get all the feature tables for this metadata model. + */ + UFUNCTION( + BlueprintCallable, + BlueprintPure, + Category = "Cesium|Metadata|Model") + static const TMap<FString, FCesiumFeatureTable>& + GetFeatureTables(UPARAM(ref) const FCesiumMetadataModel& MetadataModel); + + /** + * @brief Get all the feature textures for this metadata model. + */ + UFUNCTION( + BlueprintCallable, + BlueprintPure, + Category = "Cesium|Metadata|Model") + static const TMap<FString, FCesiumFeatureTexture>& + GetFeatureTextures(UPARAM(ref) const FCesiumMetadataModel& MetadataModel); +}; diff --git a/Plugins/CesiumForUnreal/Source/CesiumRuntime/Public/CesiumMetadataPrimitive.h b/Plugins/CesiumForUnreal/Source/CesiumRuntime/Public/CesiumMetadataPrimitive.h new file mode 100644 index 0000000000000000000000000000000000000000..440286d99357bc0ade4c6df31634522af4d2533f --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/CesiumRuntime/Public/CesiumMetadataPrimitive.h @@ -0,0 +1,145 @@ +// Copyright 2020-2021 CesiumGS, Inc. and Contributors + +#pragma once + +#include "CesiumFeatureIdAttribute.h" +#include "CesiumFeatureIdTexture.h" +#include "Kismet/BlueprintFunctionLibrary.h" +#include "UObject/ObjectMacros.h" +// REMOVE AFTER DEPRECATION +#include "CesiumMetadataFeatureTable.h" + +#include "CesiumMetadataPrimitive.generated.h" + +// REMOVE AFTER DEPRECATION +struct FCesiumMetadataFeatureTable; + +namespace CesiumGltf { +struct ExtensionMeshPrimitiveExtFeatureMetadata; + +// REMOVE AFTER DEPRECATION +struct ExtensionModelExtFeatureMetadata; +} // namespace CesiumGltf + +/** + * A Blueprint-accessible wrapper for a glTF Primitive's Metadata. It holds + * views of feature id attributes / feature id textures and names of feature + * textures associated with this primitive. + */ +USTRUCT(BlueprintType) +struct CESIUMRUNTIME_API FCesiumMetadataPrimitive { + GENERATED_USTRUCT_BODY() + + using VertexIDAccessorType = std::variant< + CesiumGltf::AccessorView<CesiumGltf::AccessorTypes::SCALAR<uint8_t>>, + CesiumGltf::AccessorView<CesiumGltf::AccessorTypes::SCALAR<uint16_t>>, + CesiumGltf::AccessorView<CesiumGltf::AccessorTypes::SCALAR<uint32_t>>>; + +public: + /** + * Construct an empty primitive metadata. + */ + FCesiumMetadataPrimitive() {} + + /** + * Constructs a primitive metadata instance. + * + * @param model The model that stores EXT_feature_metadata extension + * @param primitive The mesh primitive that stores EXT_feature_metadata + * extension + * @param metadata The EXT_feature_metadata of the gltf mesh primitive. + * primitive + */ + FCesiumMetadataPrimitive( + const CesiumGltf::Model& model, + const CesiumGltf::MeshPrimitive& primitive, + const CesiumGltf::ExtensionMeshPrimitiveExtFeatureMetadata& metadata, + const CesiumGltf::ExtensionModelExtFeatureMetadata& modelMetadata); + +private: + TArray<FCesiumFeatureIdAttribute> _featureIdAttributes; + TArray<FCesiumFeatureIdTexture> _featureIdTextures; + TArray<FString> _featureTextureNames; + VertexIDAccessorType _vertexIDAccessor; + + // REMOVE AFTER DEPRECATION + PRAGMA_DISABLE_DEPRECATION_WARNINGS + TArray<FCesiumMetadataFeatureTable> _featureTables_deprecated; + PRAGMA_ENABLE_DEPRECATION_WARNINGS + + friend class UCesiumMetadataPrimitiveBlueprintLibrary; +}; + +UCLASS() +class CESIUMRUNTIME_API UCesiumMetadataPrimitiveBlueprintLibrary + : public UBlueprintFunctionLibrary { + GENERATED_BODY() + +public: + PRAGMA_DISABLE_DEPRECATION_WARNINGS + /** + * Get all the feature tables that are associated with the primitive. + */ + UFUNCTION( + BlueprintCallable, + BlueprintPure, + Category = "Cesium|Metadata|Property", + Meta = + (DeprecatedFunction, + DeprecationMessage = + "Use UCesiumMetadataModelBlueprintLibrary::GetFeatureTables() instead.")) + static const TArray<FCesiumMetadataFeatureTable>& + GetFeatureTables(UPARAM(ref) + const FCesiumMetadataPrimitive& MetadataPrimitive); + PRAGMA_ENABLE_DEPRECATION_WARNINGS + + /** + * @brief Get all the feature id attributes that are associated with the + * primitive. + */ + UFUNCTION( + BlueprintCallable, + BlueprintPure, + Category = "Cesium|Metadata|Primitive") + static const TArray<FCesiumFeatureIdAttribute>& + GetFeatureIdAttributes(UPARAM(ref) + const FCesiumMetadataPrimitive& MetadataPrimitive); + + /** + * @brief Get all the feature id textures that are associated with the + * primitive. + */ + UFUNCTION( + BlueprintCallable, + BlueprintPure, + Category = "Cesium|Metadata|Primitive") + static const TArray<FCesiumFeatureIdTexture>& + GetFeatureIdTextures(UPARAM(ref) + const FCesiumMetadataPrimitive& MetadataPrimitive); + + /** + * @brief Get all the feature textures that are associated with the + * primitive. + */ + UFUNCTION( + BlueprintCallable, + BlueprintPure, + Category = "Cesium|Metadata|Primitive") + static const TArray<FString>& + GetFeatureTextureNames(UPARAM(ref) + const FCesiumMetadataPrimitive& MetadataPrimitive); + + /** + * Gets the ID of the first vertex that makes up a given face of this + * primitive. + * + * @param faceID The ID of the face. + */ + UFUNCTION( + BlueprintCallable, + BlueprintPure, + Category = "Cesium|Metadata|Primitive") + static int64 GetFirstVertexIDFromFaceID( + UPARAM(ref) const FCesiumMetadataPrimitive& MetadataPrimitive, + int64 FaceID); +}; diff --git a/Plugins/CesiumForUnreal/Source/CesiumRuntime/Public/CesiumMetadataProperty.h b/Plugins/CesiumForUnreal/Source/CesiumRuntime/Public/CesiumMetadataProperty.h new file mode 100644 index 0000000000000000000000000000000000000000..a782d50682815ebf3a200aa4b6e340dc85cab2e2 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/CesiumRuntime/Public/CesiumMetadataProperty.h @@ -0,0 +1,438 @@ +// Copyright 2020-2021 CesiumGS, Inc. and Contributors + +#pragma once + +#include "CesiumGltf/MetadataPropertyView.h" +#include "CesiumGltf/PropertyTypeTraits.h" +#include "CesiumMetadataArray.h" +#include "CesiumMetadataGenericValue.h" +#include "CesiumMetadataValueType.h" +#include "Kismet/BlueprintFunctionLibrary.h" +#include "UObject/ObjectMacros.h" +#include <string_view> +#include <variant> +#include "CesiumMetadataProperty.generated.h" + +/** + * A Blueprint-accessible wrapper for a glTF metadata property. A property has a + * particular type, such as int64 or string, and a value of that type for each + * feature in the mesh. + */ +USTRUCT(BlueprintType) +struct CESIUMRUNTIME_API FCesiumMetadataProperty { + GENERATED_USTRUCT_BODY() + +private: + using PropertyType = std::variant< + CesiumGltf::MetadataPropertyView<int8_t>, + CesiumGltf::MetadataPropertyView<uint8_t>, + CesiumGltf::MetadataPropertyView<int16_t>, + CesiumGltf::MetadataPropertyView<uint16_t>, + CesiumGltf::MetadataPropertyView<int32_t>, + CesiumGltf::MetadataPropertyView<uint32_t>, + CesiumGltf::MetadataPropertyView<int64_t>, + CesiumGltf::MetadataPropertyView<uint64_t>, + CesiumGltf::MetadataPropertyView<float>, + CesiumGltf::MetadataPropertyView<double>, + CesiumGltf::MetadataPropertyView<bool>, + CesiumGltf::MetadataPropertyView<std::string_view>, + CesiumGltf::MetadataPropertyView<CesiumGltf::MetadataArrayView<int8_t>>, + CesiumGltf::MetadataPropertyView<CesiumGltf::MetadataArrayView<uint8_t>>, + CesiumGltf::MetadataPropertyView<CesiumGltf::MetadataArrayView<int16_t>>, + CesiumGltf::MetadataPropertyView<CesiumGltf::MetadataArrayView<uint16_t>>, + CesiumGltf::MetadataPropertyView<CesiumGltf::MetadataArrayView<int32_t>>, + CesiumGltf::MetadataPropertyView<CesiumGltf::MetadataArrayView<uint32_t>>, + CesiumGltf::MetadataPropertyView<CesiumGltf::MetadataArrayView<int64_t>>, + CesiumGltf::MetadataPropertyView<CesiumGltf::MetadataArrayView<uint64_t>>, + CesiumGltf::MetadataPropertyView<CesiumGltf::MetadataArrayView<float>>, + CesiumGltf::MetadataPropertyView<CesiumGltf::MetadataArrayView<double>>, + CesiumGltf::MetadataPropertyView<CesiumGltf::MetadataArrayView<bool>>, + CesiumGltf::MetadataPropertyView< + CesiumGltf::MetadataArrayView<std::string_view>>>; + +public: + /** + * Construct an empty property with unknown type. + */ + FCesiumMetadataProperty() + : _property(), + _type(ECesiumMetadataTrueType::None), + _componentType(ECesiumMetadataTrueType::None), + _componentCount(0), + _normalized(false) {} + + /** + * Construct a wrapper for the property view. + * + * @param value The property to be stored in this struct + */ + template <typename T> + FCesiumMetadataProperty(const CesiumGltf::MetadataPropertyView<T>& value) + : _property(value), + _type(ECesiumMetadataTrueType::None), + _normalized(value.isNormalized()) { + _type = ECesiumMetadataTrueType(CesiumGltf::TypeToPropertyType<T>::value); + _componentType = + ECesiumMetadataTrueType(CesiumGltf::TypeToPropertyType<T>::component); + _componentCount = value.getComponentCount(); + } + +private: + template <typename T, typename... VariantType> + static bool + holdsPropertyAlternative(const std::variant<VariantType...>& variant) { + return std::holds_alternative<CesiumGltf::MetadataPropertyView<T>>(variant); + } + + PropertyType _property; + ECesiumMetadataTrueType _type; + ECesiumMetadataTrueType _componentType; + int64 _componentCount; + bool _normalized; + + friend class UCesiumMetadataPropertyBlueprintLibrary; +}; + +UCLASS() +class CESIUMRUNTIME_API UCesiumMetadataPropertyBlueprintLibrary + : public UBlueprintFunctionLibrary { + GENERATED_BODY() + +public: + /** + * Gets best-fitting Blueprints type for the property. For the most precise + * representation of the value possible from Blueprints, you should retrieve + * it using this type. + */ + UFUNCTION( + BlueprintCallable, + BlueprintPure, + Category = "Cesium|Metadata|Property") + static ECesiumMetadataBlueprintType + GetBlueprintType(UPARAM(ref) const FCesiumMetadataProperty& Property); + + /** + * Gets best-fitting Blueprints type for the elements of this array. If this + * value is not an array, returns None. + */ + UFUNCTION( + BlueprintCallable, + BlueprintPure, + Category = "Cesium|Metadata|Property") + static ECesiumMetadataBlueprintType + GetBlueprintComponentType(UPARAM(ref) + const FCesiumMetadataProperty& Property); + + /** + * Gets true type of the property. Many of these types are not accessible + * from Blueprints, but can be converted to a Blueprint-accessible type. + */ + UFUNCTION( + BlueprintCallable, + BlueprintPure, + Category = "Cesium|Metadata|Property") + static ECesiumMetadataTrueType + GetTrueType(UPARAM(ref) const FCesiumMetadataProperty& Property); + + /** + * 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, + Category = "Cesium|Metadata|Property") + static ECesiumMetadataTrueType + GetTrueComponentType(UPARAM(ref) const FCesiumMetadataProperty& Property); + + /** + * Queries the number of features in the property. + */ + UFUNCTION( + BlueprintCallable, + BlueprintPure, + Category = "Cesium|Metadata|Property") + static int64 GetNumberOfFeatures(UPARAM(ref) + const FCesiumMetadataProperty& Property); + + /** + * Queries the component count of this property. Only applicable when the + * property is an array type. + */ + UFUNCTION( + BlueprintCallable, + BlueprintPure, + Category = "Cesium|Metadata|Property") + static int64 GetComponentCount(UPARAM(ref) + const FCesiumMetadataProperty& Property); + + /** + * Retrieves the value of the property for the feature with the given ID and + * attempts to convert it to a Boolean value. + * + * If the property is boolean, it is returned directly. + * + * If the property is numeric, zero is converted to false, while any other + * value is converted to true. + * + * If the property 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 properties will return the default value. + * + * @param FeatureID The ID of the feature. + * @param DefaultValue The default value to use if the feature ID is invalid + * or the feature's value cannot be converted. + * @return The property value. + */ + UFUNCTION( + BlueprintCallable, + BlueprintPure, + Category = "Cesium|Metadata|Property") + static bool GetBoolean( + UPARAM(ref) const FCesiumMetadataProperty& Property, + int64 FeatureID, + bool DefaultValue = false); + + /** + * Retrieves the value of the property for the feature with the given ID and + * attempts to convert it to an unsigned 8-bit integer value. + * + * If the property is an integer and between 0 and 255, it is returned + * directly. + * + * If the property is a floating-point number, it is truncated (rounded + * toward zero). + * + * If the property is a boolean, 0 is returned for false and 1 for true. + * + * If the property 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 FeatureID The ID of the feature. + * @param DefaultValue The default value to use if the feature ID is invalid + * or the feature's value cannot be converted. + * @return The property value. + */ + UFUNCTION( + BlueprintCallable, + BlueprintPure, + Category = "Cesium|Metadata|Property") + static uint8 GetByte( + UPARAM(ref) const FCesiumMetadataProperty& Property, + int64 FeatureID, + uint8 DefaultValue = 0); + + /** + * Retrieves the value of the property for the feature with the given ID and + * attempts to convert it to a signed 32-bit integer value. + * + * If the property is an integer and between -2,147,483,647 and 2,147,483,647, + * it is returned directly. + * + * If the property is a floating-point number, it is truncated (rounded + * toward zero). + * + * If the property is a boolean, 0 is returned for false and 1 for true. + * + * If the property 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 FeatureID The ID of the feature. + * @param DefaultValue The default value to use if the feature ID is invalid + * or the feature's value cannot be converted. + * @return The property value. + */ + UFUNCTION( + BlueprintCallable, + BlueprintPure, + Category = "Cesium|Metadata|Property") + static int32 GetInteger( + UPARAM(ref) const FCesiumMetadataProperty& Property, + int64 FeatureID, + int32 DefaultValue = 0); + + /** + * Retrieves the value of the property for the feature with the given ID and + * attempts to convert it to a signed 64-bit integer value. + * + * If the property is an integer and between -2^63-1 and 2^63-1, it + * is returned directly. + * + * If the property is a floating-point number, it is truncated (rounded + * toward zero). + * + * If the property is a boolean, 0 is returned for false and 1 for true. + * + * If the property 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 FeatureID The ID of the feature. + * @param DefaultValue The default value to use if the feature ID is invalid + * or the feature's value cannot be converted. + * @return The property value. + */ + UFUNCTION( + BlueprintCallable, + BlueprintPure, + Category = "Cesium|Metadata|Property") + static int64 GetInteger64( + UPARAM(ref) const FCesiumMetadataProperty& Property, + int64 FeatureID, + int64 DefaultValue = 0); + + /** + * Retrieves the value of the property for the feature with the given ID and + * attempts to convert it to a 32-bit floating-point value. + * + * If the property is a singe-precision floating-point number, is is returned. + * + * If the property is an integer or double-precision floating-point number, + * it is converted to the closest representable single-precision + * floating-point number. + * + * If the property is a boolean, 0.0 is returned for false and 1.0 for true. + * + * If the property 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 FeatureID The ID of the feature. + * @param DefaultValue The default value to use if the feature ID is invalid + * or the feature's value cannot be converted. + * @return The property value. + */ + UFUNCTION( + BlueprintCallable, + BlueprintPure, + Category = "Cesium|Metadata|Property") + static float GetFloat( + UPARAM(ref) const FCesiumMetadataProperty& Property, + int64 FeatureID, + float DefaultValue = 0.0f); + + /** + * Retrieves the value of the property for the feature with the given ID and + * attempts to convert it to a 64-bit floating-point value. + * + * If the property is a single- or double-precision floating-point number, is + * is returned. + * + * If the property is an integer, it is converted to the closest representable + * single-precision floating-point number. + * + * If the property is a boolean, 0.0 is returned for false and 1.0 for true. + * + * If the property 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 FeatureID The ID of the feature. + * @param DefaultValue The default value to use if the feature ID is invalid + * or the feature's value cannot be converted. + * @return The property value. + */ + UFUNCTION( + BlueprintCallable, + BlueprintPure, + Category = "Cesium|Metadata|Property") + static double GetFloat64( + UPARAM(ref) const FCesiumMetadataProperty& Property, + int64 FeatureID, + double DefaultValue = 0.0); + + /** + * Retrieves the value of the property for the feature with the given ID and + * attempts to convert it to a string value. + * + * Numeric properties are converted to a string with `FString::Format`, which + * uses the current locale. + * + * Boolean properties are converted to "true" or "false". + * + * Array properties return the `defaultValue`. + * + * String properties are returned directly. + * + * @param featureID The ID of the feature. + * @param defaultValue The default value to use if the feature ID is invalid + * or the feature's value cannot be converted. + * @return The property value. + */ + UFUNCTION( + BlueprintCallable, + BlueprintPure, + Category = "Cesium|Metadata|Property") + static FString GetString( + UPARAM(ref) const FCesiumMetadataProperty& Property, + int64 FeatureID, + const FString& DefaultValue = ""); + + /** + * Retrieves the value of the property for the feature with the given ID. + * If the property is not an array type, this method returns an empty array. + * + * If the property is not an array, the default value is returned. + * + * @param featureID The ID of the feature. + * @return The property value. + */ + UFUNCTION( + BlueprintCallable, + BlueprintPure, + Category = "Cesium|Metadata|Property") + static FCesiumMetadataArray GetArray( + UPARAM(ref) const FCesiumMetadataProperty& Property, + int64 FeatureID); + + /** + * Retrieves the value of the property for the feature with the given ID. + * The value is returned in a generic form that can be queried as a specific + * type later. + * + * @param featureID The ID of the feature. + * @return The property value. + */ + UFUNCTION( + BlueprintCallable, + BlueprintPure, + Category = "Cesium|Metadata|Property") + static FCesiumMetadataGenericValue GetGenericValue( + UPARAM(ref) const FCesiumMetadataProperty& Property, + int64 FeatureID); + + /** + * Whether this property is supposed to be normalized. Only applicable when + * the type (or componentType if this is an array) is an integer. + * + * @return Whether this property is normalized. + */ + UFUNCTION( + BlueprintCallable, + BlueprintPure, + Category = "Cesium|Metadata|Property") + static bool IsNormalized(UPARAM(ref) const FCesiumMetadataProperty& Property); +}; diff --git a/Plugins/CesiumForUnreal/Source/CesiumRuntime/Public/CesiumMetadataUtilityBlueprintLibrary.h b/Plugins/CesiumForUnreal/Source/CesiumRuntime/Public/CesiumMetadataUtilityBlueprintLibrary.h new file mode 100644 index 0000000000000000000000000000000000000000..0b70baa577816325f64f76a070e0e109f9d65dde --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/CesiumRuntime/Public/CesiumMetadataUtilityBlueprintLibrary.h @@ -0,0 +1,105 @@ +// Copyright 2020-2021 CesiumGS, Inc. and Contributors + +#pragma once + +#include "CesiumFeatureTable.h" +#include "CesiumMetadataGenericValue.h" +#include "CesiumMetadataModel.h" +#include "CesiumMetadataPrimitive.h" +#include "Containers/UnrealString.h" +#include "Kismet/BlueprintFunctionLibrary.h" +#include "UObject/ObjectMacros.h" +#include "CesiumMetadataUtilityBlueprintLibrary.generated.h" + +struct FCesiumFeatureIdAttribute; +struct FCesiumFeatureIdTexture; + +// REMOVE AFTER DEPRECATION +struct FCesiumMetadataFeatureTable; + +UCLASS() +class CESIUMRUNTIME_API UCesiumMetadataUtilityBlueprintLibrary + : 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|Metadata|Utility") + static const FCesiumMetadataModel& + GetModelMetadata(const UPrimitiveComponent* component); + + /** + * 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|Metadata|Utility") + 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, + Category = "Cesium|Metadata|Utility") + static TMap<FString, FCesiumMetadataGenericValue> + 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, + Category = "Cesium|Metadata|Utility") + static TMap<FString, FString> GetMetadataValuesAsStringForFace( + const UPrimitiveComponent* component, + int64 faceID); + + /** + * Gets the feature ID associated with a given face for a feature id + * attribute. + */ + UFUNCTION( + BlueprintCallable, + BlueprintPure, + Category = "Cesium|Metadata|Utility") + static int64 GetFeatureIDFromFaceID( + UPARAM(ref) const FCesiumMetadataPrimitive& Primitive, + UPARAM(ref) const FCesiumFeatureIdAttribute& FeatureIdAttribute, + int64 faceID); + + PRAGMA_DISABLE_DEPRECATION_WARNINGS + /** + * Gets the feature ID associated with a given face for a given feature table. + */ + UFUNCTION( + BlueprintCallable, + BlueprintPure, + Category = "Cesium|Metadata|Utility", + Meta = + (DeprecatedFunction, + DeprecationMessage = + "GetFeatureIDForFace(Primitive, FeatureTable) is deprecated. Please use GetFeatureIDFromFaceID(Primitive, FeatureIdAttribute).")) + static int64 GetFeatureIDForFace( + UPARAM(ref) const FCesiumMetadataPrimitive& Primitive, + UPARAM(ref) const FCesiumMetadataFeatureTable& FeatureTable, + int64 faceID); + PRAGMA_ENABLE_DEPRECATION_WARNINGS +}; diff --git a/Plugins/CesiumForUnreal/Source/CesiumRuntime/Public/CesiumMetadataValueType.h b/Plugins/CesiumForUnreal/Source/CesiumRuntime/Public/CesiumMetadataValueType.h new file mode 100644 index 0000000000000000000000000000000000000000..5d3ff75fc572cb30f400ce16b35b7bc7625cf265 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/CesiumRuntime/Public/CesiumMetadataValueType.h @@ -0,0 +1,49 @@ +// Copyright 2020-2021 CesiumGS, Inc. and Contributors + +#pragma once + +#include "CesiumGltf/PropertyType.h" +#include "UObject/ObjectMacros.h" + +/** + * The Blueprint type that can losslessly represent values of a given property. + */ +UENUM(BlueprintType) +enum class ECesiumMetadataBlueprintType : uint8 { + None, + Boolean, + Byte, + Integer, + Integer64, + Float, + Float64, + String, + Array +}; + +// True types are cast, reintepreted, or parsed before being packed into gpu +// types when encoding into a texture. +enum class ECesiumMetadataPackedGpuType : uint8 { None, Uint8, Float }; + +// UE requires us to have an enum with the value 0. +// None should have that value, but make sure. +static_assert(int(CesiumGltf::PropertyType::None) == 0); + +UENUM(BlueprintType) +enum class ECesiumMetadataTrueType : uint8 { + None = 0, + Int8 = int(CesiumGltf::PropertyType::Int8), + Uint8 = int(CesiumGltf::PropertyType::Uint8), + Int16 = int(CesiumGltf::PropertyType::Int16), + Uint16 = int(CesiumGltf::PropertyType::Uint16), + Int32 = int(CesiumGltf::PropertyType::Int32), + Uint32 = int(CesiumGltf::PropertyType::Uint32), + Int64 = int(CesiumGltf::PropertyType::Int64), + Uint64 = int(CesiumGltf::PropertyType::Uint64), + Float32 = int(CesiumGltf::PropertyType::Float32), + Float64 = int(CesiumGltf::PropertyType::Float64), + Boolean = int(CesiumGltf::PropertyType::Boolean), + Enum = int(CesiumGltf::PropertyType::Enum), + String = int(CesiumGltf::PropertyType::String), + Array = int(CesiumGltf::PropertyType::Array) +}; diff --git a/Plugins/CesiumForUnreal/Source/CesiumRuntime/Public/CesiumPolygonRasterOverlay.h b/Plugins/CesiumForUnreal/Source/CesiumRuntime/Public/CesiumPolygonRasterOverlay.h new file mode 100644 index 0000000000000000000000000000000000000000..cb5bb00ae8a5d319f3eee55c41969e7c3cdd6b2d --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/CesiumRuntime/Public/CesiumPolygonRasterOverlay.h @@ -0,0 +1,72 @@ +// Copyright 2020-2021 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<ACesiumCartographicPolygon*> 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<Cesium3DTilesSelection::RasterOverlay> CreateOverlay( + const Cesium3DTilesSelection::RasterOverlayOptions& options = {}) + override; + + virtual void OnAdd( + Cesium3DTilesSelection::Tileset* pTileset, + Cesium3DTilesSelection::RasterOverlay* pOverlay) override; + virtual void OnRemove( + Cesium3DTilesSelection::Tileset* pTileset, + Cesium3DTilesSelection::RasterOverlay* pOverlay) override; + +private: + std::shared_ptr<Cesium3DTilesSelection::RasterizedPolygonsTileExcluder> + _pExcluder; +}; diff --git a/Plugins/CesiumForUnreal/Source/CesiumRuntime/Public/CesiumRasterOverlay.h b/Plugins/CesiumForUnreal/Source/CesiumRuntime/Public/CesiumRasterOverlay.h new file mode 100644 index 0000000000000000000000000000000000000000..fe6417e705c89961b8338b6bb43dbd21dbb1b3b1 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/CesiumRuntime/Public/CesiumRasterOverlay.h @@ -0,0 +1,224 @@ +// Copyright 2020-2021 CesiumGS, Inc. and Contributors + +#pragma once + +#include "Cesium3DTilesSelection/RasterOverlay.h" +#include "CesiumRasterOverlayLoadFailureDetails.h" +#include "Components/ActorComponent.h" +#include "CoreMinimal.h" +#include "Engine/Texture.h" +#include "Engine/TextureDefines.h" +#include <memory> +#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<TextureFilter> filter = TextureFilter::TF_Default; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Cesium") + TEnumAsByte<TextureGroup> 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(); + + /** + * Adds this raster overlay to its owning Cesium 3D Tileset Actor. 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(); + + /** + * Removes this raster overlay from its owning Cesium 3D Tileset Actor. 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. + */ + 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); + + virtual void Activate(bool bReset) override; + 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<Cesium3DTilesSelection::RasterOverlay> CreateOverlay( + const Cesium3DTilesSelection::RasterOverlayOptions& options = {}) + PURE_VIRTUAL(UCesiumRasterOverlay::CreateOverlay, return nullptr;); + + virtual void OnAdd( + Cesium3DTilesSelection::Tileset* pTileset, + Cesium3DTilesSelection::RasterOverlay* pOverlay) {} + virtual void OnRemove( + Cesium3DTilesSelection::Tileset* pTileset, + Cesium3DTilesSelection::RasterOverlay* pOverlay) {} + +private: + Cesium3DTilesSelection::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 0000000000000000000000000000000000000000..8874283374123c8780bf76e38ebfd67f6f2ab9d9 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/CesiumRuntime/Public/CesiumRasterOverlayLoadFailureDetails.h @@ -0,0 +1,58 @@ +// Copyright 2020-2021 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<UCesiumRasterOverlay> 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 0000000000000000000000000000000000000000..606c61c8990ac9bb851c6bf4212525ea2a471434 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/CesiumRuntime/Public/CesiumRuntime.h @@ -0,0 +1,49 @@ +// Copyright 2020-2021 CesiumGS, Inc. and Contributors + +#pragma once + +#include "CoreMinimal.h" +#include "Modules/ModuleManager.h" + +class ACesium3DTileset; +class UCesiumRasterOverlay; + +namespace CesiumAsync { +class AsyncSystem; +class IAssetAccessor; +} // 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<CesiumAsync::IAssetAccessor>& +getAssetAccessor(); diff --git a/Plugins/CesiumForUnreal/Source/CesiumRuntime/Public/CesiumRuntimeSettings.h b/Plugins/CesiumForUnreal/Source/CesiumRuntime/Public/CesiumRuntimeSettings.h new file mode 100644 index 0000000000000000000000000000000000000000..ecd190acef41216ee03a5e233b11ce22615a9d8c --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/CesiumRuntime/Public/CesiumRuntimeSettings.h @@ -0,0 +1,55 @@ +// Copyright 2020-2021 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: + /** + * 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( + Config, + EditAnywhere, + Category = "Cesium ion", + 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( + Config, + EditAnywhere, + Category = "Cesium ion", + meta = (DisplayName = "Default Cesium ion Access Token")) + FString DefaultIonAccessToken; + + 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; +}; diff --git a/Plugins/CesiumForUnreal/Source/CesiumRuntime/Public/CesiumSubLevel.h b/Plugins/CesiumForUnreal/Source/CesiumRuntime/Public/CesiumSubLevel.h new file mode 100644 index 0000000000000000000000000000000000000000..f4c234cd9113f2ce57a24e1a179715c4502865e0 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/CesiumRuntime/Public/CesiumSubLevel.h @@ -0,0 +1,82 @@ +// Copyright 2020-2021 CesiumGS, Inc. and Contributors + +#pragma once + +#include "CoreMinimal.h" +#include "GameFramework/Actor.h" +#include "CesiumSubLevel.generated.h" + +class ULevelStreaming; + +/* + * 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/CesiumSunSky.h b/Plugins/CesiumForUnreal/Source/CesiumRuntime/Public/CesiumSunSky.h new file mode 100644 index 0000000000000000000000000000000000000000..64ad27395264b64a93adf32f562053bf6e17c811 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/CesiumRuntime/Public/CesiumSunSky.h @@ -0,0 +1,447 @@ +// Copyright 2020-2021 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(VisibleAnywhere, BlueprintReadOnly, Category = "Cesium") + 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. + */ + 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. + */ + UPROPERTY( + EditAnywhere, + BlueprintReadWrite, + meta = (EditCondition = "UpdateAtmosphereAtRuntime"), + Category = "Cesium|Atmosphere") + double CircumscribedGroundThreshold = 100.0; + + /** + * 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<AActor> 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(); + + // 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/CesiumTileMapServiceRasterOverlay.h b/Plugins/CesiumForUnreal/Source/CesiumRuntime/Public/CesiumTileMapServiceRasterOverlay.h new file mode 100644 index 0000000000000000000000000000000000000000..ff28f8b13948c198d5891ea74717de67592c0c25 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/CesiumRuntime/Public/CesiumTileMapServiceRasterOverlay.h @@ -0,0 +1,59 @@ +// Copyright 2020-2021 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<Cesium3DTilesSelection::RasterOverlay> CreateOverlay( + const Cesium3DTilesSelection::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 0000000000000000000000000000000000000000..3ff2991c86f33c6a30500ecc986e97dc1513dbd3 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/CesiumRuntime/Public/CesiumWebMapServiceRasterOverlay.h @@ -0,0 +1,82 @@ +// Copyright 2020-2022 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<Cesium3DTilesSelection::RasterOverlay> CreateOverlay( + const Cesium3DTilesSelection::RasterOverlayOptions& options = {}) + override; +}; diff --git a/Plugins/CesiumForUnreal/Source/CesiumRuntime/Public/CustomDepthParameters.h b/Plugins/CesiumForUnreal/Source/CesiumRuntime/Public/CustomDepthParameters.h new file mode 100644 index 0000000000000000000000000000000000000000..2de784164079bb6cbb3cfb425bf177933c398f96 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/CesiumRuntime/Public/CustomDepthParameters.h @@ -0,0 +1,54 @@ +// Copyright 2020-2021 CesiumGS, Inc. and Contributors + +#pragma once + +#include <Components/PrimitiveComponent.h> +#include <CoreMinimal.h> + +#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 0000000000000000000000000000000000000000..777135027de70a2f04899b0243c3467ebb147056 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/CesiumRuntime/Public/GeoTransforms.h @@ -0,0 +1,276 @@ +// Copyright 2020-2021 CesiumGS, Inc. and Contributors + +#pragma once + +#include "CesiumGeospatial/Ellipsoid.h" +#include "HAL/Platform.h" +#include <glm/glm.hpp> + +/** + * @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() + : _ellipsoid(CesiumGeospatial::Ellipsoid::WGS84), + _center(glm::dvec3(0.0)), + _georeferencedToEcef(1.0), + _ecefToGeoreferenced(1.0), + _ueAbsToEcef(1.0), + _ecefToUeAbs(1.0) { + updateTransforms(); + } + + /** + * @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. + */ + GeoTransforms( + const CesiumGeospatial::Ellipsoid& ellipsoid, + const glm::dvec3& center) + : _ellipsoid(ellipsoid), + _center(center), + _georeferencedToEcef(1.0), + _ecefToGeoreferenced(1.0), + _ueAbsToEcef(1.0), + _ecefToUeAbs(1.0) { + updateTransforms(); + } + + /** + * @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::dmat3 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 "Georeferenced" reference frame + * defined by this instance to the "Ellipsoid-centered" reference frame (i.e. + * ECEF). + * + * Gets a matrix that transforms coordinates from the "Georeference" reference + * frame defined by this instance to the "Ellipsoid-centered" reference frame, + * which is usually Earth-centered, Earth-fixed. See {@link + * reference-frames.md}. + */ + const glm::dmat4& + GetGeoreferencedToEllipsoidCenteredTransform() const noexcept { + return this->_georeferencedToEcef; + } + + /** + * @brief Gets the transformation from the "Ellipsoid-centered" reference + * frame (i.e. ECEF) to the georeferenced reference frame defined by this + * instance. + * + * Gets a matrix that transforms coordinates from the "Ellipsoid-centered" + * reference frame (which is usually Earth-centered, Earth-fixed) to the + * "Georeferenced" reference frame defined by this instance. See {@link + * reference-frames.md}. + */ + const glm::dmat4& + GetEllipsoidCenteredToGeoreferencedTransform() const noexcept { + return this->_ecefToGeoreferenced; + } + + /** + * @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->_ueAbsToEcef; + } + + /** + * @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->_ecefToUeAbs; + } + + /** + * @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; + +private: + /** + * Update the derived state (i.e. the matrices) when either + * the center or the ellipsoid has changed. + */ + void updateTransforms() noexcept; + + // Modifiable state + CesiumGeospatial::Ellipsoid _ellipsoid; + glm::dvec3 _center; + + // Derived state + glm::dmat4 _georeferencedToEcef; + glm::dmat4 _ecefToGeoreferenced; + glm::dmat4 _ueAbsToEcef; + glm::dmat4 _ecefToUeAbs; +}; diff --git a/Plugins/CesiumForUnreal/Source/CesiumRuntime/Public/GlobeAwareDefaultPawn.h b/Plugins/CesiumForUnreal/Source/CesiumRuntime/Public/GlobeAwareDefaultPawn.h new file mode 100644 index 0000000000000000000000000000000000000000..9adfdd9de88d7f3bfa5e52f71ad11c033a5db7cf --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/CesiumRuntime/Public/GlobeAwareDefaultPawn.h @@ -0,0 +1,249 @@ +// Copyright 2020-2021 CesiumGS, Inc. and Contributors + +#pragma once + +#include "CoreMinimal.h" +#include "GameFramework/DefaultPawn.h" +#include <glm/mat3x3.hpp> +#include <glm/vec3.hpp> +#include <vector> +#include "GlobeAwareDefaultPawn.generated.h" + +class ACesiumGeoreference; +class UCesiumGlobeAnchorComponent; +class UCurveFloat; + +/** + * 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; + + /** + * This curve dictates what percentage of the max altitude the pawn should + * take at a given time on the curve. This curve must be kept in the 0 to + * 1 range on both axes. The {@see FlyToMaximumAltitudeCurve} dictates the + * actual max altitude at each point along the curve. + */ + UPROPERTY(EditAnywhere, Category = "Cesium") + UCurveFloat* FlyToAltitudeProfileCurve; + + /** + * This curve is used to determine the progress percentage for all the other + * curves. This allows us to accelerate and deaccelerate as wanted throughout + * the curve. + */ + UPROPERTY(EditAnywhere, Category = "Cesium") + UCurveFloat* FlyToProgressCurve; + + /** + * This curve dictates the maximum altitude at each point along the curve. + * This can be used in conjunction with the {@see FlyToAltitudeProfileCurve} + * to allow the pawn to take some altitude during the flight. + */ + UPROPERTY(EditAnywhere, Category = "Cesium") + UCurveFloat* FlyToMaximumAltitudeCurve; + + /** + * The length in seconds that the flight should last. + */ + UPROPERTY(EditAnywhere, Category = "Cesium", meta = (ClampMin = 0.0)) + double FlyToDuration = 5.0; + + /** + * The granularity in degrees with which keypoints should be generated for + * the flight interpolation. + */ + UPROPERTY(EditAnywhere, Category = "Cesium", meta = (ClampMin = 0.0)) + double FlyToGranularityDegrees = 0.01; + + /** + * A delegate that will be called whenever the pawn finishes flying + * + */ + UPROPERTY(BlueprintAssignable, Category = "Cesium"); + FCompletedFlight OnFlightComplete; + + /** + * A delegate that will be called when a pawn's flying is interrupted + * + */ + UPROPERTY(BlueprintAssignable, Category = "Cesium"); + FInterruptedFlight OnFlightInterrupt; + + /** + * 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}, {@see FlyToDuration}, and + * {@see FlyToGranularityDegrees}. + */ + void FlyToLocationECEF( + const glm::dvec3& ECEFDestination, + double YawAtDestination, + double PitchAtDestination, + bool CanInterruptByMoving); + + /** + * 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}, {@see FlyToDuration}, and + * {@see FlyToGranularityDegrees}. + */ + UFUNCTION(BlueprintCallable, Category = "Cesium") + 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}. + */ + void FlyToLocationLongitudeLatitudeHeight( + const glm::dvec3& LongitudeLatitudeHeightDestination, + 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, Category = "Cesium") + void FlyToLocationLongitudeLatitudeHeight( + const FVector& LongitudeLatitudeHeightDestination, + double YawAtDestination, + double PitchAtDestination, + bool CanInterruptByMoving); + + virtual bool ShouldTickIfViewportsOnly() const override; + virtual void Tick(float DeltaSeconds) override; + virtual void PostLoad() override; + // virtual void Serialize(FArchive& Ar) override; + +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; + + /** + * The Globe Anchor Component that precisely ties this Pawn to the Globe. + */ + UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = "Cesium") + UCesiumGlobeAnchorComponent* GlobeAnchor; + +private: + void _moveAlongViewAxis(EAxis::Type axis, double Val); + void _moveAlongVector(const FVector& axis, double Val); + void _interruptFlight(); + + /** + * @brief Advance the camera flight based on the given time delta. + * + * NOTE: This function requires the Georefence to be valid. If it + * is not valid, then this function will do nothing. + * + * The given delta will be added to the _currentFlyTime, and the position + * and orientation will be computed by interpolating the _keypoints + * and _flyToSourceRotation/_flyToDestinationRotation based on this time. + * + * The position will be set as the SetECEFCameraLocation, and the + * orientation will be assigned GetController()->SetControlRotation. + * + * @param DeltaSeconds The time delta, in seconds + */ + void _handleFlightStep(float DeltaSeconds); + + // helper variables for FlyToLocation + bool _bFlyingToLocation = false; + bool _bCanInterruptFlight = false; + double _currentFlyTime = 0.0; + FQuat _flyToSourceRotation; + FQuat _flyToDestinationRotation; + + std::vector<glm::dvec3> _keypoints; +}; diff --git a/Plugins/CesiumForUnreal/Source/CesiumRuntime/Public/OriginPlacement.h b/Plugins/CesiumForUnreal/Source/CesiumRuntime/Public/OriginPlacement.h new file mode 100644 index 0000000000000000000000000000000000000000..e41ba7124cda3b41909d0f4a6e1f0fe2164c6552 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/CesiumRuntime/Public/OriginPlacement.h @@ -0,0 +1,31 @@ +// Copyright 2020-2021 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 0000000000000000000000000000000000000000..c24314bddeb726fffc41bec71bd0790391322ebe --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/CesiumRuntime/Public/UnrealAssetAccessor.h @@ -0,0 +1,34 @@ +// Copyright 2020-2021 CesiumGS, Inc. and Contributors + +#pragma once + +#include "CesiumAsync/AsyncSystem.h" +#include "CesiumAsync/IAssetAccessor.h" +#include "Containers/UnrealString.h" +#include "HAL/Platform.h" +#include <cstddef> + +class CESIUMRUNTIME_API UnrealAssetAccessor + : public CesiumAsync::IAssetAccessor { +public: + UnrealAssetAccessor(); + + virtual CesiumAsync::Future<std::shared_ptr<CesiumAsync::IAssetRequest>> + get(const CesiumAsync::AsyncSystem& asyncSystem, + const std::string& url, + const std::vector<CesiumAsync::IAssetAccessor::THeader>& headers) + override; + + virtual CesiumAsync::Future<std::shared_ptr<CesiumAsync::IAssetRequest>> + request( + const CesiumAsync::AsyncSystem& asyncSystem, + const std::string& verb, + const std::string& url, + const std::vector<CesiumAsync::IAssetAccessor::THeader>& headers, + const gsl::span<const std::byte>& contentPayload) override; + + virtual void tick() noexcept override; + +private: + FString _userAgent; +}; diff --git a/Plugins/CesiumForUnreal/Source/CesiumRuntime/Public/UnrealTaskProcessor.h b/Plugins/CesiumForUnreal/Source/CesiumRuntime/Public/UnrealTaskProcessor.h new file mode 100644 index 0000000000000000000000000000000000000000..d2707736294e7914e45de249b6897232c68ca7f8 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/CesiumRuntime/Public/UnrealTaskProcessor.h @@ -0,0 +1,12 @@ +// Copyright 2020-2021 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<void()> 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 0000000000000000000000000000000000000000..d11a5f3e5af51f831da9556f84e44e33abca1ef5 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/Cesium3DTiles/Asset.h @@ -0,0 +1,31 @@ +// This file was generated by generate-classes. +// DO NOT EDIT THIS FILE! +#pragma once + +#include "Cesium3DTiles/Library.h" + +#include <CesiumUtility/ExtensibleObject.h> + +#include <optional> +#include <string> + +namespace Cesium3DTiles { +/** + * @brief Metadata about the entire tileset. + */ +struct CESIUM3DTILES_API Asset final : public CesiumUtility::ExtensibleObject { + static inline 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<std::string> tilesetVersion; +}; +} // 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 0000000000000000000000000000000000000000..6356396fdd31f69860cfa3bccbddf6bdd8fbb75b --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/Cesium3DTiles/Availability.h @@ -0,0 +1,53 @@ +// This file was generated by generate-classes. +// DO NOT EDIT THIS FILE! +#pragma once + +#include "Cesium3DTiles/Library.h" + +#include <CesiumUtility/ExtensibleObject.h> + +#include <cstdint> +#include <optional> + +namespace Cesium3DTiles { +/** + * @brief An object describing the availability of a set of elements. + */ +struct CESIUM3DTILES_API Availability final + : public CesiumUtility::ExtensibleObject { + static inline 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 { + static constexpr int32_t UNAVAILABLE = 0; + + 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<int64_t> bitstream; + + /** + * @brief A number indicating how many 1 bits exist in the availability + * bitstream. + */ + std::optional<int64_t> 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<int32_t> constant; +}; +} // 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 0000000000000000000000000000000000000000..8fd79eab175ae839aa37b834d3616485cf661000 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/Cesium3DTiles/BoundingVolume.h @@ -0,0 +1,46 @@ +// This file was generated by generate-classes. +// DO NOT EDIT THIS FILE! +#pragma once + +#include "Cesium3DTiles/Library.h" + +#include <CesiumUtility/ExtensibleObject.h> + +#include <vector> + +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 { + static inline 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<double> 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, and + * heights are in meters above (or below) the WGS84 ellipsoid. + */ + std::vector<double> 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. + */ + std::vector<double> sphere; +}; +} // 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 0000000000000000000000000000000000000000..765ac75f367a05448ff7616265d5de3a879784a2 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/Cesium3DTiles/Buffer.h @@ -0,0 +1,40 @@ +// This file was generated by generate-classes. +// DO NOT EDIT THIS FILE! +#pragma once + +#include "Cesium3DTiles/Library.h" + +#include <CesiumUtility/ExtensibleObject.h> + +#include <cstdint> +#include <optional> +#include <string> + +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 Buffer final : public CesiumUtility::ExtensibleObject { + static inline constexpr const char* TypeName = "Buffer"; + + /** + * @brief The URI (or IRI) of the external schema file. 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<std::string> uri; + + /** + * @brief The length of the buffer in bytes. + */ + int64_t byteLength = int64_t(); + + /** + * @brief The name of the buffer. + */ + std::optional<std::string> name; +}; +} // 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 0000000000000000000000000000000000000000..ad14c84d424685843e53db7e18402f7bcbd8be5a --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/Cesium3DTiles/BufferView.h @@ -0,0 +1,41 @@ +// This file was generated by generate-classes. +// DO NOT EDIT THIS FILE! +#pragma once + +#include "Cesium3DTiles/Library.h" + +#include <CesiumUtility/ExtensibleObject.h> + +#include <cstdint> +#include <optional> +#include <string> + +namespace Cesium3DTiles { +/** + * @brief A contiguous subset of a buffer + */ +struct CESIUM3DTILES_API BufferView final + : public CesiumUtility::ExtensibleObject { + static inline 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<std::string> name; +}; +} // 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 0000000000000000000000000000000000000000..edd7ca1c07c18f423028b94ae365d66191e8f7f9 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/Cesium3DTiles/Class.h @@ -0,0 +1,38 @@ +// This file was generated by generate-classes. +// DO NOT EDIT THIS FILE! +#pragma once + +#include "Cesium3DTiles/ClassProperty.h" +#include "Cesium3DTiles/Library.h" + +#include <CesiumUtility/ExtensibleObject.h> + +#include <optional> +#include <string> +#include <unordered_map> + +namespace Cesium3DTiles { +/** + * @brief A class containing a set of properties. + */ +struct CESIUM3DTILES_API Class final : public CesiumUtility::ExtensibleObject { + static inline constexpr const char* TypeName = "Class"; + + /** + * @brief The name of the class, e.g. for display purposes. + */ + std::optional<std::string> name; + + /** + * @brief The description of the class. + */ + std::optional<std::string> 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<std::string, Cesium3DTiles::ClassProperty> properties; +}; +} // 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 0000000000000000000000000000000000000000..be2fd97401041a1ad4ce3ef6ad88fc96414ede2c --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/Cesium3DTiles/ClassProperty.h @@ -0,0 +1,191 @@ +// This file was generated by generate-classes. +// DO NOT EDIT THIS FILE! +#pragma once + +#include "Cesium3DTiles/Library.h" + +#include <CesiumUtility/ExtensibleObject.h> +#include <CesiumUtility/JsonValue.h> + +#include <cstdint> +#include <optional> +#include <string> + +namespace Cesium3DTiles { +/** + * @brief A single property of a metadata class. + */ +struct CESIUM3DTILES_API ClassProperty final + : public CesiumUtility::ExtensibleObject { + static inline constexpr const char* TypeName = "ClassProperty"; + + /** + * @brief Known values for The element type. + */ + struct Type { + inline static const std::string SCALAR = "SCALAR"; + + inline static const std::string VEC2 = "VEC2"; + + inline static const std::string VEC3 = "VEC3"; + + inline static const std::string VEC4 = "VEC4"; + + inline static const std::string MAT2 = "MAT2"; + + inline static const std::string MAT3 = "MAT3"; + + inline static const std::string MAT4 = "MAT4"; + + inline static const std::string STRING = "STRING"; + + inline static const std::string BOOLEAN = "BOOLEAN"; + + 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 { + inline static const std::string INT8 = "INT8"; + + inline static const std::string UINT8 = "UINT8"; + + inline static const std::string INT16 = "INT16"; + + inline static const std::string UINT16 = "UINT16"; + + inline static const std::string INT32 = "INT32"; + + inline static const std::string UINT32 = "UINT32"; + + inline static const std::string INT64 = "INT64"; + + inline static const std::string UINT64 = "UINT64"; + + inline static const std::string FLOAT32 = "FLOAT32"; + + inline static const std::string FLOAT64 = "FLOAT64"; + }; + + /** + * @brief The name of the property, e.g. for display purposes. + */ + std::optional<std::string> name; + + /** + * @brief The description of the property. + */ + std::optional<std::string> 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<std::string> componentType; + + /** + * @brief Enum ID as declared in the `enums` dictionary. Required when `type` + * is `ENUM`. + */ + std::optional<std::string> 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<int64_t> 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`. + */ + std::optional<CesiumUtility::JsonValue> 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<CesiumUtility::JsonValue> 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<CesiumUtility::JsonValue> 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<CesiumUtility::JsonValue> 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<CesiumUtility::JsonValue> 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<CesiumUtility::JsonValue> 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<std::string> semantic; +}; +} // 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 0000000000000000000000000000000000000000..45666859880ecdcde8e1a84f6f34ff4740ecdc11 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/Cesium3DTiles/ClassStatistics.h @@ -0,0 +1,34 @@ +// This file was generated by generate-classes. +// DO NOT EDIT THIS FILE! +#pragma once + +#include "Cesium3DTiles/Library.h" +#include "Cesium3DTiles/PropertyStatistics.h" + +#include <CesiumUtility/ExtensibleObject.h> + +#include <cstdint> +#include <optional> +#include <unordered_map> + +namespace Cesium3DTiles { +/** + * @brief Statistics about entities that conform to a class. + */ +struct CESIUM3DTILES_API ClassStatistics final + : public CesiumUtility::ExtensibleObject { + static inline constexpr const char* TypeName = "ClassStatistics"; + + /** + * @brief The number of entities that conform to the class. + */ + std::optional<int64_t> 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<std::string, Cesium3DTiles::PropertyStatistics> properties; +}; +} // 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 0000000000000000000000000000000000000000..1a09fad04fbb54ebf1184cb7ae1b46aab0c42b92 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/Cesium3DTiles/Content.h @@ -0,0 +1,48 @@ +// This file was generated by generate-classes. +// DO NOT EDIT THIS FILE! +#pragma once + +#include "Cesium3DTiles/BoundingVolume.h" +#include "Cesium3DTiles/Library.h" +#include "Cesium3DTiles/MetadataEntity.h" + +#include <CesiumUtility/ExtensibleObject.h> + +#include <cstdint> +#include <optional> +#include <string> + +namespace Cesium3DTiles { +/** + * @brief Metadata about the tile's content and a link to the content. + */ +struct CESIUM3DTILES_API Content final + : public CesiumUtility::ExtensibleObject { + static inline 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<Cesium3DTiles::BoundingVolume> 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<Cesium3DTiles::MetadataEntity> 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<int64_t> group; +}; +} // 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 0000000000000000000000000000000000000000..ec959200b5d9666be8783dcacadae37a867686f5 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/Cesium3DTiles/Enum.h @@ -0,0 +1,66 @@ +// This file was generated by generate-classes. +// DO NOT EDIT THIS FILE! +#pragma once + +#include "Cesium3DTiles/EnumValue.h" +#include "Cesium3DTiles/Library.h" + +#include <CesiumUtility/ExtensibleObject.h> + +#include <optional> +#include <string> +#include <vector> + +namespace Cesium3DTiles { +/** + * @brief An object defining the values of an enum. + */ +struct CESIUM3DTILES_API Enum final : public CesiumUtility::ExtensibleObject { + static inline constexpr const char* TypeName = "Enum"; + + /** + * @brief Known values for The type of the integer enum value. + */ + struct ValueType { + inline static const std::string INT8 = "INT8"; + + inline static const std::string UINT8 = "UINT8"; + + inline static const std::string INT16 = "INT16"; + + inline static const std::string UINT16 = "UINT16"; + + inline static const std::string INT32 = "INT32"; + + inline static const std::string UINT32 = "UINT32"; + + inline static const std::string INT64 = "INT64"; + + inline static const std::string UINT64 = "UINT64"; + }; + + /** + * @brief The name of the enum, e.g. for display purposes. + */ + std::optional<std::string> name; + + /** + * @brief The description of the enum. + */ + std::optional<std::string> 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<Cesium3DTiles::EnumValue> values; +}; +} // 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 0000000000000000000000000000000000000000..2c01d1b99331a3f1dba09607993e5d01e5760d72 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/Cesium3DTiles/EnumValue.h @@ -0,0 +1,36 @@ +// This file was generated by generate-classes. +// DO NOT EDIT THIS FILE! +#pragma once + +#include "Cesium3DTiles/Library.h" + +#include <CesiumUtility/ExtensibleObject.h> + +#include <cstdint> +#include <optional> +#include <string> + +namespace Cesium3DTiles { +/** + * @brief An enum value. + */ +struct CESIUM3DTILES_API EnumValue final + : public CesiumUtility::ExtensibleObject { + static inline constexpr const char* TypeName = "EnumValue"; + + /** + * @brief The name of the enum value. + */ + std::string name; + + /** + * @brief The description of the enum value. + */ + std::optional<std::string> description; + + /** + * @brief The integer enum value. + */ + int64_t value = int64_t(); +}; +} // 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 0000000000000000000000000000000000000000..9710eb9be708ff9a30d8270ed3a550ba84b1feb5 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/Cesium3DTiles/Extension3dTilesBoundingVolumeS2.h @@ -0,0 +1,41 @@ +// This file was generated by generate-classes. +// DO NOT EDIT THIS FILE! +#pragma once + +#include "Cesium3DTiles/Library.h" + +#include <CesiumUtility/ExtensibleObject.h> + +#include <string> + +namespace Cesium3DTiles { +/** + * @brief 3D Tiles extension for S2 bounding volumes. + */ +struct CESIUM3DTILES_API Extension3dTilesBoundingVolumeS2 final + : public CesiumUtility::ExtensibleObject { + static inline constexpr const char* TypeName = + "Extension3dTilesBoundingVolumeS2"; + static inline 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(); +}; +} // 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 0000000000000000000000000000000000000000..88ccf60d64f79d570da458fccb54779b27395e8e --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/Cesium3DTiles/GroupMetadata.h @@ -0,0 +1,15 @@ +// This file was generated by generate-classes. +// DO NOT EDIT THIS FILE! +#pragma once + +#include "Cesium3DTiles/Library.h" +#include "Cesium3DTiles/MetadataEntity.h" + +namespace Cesium3DTiles { +/** + * @brief An object containing metadata about a group. + */ +struct CESIUM3DTILES_API GroupMetadata final : public MetadataEntity { + static inline constexpr const char* TypeName = "GroupMetadata"; +}; +} // 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 0000000000000000000000000000000000000000..56666c78018fc64d54f39d3a9898e9def9bcfccf --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/Cesium3DTiles/ImplicitTiling.h @@ -0,0 +1,57 @@ +// This file was generated by generate-classes. +// DO NOT EDIT THIS FILE! +#pragma once + +#include "Cesium3DTiles/Library.h" +#include "Cesium3DTiles/Subtrees.h" + +#include <CesiumUtility/ExtensibleObject.h> + +#include <cstdint> + +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 { + static inline constexpr const char* TypeName = "ImplicitTiling"; + + /** + * @brief Known values for A string describing the subdivision scheme used + * within the tileset. + */ + struct SubdivisionScheme { + inline static const std::string QUADTREE = "QUADTREE"; + + 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; +}; +} // 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 0000000000000000000000000000000000000000..b68e1a4845660a1271875632a70f6fa2f1ac8a1a --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/Cesium3DTiles/Library.h @@ -0,0 +1,16 @@ +#pragma once + +/** + * @brief Classes for using [3D Tiles](https://github.com/CesiumGS/3d-tiles). + */ +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 0000000000000000000000000000000000000000..15b1436ae9b0d4c817f7117ffc4bef65baa4dade --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/Cesium3DTiles/MetadataEntity.h @@ -0,0 +1,40 @@ +// This file was generated by generate-classes. +// DO NOT EDIT THIS FILE! +#pragma once + +#include "Cesium3DTiles/Library.h" + +#include <CesiumUtility/ExtensibleObject.h> +#include <CesiumUtility/JsonValue.h> + +#include <string> +#include <unordered_map> + +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 { + static inline 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<std::string, CesiumUtility::JsonValue> properties; +}; +} // 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 0000000000000000000000000000000000000000..353ed992181f3dee03904a9079bfe5e8c3bd657d --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/Cesium3DTiles/Properties.h @@ -0,0 +1,29 @@ +// This file was generated by generate-classes. +// DO NOT EDIT THIS FILE! +#pragma once + +#include "Cesium3DTiles/Library.h" + +#include <CesiumUtility/ExtensibleObject.h> + +namespace Cesium3DTiles { +/** + * @brief A dictionary object of metadata about per-feature properties. + */ +struct CESIUM3DTILES_API Properties final + : public CesiumUtility::ExtensibleObject { + static inline constexpr const char* TypeName = "Properties"; + + /** + * @brief The maximum value of this property of all the features in the + * tileset. + */ + double maximum = double(); + + /** + * @brief The minimum value of this property of all the features in the + * tileset. + */ + double minimum = double(); +}; +} // 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 0000000000000000000000000000000000000000..e2a24a90981bda62d0532781dc4000a8f65dbf4e --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/Cesium3DTiles/PropertyStatistics.h @@ -0,0 +1,85 @@ +// This file was generated by generate-classes. +// DO NOT EDIT THIS FILE! +#pragma once + +#include "Cesium3DTiles/Library.h" + +#include <CesiumUtility/ExtensibleObject.h> +#include <CesiumUtility/JsonValue.h> + +#include <optional> +#include <unordered_map> + +namespace Cesium3DTiles { +/** + * @brief Statistics about property values. + */ +struct CESIUM3DTILES_API PropertyStatistics final + : public CesiumUtility::ExtensibleObject { + static inline 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<CesiumUtility::JsonValue> 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<CesiumUtility::JsonValue> 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<CesiumUtility::JsonValue> 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<CesiumUtility::JsonValue> 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<CesiumUtility::JsonValue> 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<CesiumUtility::JsonValue> 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<CesiumUtility::JsonValue> 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<std::string, CesiumUtility::JsonValue> occurrences; +}; +} // 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 0000000000000000000000000000000000000000..16177e63e98297378a1b7e464e545fb3b9437983 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/Cesium3DTiles/PropertyTable.h @@ -0,0 +1,49 @@ +// This file was generated by generate-classes. +// DO NOT EDIT THIS FILE! +#pragma once + +#include "Cesium3DTiles/Library.h" +#include "Cesium3DTiles/PropertyTableProperty.h" + +#include <CesiumUtility/ExtensibleObject.h> + +#include <cstdint> +#include <optional> +#include <string> +#include <unordered_map> + +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 { + static inline constexpr const char* TypeName = "PropertyTable"; + + /** + * @brief The name of the property table, e.g. for display purposes. + */ + std::optional<std::string> 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<std::string, Cesium3DTiles::PropertyTableProperty> + properties; +}; +} // 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 0000000000000000000000000000000000000000..74f2423b1f5a0a875a9d084dd37b972625266fdf --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/Cesium3DTiles/PropertyTableProperty.h @@ -0,0 +1,138 @@ +// This file was generated by generate-classes. +// DO NOT EDIT THIS FILE! +#pragma once + +#include "Cesium3DTiles/Library.h" + +#include <CesiumUtility/ExtensibleObject.h> +#include <CesiumUtility/JsonValue.h> + +#include <cstdint> +#include <optional> + +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 { + static inline constexpr const char* TypeName = "PropertyTableProperty"; + + /** + * @brief Known values for The type of values in `arrayOffsets`. + */ + struct ArrayOffsetType { + inline static const std::string UINT8 = "UINT8"; + + inline static const std::string UINT16 = "UINT16"; + + inline static const std::string UINT32 = "UINT32"; + + inline static const std::string UINT64 = "UINT64"; + }; + + /** + * @brief Known values for The type of values in `stringOffsets`. + */ + struct StringOffsetType { + inline static const std::string UINT8 = "UINT8"; + + inline static const std::string UINT16 = "UINT16"; + + inline static const std::string UINT32 = "UINT32"; + + 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<int64_t> 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<int64_t> 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<CesiumUtility::JsonValue> 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<CesiumUtility::JsonValue> 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<CesiumUtility::JsonValue> 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<CesiumUtility::JsonValue> min; +}; +} // 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 0000000000000000000000000000000000000000..568e619d4105d5975b0086a3f187ac1cc37ffd30 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/Cesium3DTiles/Schema.h @@ -0,0 +1,57 @@ +// This file was generated by generate-classes. +// DO NOT EDIT THIS FILE! +#pragma once + +#include "Cesium3DTiles/Class.h" +#include "Cesium3DTiles/Enum.h" +#include "Cesium3DTiles/Library.h" + +#include <CesiumUtility/ExtensibleObject.h> + +#include <optional> +#include <string> +#include <unordered_map> + +namespace Cesium3DTiles { +/** + * @brief An object defining classes and enums. + */ +struct CESIUM3DTILES_API Schema final : public CesiumUtility::ExtensibleObject { + static inline 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<std::string> name; + + /** + * @brief The description of the schema. + */ + std::optional<std::string> description; + + /** + * @brief Application-specific version of the schema. + */ + std::optional<std::string> 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<std::string, Cesium3DTiles::Class> 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<std::string, Cesium3DTiles::Enum> enums; +}; +} // 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 0000000000000000000000000000000000000000..2fb0b6bba6c6440b2d41c8542f08be11144a35ba --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/Cesium3DTiles/Statistics.h @@ -0,0 +1,27 @@ +// This file was generated by generate-classes. +// DO NOT EDIT THIS FILE! +#pragma once + +#include "Cesium3DTiles/ClassStatistics.h" +#include "Cesium3DTiles/Library.h" + +#include <CesiumUtility/ExtensibleObject.h> + +#include <unordered_map> + +namespace Cesium3DTiles { +/** + * @brief Statistics about entities. + */ +struct CESIUM3DTILES_API Statistics final + : public CesiumUtility::ExtensibleObject { + static inline constexpr const char* TypeName = "Statistics"; + + /** + * @brief A dictionary, where each key corresponds to a class ID in the + * `classes` dictionary and each value is an object containing statistics + * about entities that conform to the class. + */ + std::unordered_map<std::string, Cesium3DTiles::ClassStatistics> classes; +}; +} // 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 0000000000000000000000000000000000000000..21935e84688bf4b4f2a3d9aaf651bc1e0910c177 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/Cesium3DTiles/Subtree.h @@ -0,0 +1,103 @@ +// This file was generated by generate-classes. +// DO NOT EDIT THIS FILE! +#pragma once + +#include "Cesium3DTiles/Availability.h" +#include "Cesium3DTiles/Buffer.h" +#include "Cesium3DTiles/BufferView.h" +#include "Cesium3DTiles/Library.h" +#include "Cesium3DTiles/MetadataEntity.h" +#include "Cesium3DTiles/PropertyTable.h" + +#include <CesiumUtility/ExtensibleObject.h> + +#include <cstdint> +#include <optional> +#include <vector> + +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 { + static inline constexpr const char* TypeName = "Subtree"; + + /** + * @brief An array of buffers. + */ + std::vector<Cesium3DTiles::Buffer> buffers; + + /** + * @brief An array of buffer views. + */ + std::vector<Cesium3DTiles::BufferView> bufferViews; + + /** + * @brief An array of property tables. + */ + std::vector<Cesium3DTiles::PropertyTable> 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<Cesium3DTiles::Availability> 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<int64_t> 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<int64_t> contentMetadata; + + /** + * @brief Subtree metadata encoded in JSON. + */ + std::optional<Cesium3DTiles::MetadataEntity> subtreeMetadata; +}; +} // 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 0000000000000000000000000000000000000000..41269de1759611c3029f3f833db5f1ffec8eb88b --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/Cesium3DTiles/Subtrees.h @@ -0,0 +1,24 @@ +// This file was generated by generate-classes. +// DO NOT EDIT THIS FILE! +#pragma once + +#include "Cesium3DTiles/Library.h" + +#include <CesiumUtility/ExtensibleObject.h> + +#include <string> + +namespace Cesium3DTiles { +/** + * @brief An object describing the location of subtree files. + */ +struct CESIUM3DTILES_API Subtrees final + : public CesiumUtility::ExtensibleObject { + static inline 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; +}; +} // 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 0000000000000000000000000000000000000000..c9b3314ec87389bab337dc5f43d2226af567d566 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/Cesium3DTiles/Tile.h @@ -0,0 +1,110 @@ +// This file was generated by generate-classes. +// DO NOT EDIT THIS FILE! +#pragma once + +#include "Cesium3DTiles/BoundingVolume.h" +#include "Cesium3DTiles/Content.h" +#include "Cesium3DTiles/ImplicitTiling.h" +#include "Cesium3DTiles/Library.h" +#include "Cesium3DTiles/MetadataEntity.h" + +#include <CesiumUtility/ExtensibleObject.h> + +#include <optional> +#include <vector> + +namespace Cesium3DTiles { +/** + * @brief A tile in a 3D Tiles tileset. + */ +struct CESIUM3DTILES_API Tile final : public CesiumUtility::ExtensibleObject { + static inline 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 { + inline static const std::string ADD = "ADD"; + + 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<Cesium3DTiles::BoundingVolume> 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<std::string> 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<double> 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<Cesium3DTiles::Content> content; + + /** + * @brief An array of contents. When this is defined, then `content` shall be + * undefined. + */ + std::vector<Cesium3DTiles::Content> contents; + + /** + * @brief A metadata entity that is associated with this tile. + */ + std::optional<Cesium3DTiles::MetadataEntity> metadata; + + /** + * @brief An object that describes the implicit subdivision of this tile. + */ + std::optional<Cesium3DTiles::ImplicitTiling> 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, the length of this array is zero, and children may not be defined. + */ + std::vector<Cesium3DTiles::Tile> children; +}; +} // 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 0000000000000000000000000000000000000000..2746daedf5c27fbe82ace948438074be2584b697 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/Cesium3DTiles/Tileset.h @@ -0,0 +1,90 @@ +// This file was generated by generate-classes. +// DO NOT EDIT THIS FILE! +#pragma once + +#include "Cesium3DTiles/Asset.h" +#include "Cesium3DTiles/GroupMetadata.h" +#include "Cesium3DTiles/Library.h" +#include "Cesium3DTiles/MetadataEntity.h" +#include "Cesium3DTiles/Properties.h" +#include "Cesium3DTiles/Schema.h" +#include "Cesium3DTiles/Statistics.h" +#include "Cesium3DTiles/Tile.h" + +#include <CesiumUtility/ExtensibleObject.h> + +#include <optional> +#include <string> +#include <unordered_map> +#include <vector> + +namespace Cesium3DTiles { +/** + * @brief A 3D Tiles tileset. + */ +struct CESIUM3DTILES_API Tileset final + : public CesiumUtility::ExtensibleObject { + static inline 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<std::string, Cesium3DTiles::Properties> properties; + + /** + * @brief An object defining the structure of metadata classes and enums. When + * this is defined, then `schemaUri` shall be undefined. + */ + std::optional<Cesium3DTiles::Schema> schema; + + /** + * @brief The URI (or IRI) of the external schema file. When this is defined, + * then `schema` shall be undefined. + */ + std::optional<std::string> schemaUri; + + /** + * @brief An object containing statistics about metadata entities. + */ + std::optional<Cesium3DTiles::Statistics> 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<Cesium3DTiles::GroupMetadata> groups; + + /** + * @brief A metadata entity that is associated with this tileset. + */ + std::optional<Cesium3DTiles::MetadataEntity> 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<std::string> extensionsUsed; + + /** + * @brief Names of 3D Tiles extensions required to properly load this tileset. + */ + std::vector<std::string> extensionsRequired; +}; +} // namespace Cesium3DTiles 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 0000000000000000000000000000000000000000..8dc93b6683d72f5ce7493211df9a958d31112ea3 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/Cesium3DTilesReader/Library.h @@ -0,0 +1,16 @@ +#pragma once + +/** + * @brief Classes for reading [3D Tiles](https://github.com/CesiumGS/3d-tiles). + */ +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/SchemaReader.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/Cesium3DTilesReader/SchemaReader.h new file mode 100644 index 0000000000000000000000000000000000000000..4b720322412115e74d2a0ff43991d5fc2cba0524 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/Cesium3DTilesReader/SchemaReader.h @@ -0,0 +1,74 @@ +#pragma once + +#include "Cesium3DTilesReader/Library.h" + +#include <Cesium3DTiles/Schema.h> +#include <CesiumJsonReader/ExtensionReaderContext.h> + +#include <gsl/span> + +#include <functional> +#include <memory> +#include <optional> +#include <string> +#include <unordered_map> +#include <vector> + +namespace Cesium3DTilesReader { + +/** + * @brief The result of reading a schema with + * {@link SchemaReader::readSchema}. + */ +struct CESIUM3DTILESREADER_API SchemaReaderResult { + /** + * @brief The read schema, or std::nullopt if the schema could not be read. + */ + std::optional<Cesium3DTiles::Schema> schema; + + /** + * @brief Errors, if any, that occurred during the load process. + */ + std::vector<std::string> errors; + + /** + * @brief Warnings, if any, that occurred during the load process. + */ + std::vector<std::string> warnings; +}; + +/** + * @brief Reads schemas. + */ +class CESIUM3DTILESREADER_API SchemaReader { +public: + /** + * @brief Constructs a new instance. + */ + SchemaReader(); + + /** + * @brief Gets the context used to control how extensions are loaded from a + * schema. + */ + CesiumJsonReader::ExtensionReaderContext& getExtensions(); + + /** + * @brief Gets the context used to control how extensions are loaded from a + * schema. + */ + const CesiumJsonReader::ExtensionReaderContext& getExtensions() const; + + /** + * @brief Reads a schema. + * + * @param data The buffer from which to read the schema. + * @return The result of reading the schame. + */ + SchemaReaderResult readSchema(const gsl::span<const std::byte>& data) const; + +private: + CesiumJsonReader::ExtensionReaderContext _context; +}; + +} // 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 0000000000000000000000000000000000000000..1f1d2f64aea0e4ca0464560e43e9fd5fccedd0bb --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/Cesium3DTilesReader/SubtreeReader.h @@ -0,0 +1,75 @@ +#pragma once + +#include "Cesium3DTilesReader/Library.h" + +#include <Cesium3DTiles/Subtree.h> +#include <CesiumJsonReader/ExtensionReaderContext.h> + +#include <gsl/span> + +#include <functional> +#include <memory> +#include <optional> +#include <string> +#include <unordered_map> +#include <vector> + +namespace Cesium3DTilesReader { + +/** + * @brief The result of reading a subtree with + * {@link SubtreeReader::readSubtree}. + */ +struct CESIUM3DTILESREADER_API SubtreeReaderResult { + /** + * @brief The read subtree, or std::nullopt if the subtree could not be read. + */ + std::optional<Cesium3DTiles::Subtree> subtree; + + /** + * @brief Errors, if any, that occurred during the load process. + */ + std::vector<std::string> errors; + + /** + * @brief Warnings, if any, that occurred during the load process. + */ + std::vector<std::string> warnings; +}; + +/** + * @brief Reads subtrees. + */ +class CESIUM3DTILESREADER_API SubtreeReader { +public: + /** + * @brief Constructs a new instance. + */ + SubtreeReader(); + + /** + * @brief Gets the context used to control how extensions are loaded from a + * subtree. + */ + CesiumJsonReader::ExtensionReaderContext& getExtensions(); + + /** + * @brief Gets the context used to control how extensions are loaded from a + * subtree. + */ + const CesiumJsonReader::ExtensionReaderContext& getExtensions() const; + + /** + * @brief Reads a subtree. + * + * @param data The buffer from which to read the subtree. + * @param options Options for how to read the subtree. + * @return The result of reading the subtree. + */ + SubtreeReaderResult readSubtree(const gsl::span<const std::byte>& data) const; + +private: + CesiumJsonReader::ExtensionReaderContext _context; +}; + +} // 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 0000000000000000000000000000000000000000..b5a573693ff3f379526d0fd2494948497656ecc3 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/Cesium3DTilesReader/TilesetReader.h @@ -0,0 +1,74 @@ +#pragma once + +#include "Cesium3DTilesReader/Library.h" + +#include <Cesium3DTiles/Tileset.h> +#include <CesiumJsonReader/ExtensionReaderContext.h> + +#include <gsl/span> + +#include <functional> +#include <memory> +#include <optional> +#include <string> +#include <unordered_map> +#include <vector> + +namespace Cesium3DTilesReader { + +/** + * @brief The result of reading a tileset with + * {@link TilesetReader::readTileset}. + */ +struct CESIUM3DTILESREADER_API TilesetReaderResult { + /** + * @brief The read tileset, or std::nullopt if the tileset could not be read. + */ + std::optional<Cesium3DTiles::Tileset> tileset; + + /** + * @brief Errors, if any, that occurred during the load process. + */ + std::vector<std::string> errors; + + /** + * @brief Warnings, if any, that occurred during the load process. + */ + std::vector<std::string> warnings; +}; + +/** + * @brief Reads tilesets. + */ +class CESIUM3DTILESREADER_API TilesetReader { +public: + /** + * @brief Constructs a new instance. + */ + TilesetReader(); + + /** + * @brief Gets the context used to control how extensions are loaded from a + * tileset. + */ + CesiumJsonReader::ExtensionReaderContext& getExtensions(); + + /** + * @brief Gets the context used to control how extensions are loaded from a + * tileset. + */ + const CesiumJsonReader::ExtensionReaderContext& getExtensions() const; + + /** + * @brief Reads a tileset. + * + * @param data The buffer from which to read the tileset. + * @return The result of reading the tileset. + */ + TilesetReaderResult readTileset(const gsl::span<const std::byte>& data) const; + +private: + CesiumJsonReader::ExtensionReaderContext _context; +}; + +} // namespace Cesium3DTilesReader diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/Cesium3DTilesSelection/BingMapsRasterOverlay.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/Cesium3DTilesSelection/BingMapsRasterOverlay.h new file mode 100644 index 0000000000000000000000000000000000000000..3d42a5f883158a2646a168372bdfa46072362fde --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/Cesium3DTilesSelection/BingMapsRasterOverlay.h @@ -0,0 +1,136 @@ +#pragma once + +#include "Library.h" +#include "RasterOverlay.h" + +#include <CesiumAsync/IAssetRequest.h> +#include <CesiumGeospatial/Ellipsoid.h> + +#include <functional> +#include <memory> + +namespace Cesium3DTilesSelection { + +class CreditSystem; + +/** + * @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 CESIUM3DTILESSELECTION_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 ellipsoid The ellipsoid. Default value: + * {@link CesiumGeospatial::Ellipsoid::WGS84}. + * @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 CesiumGeospatial::Ellipsoid& ellipsoid = + CesiumGeospatial::Ellipsoid::WGS84, + const RasterOverlayOptions& overlayOptions = {}); + virtual ~BingMapsRasterOverlay() override; + + virtual CesiumAsync::Future<CreateTileProviderResult> createTileProvider( + const CesiumAsync::AsyncSystem& asyncSystem, + const std::shared_ptr<CesiumAsync::IAssetAccessor>& pAssetAccessor, + const std::shared_ptr<CreditSystem>& pCreditSystem, + const std::shared_ptr<IPrepareRendererResources>& + pPrepareRendererResources, + const std::shared_ptr<spdlog::logger>& pLogger, + CesiumUtility::IntrusivePointer<const RasterOverlay> pOwner) + const override; + +private: + static const std::string BING_LOGO_HTML; + + std::string _url; + std::string _key; + std::string _mapStyle; + std::string _culture; + CesiumGeospatial::Ellipsoid _ellipsoid; +}; + +} // namespace Cesium3DTilesSelection 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 0000000000000000000000000000000000000000..6206fd122a629f88524f3e233bb88b476a407ab6 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/Cesium3DTilesSelection/BoundingVolume.h @@ -0,0 +1,81 @@ +#pragma once + +#include "Library.h" + +#include <CesiumGeometry/BoundingSphere.h> +#include <CesiumGeometry/OrientedBoundingBox.h> +#include <CesiumGeospatial/BoundingRegion.h> +#include <CesiumGeospatial/BoundingRegionWithLooseFittingHeights.h> +#include <CesiumGeospatial/GlobeRectangle.h> +#include <CesiumGeospatial/S2CellBoundingVolume.h> + +#include <optional> +#include <variant> + +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. + * @return The bounding {@link CesiumGeospatial::GlobeRectangle}. + */ +CESIUM3DTILESSELECTION_API std::optional<CesiumGeospatial::GlobeRectangle> +estimateGlobeRectangle(const BoundingVolume& boundingVolume); + +/** + * @brief Returns the bounding region if the bounding volume is a + * {@link BoundingRegion} or a {@link 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); + +} // namespace Cesium3DTilesSelection diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/Cesium3DTilesSelection/CreditSystem.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/Cesium3DTilesSelection/CreditSystem.h new file mode 100644 index 0000000000000000000000000000000000000000..4edcec355cf625a78f6a56f7b31a39b611ad1d4c --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/Cesium3DTilesSelection/CreditSystem.h @@ -0,0 +1,101 @@ +#pragma once + +#include "Library.h" + +#include <string> +#include <unordered_map> +#include <utility> +#include <vector> + +namespace Cesium3DTilesSelection { + +/** + * @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 CESIUM3DTILESSELECTION_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 CESIUM3DTILESSELECTION_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(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 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<Credit>& getCreditsToShowThisFrame() noexcept; + + /** + * @brief Get the credits that were shown last frame but should no longer be + * shown. + */ + const std::vector<Credit>& + 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<HtmlAndLastFrameNumber> _credits; + + int32_t _currentFrameNumber = 0; + std::vector<Credit> _creditsToShowThisFrame; + std::vector<Credit> _creditsToNoLongerShowThisFrame; +}; +} // namespace Cesium3DTilesSelection diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/Cesium3DTilesSelection/DebugColorizeTilesRasterOverlay.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/Cesium3DTilesSelection/DebugColorizeTilesRasterOverlay.h new file mode 100644 index 0000000000000000000000000000000000000000..56e5443cba32f588285e1f4650baaf4b10a933e7 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/Cesium3DTilesSelection/DebugColorizeTilesRasterOverlay.h @@ -0,0 +1,36 @@ +#pragma once + +#include "RasterOverlay.h" + +namespace Cesium3DTilesSelection { + +/** + * @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 CESIUM3DTILESSELECTION_API DebugColorizeTilesRasterOverlay + : public RasterOverlay { +public: + /** + * @copydoc RasterOverlay::RasterOverlay + */ + DebugColorizeTilesRasterOverlay( + const std::string& name, + const RasterOverlayOptions& overlayOptions = RasterOverlayOptions()); + + /** + * @copydoc RasterOverlay::createTileProvider + */ + virtual CesiumAsync::Future<CreateTileProviderResult> createTileProvider( + const CesiumAsync::AsyncSystem& asyncSystem, + const std::shared_ptr<CesiumAsync::IAssetAccessor>& pAssetAccessor, + const std::shared_ptr<CreditSystem>& pCreditSystem, + const std::shared_ptr<IPrepareRendererResources>& + pPrepareRendererResources, + const std::shared_ptr<spdlog::logger>& pLogger, + CesiumUtility::IntrusivePointer<const RasterOverlay> pOwner) + const override; +}; + +} // namespace Cesium3DTilesSelection diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/Cesium3DTilesSelection/ErrorList.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/Cesium3DTilesSelection/ErrorList.h new file mode 100644 index 0000000000000000000000000000000000000000..2ebd1a43e6d71813f3feb74a73a08f916844a8b7 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/Cesium3DTilesSelection/ErrorList.h @@ -0,0 +1,110 @@ +#pragma once + +#include "Library.h" + +#include <CesiumUtility/joinToString.h> + +#include <spdlog/spdlog.h> + +#include <string> +#include <vector> + +namespace Cesium3DTilesSelection { +/** + * @brief The container to store the error and warning list when loading a tile + * or glTF content + */ +struct CESIUM3DTILESSELECTION_API 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(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 <typename ErrorStr> void emplaceError(ErrorStr&& error) { + errors.emplace_back(std::forward<ErrorStr>(error)); + } + + /** + * @brief Add a warning message + * + * @param error The warning message to be added. + */ + template <typename WarningStr> void emplaceWarning(WarningStr&& warning) { + warnings.emplace_back(std::forward<WarningStr>(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 <typename PromptStr> + void logError( + const std::shared_ptr<spdlog::logger>& pLogger, + PromptStr&& prompt) const noexcept { + if (!errors.empty()) { + SPDLOG_LOGGER_ERROR( + pLogger, + "{}:\n- {}", + std::forward<PromptStr>(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 <typename PromptStr> + void logWarning( + const std::shared_ptr<spdlog::logger>& pLogger, + PromptStr&& prompt) const noexcept { + if (!warnings.empty()) { + SPDLOG_LOGGER_WARN( + pLogger, + "{}:\n- {}", + std::forward<PromptStr>(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<std::string> errors; + + /** + * @brief The warning messages of this container + */ + std::vector<std::string> warnings; +}; +} // namespace Cesium3DTilesSelection diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/Cesium3DTilesSelection/GltfConverterResult.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/Cesium3DTilesSelection/GltfConverterResult.h new file mode 100644 index 0000000000000000000000000000000000000000..83f50cf4b400b19c70b49380e5c8c9aa039582c4 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/Cesium3DTilesSelection/GltfConverterResult.h @@ -0,0 +1,31 @@ +#pragma once + +#include "Library.h" + +#include <Cesium3DTilesSelection/ErrorList.h> +#include <CesiumGltf/Model.h> + +#include <optional> + +namespace Cesium3DTilesSelection { +/** + * @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 CESIUM3DTILESSELECTION_API GltfConverterResult { + /** + * @brief The gltf model converted from a binary content. This is empty if + * there are errors during the conversion + */ + std::optional<CesiumGltf::Model> 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 + */ + ErrorList errors; +}; +} // namespace Cesium3DTilesSelection diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/Cesium3DTilesSelection/GltfConverters.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/Cesium3DTilesSelection/GltfConverters.h new file mode 100644 index 0000000000000000000000000000000000000000..f027da24cc174801bdd8b66aa3f048895c42759a --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/Cesium3DTilesSelection/GltfConverters.h @@ -0,0 +1,169 @@ +#pragma once + +#include "Library.h" + +#include <Cesium3DTilesSelection/GltfConverterResult.h> +#include <CesiumGltfReader/GltfReader.h> + +#include <gsl/span> + +#include <optional> +#include <string> +#include <string_view> + +namespace Cesium3DTilesSelection { +/** + * @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 CESIUM3DTILESSELECTION_API GltfConverters { +public: + /** + * @brief A function pointer that can create a {@link GltfConverterResult} from a + * tile binary content. + */ + using ConverterFunction = GltfConverterResult (*)( + const gsl::span<const std::byte>& content, + const CesiumGltfReader::GltfReaderOptions& options); + + /** + * @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 gsl::span<const std::byte>& 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. + * @return The {@link GltfConverterResult} that stores the gltf model converted from the binary data. + */ + static GltfConverterResult convert( + const std::string& filePath, + const gsl::span<const std::byte>& content, + const CesiumGltfReader::GltfReaderOptions& options); + + /** + * @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. + * @return The {@link GltfConverterResult} that stores the gltf model converted from the binary data. + */ + static GltfConverterResult convert( + const gsl::span<const std::byte>& content, + const CesiumGltfReader::GltfReaderOptions& options); + +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 gsl::span<const std::byte>& content, + std::string& magic); + + static std::unordered_map<std::string, ConverterFunction> _loadersByMagic; + static std::unordered_map<std::string, ConverterFunction> + _loadersByFileExtension; +}; +} // namespace Cesium3DTilesSelection diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/Cesium3DTilesSelection/GltfUtilities.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/Cesium3DTilesSelection/GltfUtilities.h new file mode 100644 index 0000000000000000000000000000000000000000..dd823816d5f94a3eb079b1654956e4b70df6a74e --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/Cesium3DTilesSelection/GltfUtilities.h @@ -0,0 +1,139 @@ +#pragma once + +#include "Library.h" + +#include <Cesium3DTilesSelection/CreditSystem.h> +#include <Cesium3DTilesSelection/RasterOverlayDetails.h> +#include <CesiumGeospatial/BoundingRegion.h> +#include <CesiumGeospatial/GlobeRectangle.h> +#include <CesiumGltf/Model.h> + +#include <glm/glm.hpp> + +#include <vector> + +namespace Cesium3DTilesSelection { +/** + * A collection of utility functions that are used to process and transform a + * gltf model + */ +struct CESIUM3DTILESSELECTION_API GltfUtilities { + /** + * @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 model 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 Creates texture coordinates for mapping {@link RasterOverlay} tiles + * to {@link Tileset} tiles. + * + * 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 named `_CESIUMOVERLAY_n` is added to each primitive, + * where `n` starts with the `firstTextureCoordinateID` passed to this + * function and increases with each projection. + * + * @param gltf The glTF model. + * @param modelToEcefTransform The transformation of this glTF to ECEF + * coordinates. + * @param firstTextureCoordinateID The texture coordinate ID of the first + * projection. + * @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. + * @return The detailed of the generated texture coordinates. + */ + static std::optional<RasterOverlayDetails> + createRasterOverlayTextureCoordinates( + CesiumGltf::Model& gltf, + const glm::dmat4& modelToEcefTransform, + int32_t firstTextureCoordinateID, + const std::optional<CesiumGeospatial::GlobeRectangle>& globeRectangle, + std::vector<CesiumGeospatial::Projection>&& projections); + + /** + * @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 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. + * @return The computed bounding region. + */ + static CesiumGeospatial::BoundingRegion computeBoundingRegion( + const CesiumGltf::Model& gltf, + const glm::dmat4& transform); + + /** + * @brief Parse the copyright field of a gltf model and create credits for it. + * + * @param creditSystems The {@link Cesium3DTilesSelection::CreditSystem} that is used to credits for the gltf's copyright + * @param gltf The model. + * @return showOnScreen The option to indicate if the created credits should + * be shown on the screen. + */ + static std::vector<Credit> parseGltfCopyright( + CreditSystem& creditSystems, + const CesiumGltf::Model& gltf, + bool showOnScreen); +}; +} // 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 0000000000000000000000000000000000000000..1209a6062776817b38e977e5fd652e3f871b4b2a --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/Cesium3DTilesSelection/IPrepareRendererResources.h @@ -0,0 +1,211 @@ +#pragma once + +#include "Library.h" +#include "TileLoadResult.h" + +#include <CesiumAsync/Future.h> + +#include <glm/mat4x4.hpp> +#include <glm/vec2.hpp> +#include <gsl/span> + +#include <any> + +namespace CesiumAsync { +class AsyncSystem; +} + +namespace CesiumGeometry { +struct Rectangle; +} + +namespace CesiumGltf { +struct ImageCesium; +struct Model; +} // namespace CesiumGltf + +namespace Cesium3DTilesSelection { + +class Tile; +class RasterOverlayTile; + +struct TileLoadResultAndRenderResources { + TileLoadResult result; + 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 can be obtained + * via {@link Tileset::getExternals}. + */ +class CESIUM3DTILESSELECTION_API IPrepareRendererResources { +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<TileLoadResultAndRenderResources> + 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 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::ImageCesium& 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 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 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* 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 called + * {@link 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; + + /** + * @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 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 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 0000000000000000000000000000000000000000..dd6c036827444ca4f1e46a241a0bc6bb66a6e670 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/Cesium3DTilesSelection/ITileExcluder.h @@ -0,0 +1,17 @@ +#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; + virtual bool shouldExclude(const Tile& tile) const noexcept = 0; +}; + +} // namespace Cesium3DTilesSelection diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/Cesium3DTilesSelection/IonRasterOverlay.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/Cesium3DTilesSelection/IonRasterOverlay.h new file mode 100644 index 0000000000000000000000000000000000000000..c9e7384f4ccf8235375e5b9d256985ea6a7be550 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/Cesium3DTilesSelection/IonRasterOverlay.h @@ -0,0 +1,82 @@ +#pragma once + +#include "Library.h" +#include "RasterOverlay.h" + +#include <CesiumAsync/IAssetRequest.h> +#include <CesiumGeospatial/Ellipsoid.h> + +#include <functional> +#include <memory> + +namespace Cesium3DTilesSelection { + +class CreditSystem; + +/** + * @brief A {@link RasterOverlay} that obtains imagery data from Cesium ion. + */ +class CESIUM3DTILESSELECTION_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. + */ + IonRasterOverlay( + const std::string& name, + int64_t ionAssetID, + const std::string& ionAccessToken, + const RasterOverlayOptions& overlayOptions = {}); + virtual ~IonRasterOverlay() override; + + virtual CesiumAsync::Future<CreateTileProviderResult> createTileProvider( + const CesiumAsync::AsyncSystem& asyncSystem, + const std::shared_ptr<CesiumAsync::IAssetAccessor>& pAssetAccessor, + const std::shared_ptr<CreditSystem>& pCreditSystem, + const std::shared_ptr<IPrepareRendererResources>& + pPrepareRendererResources, + const std::shared_ptr<spdlog::logger>& pLogger, + CesiumUtility::IntrusivePointer<const RasterOverlay> pOwner) + const override; + +private: + int64_t _ionAssetID; + std::string _ionAccessToken; + + 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<AssetEndpointAttribution> attributions; + }; + + static std::unordered_map<std::string, ExternalAssetEndpoint> endpointCache; + + CesiumAsync::Future<CreateTileProviderResult> createTileProvider( + const ExternalAssetEndpoint& endpoint, + const CesiumAsync::AsyncSystem& asyncSystem, + const std::shared_ptr<CesiumAsync::IAssetAccessor>& pAssetAccessor, + const std::shared_ptr<CreditSystem>& pCreditSystem, + const std::shared_ptr<IPrepareRendererResources>& + pPrepareRendererResources, + const std::shared_ptr<spdlog::logger>& pLogger, + CesiumUtility::IntrusivePointer<const RasterOverlay> pOwner) const; +}; + +} // 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 0000000000000000000000000000000000000000..7383da319bd0573e41025c2a55f05ee2a20b5713 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/Cesium3DTilesSelection/Library.h @@ -0,0 +1,16 @@ +#pragma once + +/** + * @brief Classes that implement the 3D Tiles standard + */ +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/QuadtreeRasterOverlayTileProvider.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/Cesium3DTilesSelection/QuadtreeRasterOverlayTileProvider.h new file mode 100644 index 0000000000000000000000000000000000000000..29001a34946337adfe6aafbb5eaec11b2294de5b --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/Cesium3DTilesSelection/QuadtreeRasterOverlayTileProvider.h @@ -0,0 +1,181 @@ +#pragma once + +#include "CreditSystem.h" +#include "IPrepareRendererResources.h" +#include "Library.h" +#include "RasterOverlayTileProvider.h" +#include "TileID.h" + +#include <CesiumAsync/AsyncSystem.h> +#include <CesiumAsync/IAssetAccessor.h> +#include <CesiumGeometry/QuadtreeTileID.h> +#include <CesiumGeometry/QuadtreeTilingScheme.h> + +#include <list> +#include <memory> +#include <optional> + +namespace Cesium3DTilesSelection { + +class CESIUM3DTILESSELECTION_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 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 {@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<const RasterOverlay>& pOwner, + const CesiumAsync::AsyncSystem& asyncSystem, + const std::shared_ptr<CesiumAsync::IAssetAccessor>& pAssetAccessor, + std::optional<Credit> credit, + const std::shared_ptr<IPrepareRendererResources>& + pPrepareRendererResources, + const std::shared_ptr<spdlog::logger>& 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<LoadedRasterOverlayImage> + loadQuadtreeTileImage(const CesiumGeometry::QuadtreeTileID& tileID) const = 0; + +private: + virtual CesiumAsync::Future<LoadedRasterOverlayImage> + loadTileImage(RasterOverlayTile& overlayTile) override final; + + struct LoadedQuadtreeImage { + std::shared_ptr<LoadedRasterOverlayImage> pLoaded = nullptr; + std::optional<CesiumGeometry::Rectangle> subset = std::nullopt; + }; + + CesiumAsync::SharedFuture<LoadedQuadtreeImage> + 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<CesiumAsync::SharedFuture<LoadedQuadtreeImage>> + mapRasterTilesToGeometryTile( + const CesiumGeometry::Rectangle& geometryRectangle, + const glm::dvec2 targetScreenPixels); + + void unloadCachedTiles(); + + 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<LoadedQuadtreeImage>& images); + + static LoadedRasterOverlayImage combineImages( + const CesiumGeometry::Rectangle& targetRectangle, + const CesiumGeospatial::Projection& projection, + std::vector<LoadedQuadtreeImage>&& images); + + uint32_t _minimumLevel; + uint32_t _maximumLevel; + uint32_t _imageWidth; + uint32_t _imageHeight; + CesiumGeometry::QuadtreeTilingScheme _tilingScheme; + + struct CacheEntry { + CesiumGeometry::QuadtreeTileID tileID; + CesiumAsync::SharedFuture<LoadedQuadtreeImage> future; + }; + + // Tiles at the beginning of this list are the least recently used (oldest), + // while the tiles at the end are most recently used (newest). + using TileLeastRecentlyUsedList = std::list<CacheEntry>; + TileLeastRecentlyUsedList _tilesOldToRecent; + + // Allows a Future to be looked up by quadtree tile ID. + std::unordered_map< + CesiumGeometry::QuadtreeTileID, + TileLeastRecentlyUsedList::iterator> + _tileLookup; + + std::atomic<int64_t> _cachedBytes; +}; +} // namespace Cesium3DTilesSelection 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 0000000000000000000000000000000000000000..0b986d3bb5834df620eaa5af7ca14177d1988a60 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/Cesium3DTilesSelection/RasterMappedTo3DTile.h @@ -0,0 +1,236 @@ +#pragma once + +#include "IPrepareRendererResources.h" +#include "RasterOverlayTile.h" + +#include <CesiumGeometry/Rectangle.h> +#include <CesiumGeospatial/Projection.h> +#include <CesiumUtility/IntrusivePointer.h> + +#include <memory> + +namespace Cesium3DTilesSelection { + +class Tile; + +/** + * @brief The result of applying a {@link RasterOverlayTile} to geometry. + * + * Instances of this class are used by a {@link Tile} in order to map + * imagery data that is given as {@link 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 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<RasterOverlayTile>& pRasterTile, + int32_t textureCoordinateIndex); + + /** + * @brief Returns a {@link 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`. + */ + RasterOverlayTile* getLoadingTile() noexcept { + return this->_pLoadingTile.get(); + } + + /** @copydoc getLoadingTile */ + const RasterOverlayTile* getLoadingTile() const noexcept { + return this->_pLoadingTile.get(); + } + + /** + * @brief Returns the {@link 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`. + */ + RasterOverlayTile* getReadyTile() noexcept { return this->_pReadyTile.get(); } + + /** @copydoc getReadyTile */ + const 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 {@link Tile::update}. It + * will return whether there is a more detailed version of the + * raster data available. + * + * @param prepareRendererResources The IPrepareRendererResources used to + * create render resources for raster overlay + * @param tile The owner tile. + * @return The {@link MoreDetailAvailable} state. + */ + RasterOverlayTile::MoreDetailAvailable + update(IPrepareRendererResources& prepareRendererResources, Tile& tile); + + 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 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 RasterOverlay} and a {@link Tile}. + * + * The returned mapping will be to a placeholder {@link 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. + * @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, + RasterOverlayTileProvider& tileProvider, + RasterOverlayTileProvider& placeholder, + Tile& tile, + std::vector<CesiumGeospatial::Projection>& missingProjections); + +private: + void computeTranslationAndScale(const Tile& tile); + + CesiumUtility::IntrusivePointer<RasterOverlayTile> _pLoadingTile; + CesiumUtility::IntrusivePointer<RasterOverlayTile> _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/RasterOverlay.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/Cesium3DTilesSelection/RasterOverlay.h new file mode 100644 index 0000000000000000000000000000000000000000..3ea6f1a7ccab7cd89e4239c675c8fee894a3112f --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/Cesium3DTilesSelection/RasterOverlay.h @@ -0,0 +1,235 @@ +#pragma once + +#include "Library.h" +#include "RasterOverlayLoadFailureDetails.h" + +#include <CesiumAsync/IAssetAccessor.h> +#include <CesiumGltf/Ktx2TranscodeTargets.h> +#include <CesiumUtility/IntrusivePointer.h> +#include <CesiumUtility/ReferenceCountedNonThreadSafe.h> + +#include <nonstd/expected.hpp> +#include <spdlog/fwd.h> + +#include <any> +#include <functional> +#include <memory> +#include <optional> +#include <string> + +namespace Cesium3DTilesSelection { + +struct Credit; +class CreditSystem; +class IPrepareRendererResources; +class RasterOverlayTileProvider; +class RasterOverlayCollection; + +/** + * @brief Options for loading raster overlays. + */ +struct CESIUM3DTILESSELECTION_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 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<void(const RasterOverlayLoadFailureDetails&)> loadErrorCallback; + + /** + * @brief Whether or not to display the credits on screen. + */ + bool showCreditsOnScreen = false; + + /** + * @brief Arbitrary data that will be passed to {@link 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 base class for a rasterized image that can be draped + * over a {@link 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 RasterOverlayCollection} + * that is returned by {@link 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<RasterOverlay> { +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 AsyncSystem} instances that compare equal to each other. + */ + CesiumAsync::SharedFuture<void>& + 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<Credit>& getCredits() const noexcept { + return this->_credits; + } + + /** + * @brief Gets the credits for this overlay. + */ + std::vector<Credit>& 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. + * @return The placeholder. + */ + CesiumUtility::IntrusivePointer<RasterOverlayTileProvider> createPlaceholder( + const CesiumAsync::AsyncSystem& asyncSystem, + const std::shared_ptr<CesiumAsync::IAssetAccessor>& pAssetAccessor) const; + + using CreateTileProviderResult = nonstd::expected< + CesiumUtility::IntrusivePointer<RasterOverlayTileProvider>, + 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 CreditSystem} to use when creating a + * per-TileProvider {@link 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<CreateTileProviderResult> createTileProvider( + const CesiumAsync::AsyncSystem& asyncSystem, + const std::shared_ptr<CesiumAsync::IAssetAccessor>& pAssetAccessor, + const std::shared_ptr<CreditSystem>& pCreditSystem, + const std::shared_ptr<IPrepareRendererResources>& + pPrepareRendererResources, + const std::shared_ptr<spdlog::logger>& pLogger, + CesiumUtility::IntrusivePointer<const RasterOverlay> pOwner) const = 0; + +private: + struct DestructionCompleteDetails { + CesiumAsync::AsyncSystem asyncSystem; + CesiumAsync::Promise<void> promise; + CesiumAsync::SharedFuture<void> future; + }; + + std::string _name; + RasterOverlayOptions _options; + std::vector<Credit> _credits; + std::optional<DestructionCompleteDetails> _destructionCompleteDetails; +}; + +} // 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 0000000000000000000000000000000000000000..97107377103a412bf57177543356e1e59d0d0854 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/Cesium3DTilesSelection/RasterOverlayCollection.h @@ -0,0 +1,203 @@ +#pragma once + +#include "Library.h" +#include "RasterOverlay.h" +#include "RasterOverlayTileProvider.h" +#include "Tile.h" +#include "TilesetExternals.h" + +#include <CesiumUtility/IntrusivePointer.h> +#include <CesiumUtility/ReferenceCountedNonThreadSafe.h> +#include <CesiumUtility/Tracing.h> + +#include <gsl/span> + +#include <memory> +#include <vector> + +namespace Cesium3DTilesSelection { + +/** + * @brief A collection of {@link 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 RasterOverlayTileProvider} will be created + * for each raster overlay that had been added. The raster overlay tile provider + * instances will be passed to the {@link 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 + */ + RasterOverlayCollection( + Tile::LoadedLinkedList& loadedTiles, + const TilesetExternals& externals) 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 RasterOverlay} to this collection. + * + * @param pOverlay The pointer to the overlay. This may not be `nullptr`. + */ + void add(const CesiumUtility::IntrusivePointer<RasterOverlay>& pOverlay); + + /** + * @brief Remove the given {@link RasterOverlay} from this collection. + */ + void remove( + const CesiumUtility::IntrusivePointer<RasterOverlay>& pOverlay) noexcept; + + /** + * @brief Gets the overlays in this collection. + */ + const std::vector<CesiumUtility::IntrusivePointer<RasterOverlay>>& + 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<CesiumUtility::IntrusivePointer<RasterOverlayTileProvider>>& + 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<CesiumUtility::IntrusivePointer<RasterOverlayTileProvider>>& + 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 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. + */ + RasterOverlayTileProvider* + findTileProviderForOverlay(RasterOverlay& overlay) noexcept; + + /** + * @copydoc findTileProviderForOverlay + */ + const RasterOverlayTileProvider* + findTileProviderForOverlay(const 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. + */ + RasterOverlayTileProvider* + findPlaceholderTileProviderForOverlay(RasterOverlay& overlay) noexcept; + + /** + * @copydoc findPlaceholderTileProviderForOverlay + */ + const RasterOverlayTileProvider* findPlaceholderTileProviderForOverlay( + const RasterOverlay& overlay) const noexcept; + + /** + * @brief A constant iterator for {@link RasterOverlay} instances. + */ + typedef std::vector<CesiumUtility::IntrusivePointer<RasterOverlay>>:: + 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<OverlayList> { + std::vector<CesiumUtility::IntrusivePointer<RasterOverlay>> overlays{}; + std::vector<CesiumUtility::IntrusivePointer<RasterOverlayTileProvider>> + tileProviders{}; + std::vector<CesiumUtility::IntrusivePointer<RasterOverlayTileProvider>> + placeholders{}; + }; + + Tile::LoadedLinkedList* _pLoadedTiles; + TilesetExternals _externals; + CesiumUtility::IntrusivePointer<OverlayList> _pOverlays; + CESIUM_TRACE_DECLARE_TRACK_SET(_loadingSlots, "Raster Overlay Loading Slot"); +}; + +} // namespace Cesium3DTilesSelection diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/Cesium3DTilesSelection/RasterOverlayDetails.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/Cesium3DTilesSelection/RasterOverlayDetails.h new file mode 100644 index 0000000000000000000000000000000000000000..14b2f2fabec21e68f7c6b76b0d05d3f60d3c8afe --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/Cesium3DTilesSelection/RasterOverlayDetails.h @@ -0,0 +1,79 @@ +#pragma once + +#include "Library.h" + +#include <CesiumGeometry/Rectangle.h> +#include <CesiumGeospatial/BoundingRegion.h> +#include <CesiumGeospatial/Projection.h> + +#include <vector> + +namespace Cesium3DTilesSelection { +/** + * @brief Holds details of the {@link TileRenderContent} that are useful + * for raster overlays. + */ +struct CESIUM3DTILESSELECTION_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<CesiumGeospatial::Projection>&& rasterOverlayProjections, + std::vector<CesiumGeometry::Rectangle>&& 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. + */ + void merge(const RasterOverlayDetails& other); + + /** + * @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<CesiumGeospatial::Projection> rasterOverlayProjections; + + /** + * @brief The rectangle covered by this tile in each of the + * {@link rasterOverlayProjections}. + */ + std::vector<CesiumGeometry::Rectangle> rasterOverlayRectangles; + + /** + * @brief The precise bounding region of this tile. + */ + CesiumGeospatial::BoundingRegion boundingRegion; +}; +} // namespace Cesium3DTilesSelection diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/Cesium3DTilesSelection/RasterOverlayLoadFailureDetails.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/Cesium3DTilesSelection/RasterOverlayLoadFailureDetails.h new file mode 100644 index 0000000000000000000000000000000000000000..128e4e66e38aa6d231ed11dd74642e3f02722f27 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/Cesium3DTilesSelection/RasterOverlayLoadFailureDetails.h @@ -0,0 +1,55 @@ +#pragma once + +#include <CesiumUtility/IntrusivePointer.h> + +#include <memory> +#include <string> + +namespace CesiumAsync { +class IAssetRequest; +} + +namespace Cesium3DTilesSelection { + +class RasterOverlay; + +/** + * @brief The type of load that failed in {@link TilesetLoadFailureDetails}. + */ +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 +}; + +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<CesiumAsync::IAssetRequest> pRequest = nullptr; + + /** + * @brief A human-readable explanation of what failed. + */ + std::string message = ""; +}; + +} // namespace Cesium3DTilesSelection diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/Cesium3DTilesSelection/RasterOverlayTile.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/Cesium3DTilesSelection/RasterOverlayTile.h new file mode 100644 index 0000000000000000000000000000000000000000..d5d7f57d40241308ef4e72e083b2b81fff4b73b8 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/Cesium3DTilesSelection/RasterOverlayTile.h @@ -0,0 +1,260 @@ +#pragma once + +#include <CesiumAsync/AsyncSystem.h> +#include <CesiumAsync/IAssetRequest.h> +#include <CesiumGeometry/Rectangle.h> +#include <CesiumGltf/Model.h> +#include <CesiumUtility/IntrusivePointer.h> +#include <CesiumUtility/ReferenceCountedNonThreadSafe.h> + +#include <vector> + +namespace Cesium3DTilesSelection { + +struct Credit; +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 RasterMappedTo3DTile} class, which combines a + * raster overlay tile with texture coordinates, to map the + * image on the geometry of a {@link Tile}. + */ +class RasterOverlayTile final + : public CesiumUtility::ReferenceCountedNonThreadSafe<RasterOverlayTile> { +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 RasterOverlayTile::update}, which in turn is called by + * {@link Tile::update}. 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 {@link Credit}s needed for this tile. + */ + const std::vector<Credit>& 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. + */ + const CesiumGltf::ImageCesium& getImage() const noexcept { + return this->_image; + } + + /** + * @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. + */ + CesiumGltf::ImageCesium& getImage() noexcept { return this->_image; } + + /** + * @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<Credit> _tileCredits; + LoadState _state; + CesiumGltf::ImageCesium _image; + void* _pRendererResources; + MoreDetailAvailable _moreDetailAvailable; +}; +} // namespace Cesium3DTilesSelection diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/Cesium3DTilesSelection/RasterOverlayTileProvider.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/Cesium3DTilesSelection/RasterOverlayTileProvider.h new file mode 100644 index 0000000000000000000000000000000000000000..6d392c049dc53d59094dbef1376a63d52f03bc69 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/Cesium3DTilesSelection/RasterOverlayTileProvider.h @@ -0,0 +1,407 @@ +#pragma once + +#include "CreditSystem.h" +#include "Library.h" +#include "RasterMappedTo3DTile.h" + +#include <CesiumAsync/IAssetAccessor.h> +#include <CesiumGeospatial/Projection.h> +#include <CesiumGltfReader/GltfReader.h> +#include <CesiumUtility/IntrusivePointer.h> +#include <CesiumUtility/ReferenceCountedNonThreadSafe.h> +#include <CesiumUtility/Tracing.h> + +#include <spdlog/fwd.h> + +#include <cassert> +#include <optional> + +namespace Cesium3DTilesSelection { + +class RasterOverlay; +class RasterOverlayTile; +class IPrepareRendererResources; + +/** + * @brief Summarizes the result of loading an image of a {@link RasterOverlay}. + */ +struct CESIUM3DTILESSELECTION_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. + */ + std::optional<CesiumGltf::ImageCesium> image{}; + + /** + * @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 Credit} objects that decribe the attributions that + * are required when using the image. + */ + std::vector<Credit> credits{}; + + /** + * @brief Error messages from loading the image. + * + * If the image was loaded successfully, this should be empty. + */ + std::vector<std::string> errors{}; + + /** + * @brief Warnings from loading the image. + */ + // Implementation note: In the current implementation, this will + // always be empty, but it might contain warnings in the future, + // when other image types or loaders are used. + std::vector<std::string> warnings{}; + + /** + * @brief Whether more detailed data, beyond this image, is available within + * the bounds of this image. + */ + bool moreDetailAvailable = false; +}; + +/** + * @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<Credit> 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; +}; + +/** + * @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 CESIUM3DTILESSELECTION_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. + */ + RasterOverlayTileProvider( + const CesiumUtility::IntrusivePointer<const RasterOverlay>& pOwner, + const CesiumAsync::AsyncSystem& asyncSystem, + const std::shared_ptr<CesiumAsync::IAssetAccessor>& + pAssetAccessor) 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 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<const RasterOverlay>& pOwner, + const CesiumAsync::AsyncSystem& asyncSystem, + const std::shared_ptr<CesiumAsync::IAssetAccessor>& pAssetAccessor, + std::optional<Credit> credit, + const std::shared_ptr<IPrepareRendererResources>& + pPrepareRendererResources, + const std::shared_ptr<spdlog::logger>& 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 `RasterOverTile` in + * {@link Tile::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<CesiumAsync::IAssetAccessor>& + 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<IPrepareRendererResources>& + 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<spdlog::logger>& 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<RasterOverlayTile> 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 { + assert(this->_totalTilesCurrentlyLoading > -1); + return 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 Credit} if one exists. + */ + const std::optional<Credit>& getCredit() const noexcept { return _credit; } + + /** + * @brief Loads a tile immediately, without throttling requests. + * + * If the tile is not in the `Tile::LoadState::Unloading` 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. + */ + void 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<LoadedRasterOverlayImage> + 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<LoadedRasterOverlayImage> loadTileImageFromUrl( + const std::string& url, + const std::vector<CesiumAsync::IAssetAccessor::THeader>& headers = {}, + LoadTileImageFromUrlOptions&& options = {}) const; + +private: + void 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<RasterOverlay> _pOwner; + CesiumAsync::AsyncSystem _asyncSystem; + std::shared_ptr<CesiumAsync::IAssetAccessor> _pAssetAccessor; + std::optional<Credit> _credit; + std::shared_ptr<IPrepareRendererResources> _pPrepareRendererResources; + std::shared_ptr<spdlog::logger> _pLogger; + CesiumGeospatial::Projection _projection; + CesiumGeometry::Rectangle _coverageRectangle; + CesiumUtility::IntrusivePointer<RasterOverlayTile> _pPlaceholder; + int64_t _tileDataBytes; + int32_t _totalTilesCurrentlyLoading; + int32_t _throttledTilesCurrentlyLoading; + CESIUM_TRACE_DECLARE_TRACK_SET( + _loadingSlots, + "Raster Overlay Tile Loading Slot"); + + static CesiumGltfReader::GltfReader _gltfReader; +}; +} // namespace Cesium3DTilesSelection diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/Cesium3DTilesSelection/RasterizedPolygonsOverlay.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/Cesium3DTilesSelection/RasterizedPolygonsOverlay.h new file mode 100644 index 0000000000000000000000000000000000000000..589d4dd0f0253e43e9c6fa7f97e208e5253524ff --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/Cesium3DTilesSelection/RasterizedPolygonsOverlay.h @@ -0,0 +1,56 @@ +#pragma once + +#include "Library.h" +#include "RasterOverlay.h" +#include "RasterOverlayTileProvider.h" + +#include <CesiumAsync/AsyncSystem.h> +#include <CesiumGeospatial/CartographicPolygon.h> +#include <CesiumGeospatial/Ellipsoid.h> +#include <CesiumGeospatial/Projection.h> + +#include <spdlog/fwd.h> + +#include <memory> +#include <string> +#include <vector> + +namespace Cesium3DTilesSelection { + +class CESIUM3DTILESSELECTION_API RasterizedPolygonsOverlay final + : public RasterOverlay { + +public: + RasterizedPolygonsOverlay( + const std::string& name, + const std::vector<CesiumGeospatial::CartographicPolygon>& polygons, + bool invertSelection, + const CesiumGeospatial::Ellipsoid& ellipsoid, + const CesiumGeospatial::Projection& projection, + const RasterOverlayOptions& overlayOptions = {}); + virtual ~RasterizedPolygonsOverlay() override; + + virtual CesiumAsync::Future<CreateTileProviderResult> createTileProvider( + const CesiumAsync::AsyncSystem& asyncSystem, + const std::shared_ptr<CesiumAsync::IAssetAccessor>& pAssetAccessor, + const std::shared_ptr<CreditSystem>& pCreditSystem, + const std::shared_ptr<IPrepareRendererResources>& + pPrepareRendererResources, + const std::shared_ptr<spdlog::logger>& pLogger, + CesiumUtility::IntrusivePointer<const RasterOverlay> pOwner) + const override; + + const std::vector<CesiumGeospatial::CartographicPolygon>& + getPolygons() const noexcept { + return this->_polygons; + } + + bool getInvertSelection() const noexcept { return this->_invertSelection; } + +private: + std::vector<CesiumGeospatial::CartographicPolygon> _polygons; + bool _invertSelection; + CesiumGeospatial::Ellipsoid _ellipsoid; + CesiumGeospatial::Projection _projection; +}; +} // 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 0000000000000000000000000000000000000000..7ee8c22dea5be0537c11fbfa588db00d1db811af --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/Cesium3DTilesSelection/RasterizedPolygonsTileExcluder.h @@ -0,0 +1,49 @@ +#pragma once + +#include "ITileExcluder.h" +#include "Library.h" + +#include <CesiumUtility/IntrusivePointer.h> + +namespace Cesium3DTilesSelection { + +class RasterizedPolygonsOverlay; + +/** + * @brief When provided to {@link TilesetOptions::excluders}, uses the polygons + * owned by a {@link 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 overlay The overlay definining the polygons. + */ + RasterizedPolygonsTileExcluder( + const CesiumUtility::IntrusivePointer<const 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 RasterizedPolygonsOverlay& getOverlay() const; + +private: + CesiumUtility::IntrusivePointer<const RasterizedPolygonsOverlay> _pOverlay; +}; + +} // 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 0000000000000000000000000000000000000000..7e0a9f25fee1939ec3168844e4d1a0b48621fb07 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/Cesium3DTilesSelection/Tile.h @@ -0,0 +1,548 @@ +#pragma once + +#include "BoundingVolume.h" +#include "Library.h" +#include "RasterMappedTo3DTile.h" +#include "TileContent.h" +#include "TileID.h" +#include "TileRefine.h" +#include "TileSelectionState.h" + +#include <CesiumUtility/DoublyLinkedList.h> + +#include <glm/common.hpp> +#include <glm/mat4x4.hpp> +#include <gsl/span> + +#include <atomic> +#include <limits> +#include <memory> +#include <optional> +#include <string> +#include <vector> + +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 TileContentLoadResult} + * 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. + */ + Tile( + TilesetContentLoader* pLoader, + TileExternalContent 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. + */ + 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. + */ + gsl::span<Tile> getChildren() noexcept { + return gsl::span<Tile>(this->_children); + } + + /** @copydoc Tile::getChildren() */ + gsl::span<const Tile> getChildren() const noexcept { + return gsl::span<const Tile>(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<Tile>&& 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<BoundingVolume>& 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<BoundingVolume>& 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 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 Math::Epsilon5}, returns {@link 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<double>::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<BoundingVolume>& + 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<BoundingVolume>& 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<RasterMappedTo3DTile>& getMappedRasterTiles() noexcept { + return this->_rasterTiles; + } + + /** @copydoc Tile::getMappedRasterTiles() */ + const std::vector<RasterMappedTo3DTile>& + getMappedRasterTiles() const noexcept { + return this->_rasterTiles; + } + + /** + * @brief get the content of the tile. + */ + const TileContent& getContent() const noexcept { return _content; } + + /** @copydoc Tile::getContent() */ + 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<TileContent, TileContentArgs&&...>, + int>> + Tile( + TileConstructorImpl tag, + TileLoadState loadState, + TilesetContentLoader* pLoader, + TileContentArgs&&... args); + + void setParent(Tile* pParent) noexcept; + + void setState(TileLoadState state) noexcept; + + bool shouldContentContinueUpdating() const noexcept; + + void + setContentShouldContinueUpdating(bool shouldContentContinueUpdating) noexcept; + + // Position in bounding-volume hierarchy. + Tile* _pParent; + std::vector<Tile> _children; + + // Properties from tileset.json. + // These are immutable after the tile leaves TileState::Unloaded. + TileID _id; + BoundingVolume _boundingVolume; + std::optional<BoundingVolume> _viewerRequestVolume; + std::optional<BoundingVolume> _contentBoundingVolume; + double _geometricError; + TileRefine _refine; + glm::dmat4x4 _transform; + + // Selection state + TileSelectionState _lastSelectionState; + + // tile content + CesiumUtility::DoublyLinkedListPointers<Tile> _loadedTilesLinks; + TileContent _content; + TilesetContentLoader* _pLoader; + TileLoadState _loadState; + bool _shouldContentContinueUpdating; + + // mapped raster overlay + std::vector<RasterMappedTo3DTile> _rasterTiles; + + friend class TilesetContentManager; + friend class MockTilesetContentManagerTestFixture; + +public: + /** + * @brief A {@link CesiumUtility::DoublyLinkedList} for tile objects. + */ + typedef CesiumUtility::DoublyLinkedList<Tile, &Tile::_loadedTilesLinks> + 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 0000000000000000000000000000000000000000..981b1c08563d48ae9c902a94ab2dc928c9b74650 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/Cesium3DTilesSelection/TileContent.h @@ -0,0 +1,288 @@ +#pragma once + +#include "CreditSystem.h" +#include "Library.h" +#include "RasterOverlayDetails.h" + +#include <CesiumGeospatial/Projection.h> +#include <CesiumGltf/Model.h> + +#include <memory> +#include <variant> + +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 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 RasterOverlayDetails} which is the result of generating raster overlay UVs for the glTF model + * + * @return The {@link RasterOverlayDetails} that is owned by this content + */ + const RasterOverlayDetails& getRasterOverlayDetails() const noexcept; + + /** + * @brief Get the {@link RasterOverlayDetails} which is the result of generating raster overlay UVs for the glTF model + * + * @return The {@link RasterOverlayDetails} that is owned by this content + */ + RasterOverlayDetails& getRasterOverlayDetails() noexcept; + + /** + * @brief Set the {@link RasterOverlayDetails} which is the result of generating raster overlay UVs for the glTF model + * + * @param rasterOverlayDetails The {@link RasterOverlayDetails} that will be owned by this content + */ + void + setRasterOverlayDetails(const RasterOverlayDetails& rasterOverlayDetails); + + /** + * @brief Set the {@link RasterOverlayDetails} which is the result of generating raster overlay UVs for the glTF model + * + * @param rasterOverlayDetails The {@link RasterOverlayDetails} that will be owned by this content + */ + void setRasterOverlayDetails(RasterOverlayDetails&& rasterOverlayDetails); + + /** + * @brief Get the list of {@link Credit} of the content + * + * @return The list of {@link Credit} of the content + */ + const std::vector<Credit>& getCredits() const noexcept; + + /** + * @brief Get the list of {@link Credit} of the content + * + * @return The list of {@link Credit} of the content + */ + std::vector<Credit>& getCredits() noexcept; + + /** + * @brief Set the list of {@link Credit} for the content + * + * @param credits The list of {@link Credit} to be owned by the content + */ + void setCredits(std::vector<Credit>&& credits); + + /** + * @brief Set the list of {@link Credit} for the content + * + * @param credits The list of {@link Credit} to be owned by the content + */ + void setCredits(const std::vector<Credit>& 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; + RasterOverlayDetails _rasterOverlayDetails; + std::vector<Credit> _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, + TileExternalContent, + std::unique_ptr<TileRenderContent>>; + +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(TileExternalContent 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(TileExternalContent content); + + /** + * @brief Set a glTF model content for a tile + */ + void setContentKind(std::unique_ptr<TileRenderContent>&& 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 + * + * @return 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 + * + * @return The {@link TileRenderContent} which stores the glTF model + * and render resources of the tile + */ + TileRenderContent* getRenderContent() 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 0000000000000000000000000000000000000000..b5ee6833c18d5b647474601b45ea0c454630defe --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/Cesium3DTilesSelection/TileID.h @@ -0,0 +1,61 @@ +#pragma once + +#include "Library.h" + +#include <CesiumGeometry/OctreeTileID.h> +#include <CesiumGeometry/QuadtreeTileID.h> + +#include <string> +#include <variant> + +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 0000000000000000000000000000000000000000..dce5889f4fbde4754cb0a9a6b32a880c34b7c673 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/Cesium3DTilesSelection/TileLoadResult.h @@ -0,0 +1,140 @@ +#pragma once + +#include "BoundingVolume.h" +#include "RasterOverlayDetails.h" +#include "TileContent.h" + +#include <CesiumAsync/IAssetRequest.h> +#include <CesiumGeometry/Axis.h> +#include <CesiumGltf/Model.h> + +#include <functional> +#include <memory> +#include <optional> +#include <variant> + +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 TilesetContentLoader::loadTileContent} and + * {@link 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<BoundingVolume> 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<BoundingVolume> updatedContentBoundingVolume; + + /** + * @brief Holds details of the {@link TileRenderContent} that are useful + * for raster overlays. + */ + std::optional<RasterOverlayDetails> rasterOverlayDetails; + + /** + * @brief The request that is created to download the tile content. + */ + std::shared_ptr<CesiumAsync::IAssetRequest> 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<void(Tile&)> 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 Create a result with Failed state + * + * @param pCompletedRequest The failed request + */ + static TileLoadResult createFailedResult( + std::shared_ptr<CesiumAsync::IAssetRequest> pCompletedRequest); + + /** + * @brief Create a result with RetryLater state + * + * @param pCompletedRequest The failed request + */ + static TileLoadResult createRetryLaterResult( + std::shared_ptr<CesiumAsync::IAssetRequest> pCompletedRequest); +}; + +} // namespace Cesium3DTilesSelection diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/Cesium3DTilesSelection/TileMapServiceRasterOverlay.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/Cesium3DTilesSelection/TileMapServiceRasterOverlay.h new file mode 100644 index 0000000000000000000000000000000000000000..0268dc1a519cda02130d4933afd8e9e74f207f3b --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/Cesium3DTilesSelection/TileMapServiceRasterOverlay.h @@ -0,0 +1,136 @@ +#pragma once + +#include "Library.h" +#include "RasterOverlay.h" + +#include <CesiumAsync/IAssetRequest.h> +#include <CesiumGeometry/QuadtreeTilingScheme.h> +#include <CesiumGeospatial/Ellipsoid.h> +#include <CesiumGeospatial/GlobeRectangle.h> +#include <CesiumGeospatial/Projection.h> + +#include <functional> +#include <memory> + +namespace Cesium3DTilesSelection { + +class CreditSystem; + +/** + * @brief Options for tile map service accesses. + */ +struct TileMapServiceRasterOverlayOptions { + + /** + * @brief The file extension for images on the server. + */ + std::optional<std::string> fileExtension; + + /** + * @brief A credit for the data source, which is displayed on the canvas. + */ + std::optional<std::string> 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<uint32_t> minimumLevel; + + /** + * @brief The maximum level-of-detail supported by the imagery provider. + * + * This will be `std::nullopt` if there is no limit. + */ + std::optional<uint32_t> maximumLevel; + + /** + * @brief The {@link CesiumGeometry::Rectangle}, in radians, covered by the + * image. + */ + std::optional<CesiumGeometry::Rectangle> coverageRectangle; + + /** + * @brief The {@link CesiumGeospatial::Projection} that is used. + */ + std::optional<CesiumGeospatial::Projection> projection; + + /** + * @brief The {@link CesiumGeometry::QuadtreeTilingScheme} specifying how + * the ellipsoidal surface is broken into tiles. + */ + std::optional<CesiumGeometry::QuadtreeTilingScheme> tilingScheme; + + /** + * @brief The {@link CesiumGeospatial::Ellipsoid}. + * + * If the `tilingScheme` is specified, this parameter is ignored and + * the tiling scheme's ellipsoid is used instead. If neither parameter + * is specified, the {@link CesiumGeospatial::Ellipsoid::WGS84} is used. + */ + std::optional<CesiumGeospatial::Ellipsoid> ellipsoid; + + /** + * @brief Pixel width of image tiles. + */ + std::optional<uint32_t> tileWidth; + + /** + * @brief Pixel height of image tiles. + */ + std::optional<uint32_t> 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<bool> flipXY; +}; + +/** + * @brief A {@link RasterOverlay} based on tile map service imagery. + */ +class CESIUM3DTILESSELECTION_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<CesiumAsync::IAssetAccessor::THeader>& headers = {}, + const TileMapServiceRasterOverlayOptions& tmsOptions = {}, + const RasterOverlayOptions& overlayOptions = {}); + virtual ~TileMapServiceRasterOverlay() override; + + virtual CesiumAsync::Future<CreateTileProviderResult> createTileProvider( + const CesiumAsync::AsyncSystem& asyncSystem, + const std::shared_ptr<CesiumAsync::IAssetAccessor>& pAssetAccessor, + const std::shared_ptr<CreditSystem>& pCreditSystem, + const std::shared_ptr<IPrepareRendererResources>& + pPrepareRendererResources, + const std::shared_ptr<spdlog::logger>& pLogger, + CesiumUtility::IntrusivePointer<const RasterOverlay> pOwner) + const override; + +private: + std::string _url; + std::vector<CesiumAsync::IAssetAccessor::THeader> _headers; + TileMapServiceRasterOverlayOptions _options; +}; + +} // 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 0000000000000000000000000000000000000000..18d6c8cc40ee306aac3596bdfedc5913bcf0d678 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/Cesium3DTilesSelection/TileOcclusionRendererProxy.h @@ -0,0 +1,146 @@ +#pragma once + +#include "Library.h" +#include "Tile.h" + +#include <cstdint> +#include <unordered_map> +#include <vector> + +/** + * @brief The occlusion state of a tile as reported by the renderer proxy. + */ +namespace Cesium3DTilesSelection { +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<const Tile*, TileOcclusionRendererProxy*> + _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 0000000000000000000000000000000000000000..8d30966897e409a117e0d5ef1e0ca50decea82a6 --- /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 0000000000000000000000000000000000000000..dc27976208b4e1b2654babc2442cc64fee128933 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/Cesium3DTilesSelection/TileSelectionState.h @@ -0,0 +1,168 @@ +#pragma once + +#include "Library.h" + +#include <cstdint> + +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 0000000000000000000000000000000000000000..b58c9f81a567b228f5fc630d71a377897ea40574 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/Cesium3DTilesSelection/Tileset.h @@ -0,0 +1,436 @@ +#pragma once + +#include "Library.h" +#include "RasterOverlayCollection.h" +#include "Tile.h" +#include "TilesetContentLoader.h" +#include "TilesetExternals.h" +#include "TilesetLoadFailureDetails.h" +#include "TilesetOptions.h" +#include "ViewState.h" +#include "ViewUpdateResult.h" + +#include <CesiumAsync/AsyncSystem.h> +#include <CesiumUtility/IntrusivePointer.h> + +#include <rapidjson/fwd.h> + +#include <memory> +#include <optional> +#include <string> +#include <vector> + +namespace Cesium3DTilesSelection { +class TilesetContentManager; + +/** + * @brief A <a + * href="https://github.com/CesiumGS/3d-tiles/tree/master/specification">3D + * Tiles tileset</a>, 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<TilesetContentLoader>&& pCustomLoader, + std::unique_ptr<Tile>&& 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 <a + * href="https://cesium.com/ion/">Cesium ion</a>. + * @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 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<void>& getAsyncDestructionCompleteEvent(); + + /** + * @brief Destroys this tileset. + * + * This may block the calling thread while waiting for pending asynchronous + * tile loads to terminate. Use {@link canBeDestroyedWithoutBlocking} to + * determine if it will block. + */ + ~Tileset() noexcept; + + /** + * @brief Get tileset credits. + */ + const std::vector<Credit>& getTilesetCredits() const 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 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 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<ViewState>& 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<ViewState>& frustums, float deltaTime = 0.0f); + + /** + * @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<void(Tile& tile)>& callback); + + /** + * @brief Gets the total number of bytes of tile and raster overlay data that + * are currently loaded. + */ + int64_t getTotalDataBytes() const noexcept; + +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<ViewState>& frustums; + std::vector<double> 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); + TraversalDetails _refineToNothing( + const FrameState& frameState, + Tile& tile, + ViewUpdateResult& result, + bool areChildrenRenderable); + bool _kickDescendantsAndRenderTile( + const FrameState& frameState, + Tile& tile, + ViewUpdateResult& result, + TraversalDetails& traversalDetails, + size_t firstRenderedDescendantIndex, + size_t loadIndexLow, + size_t loadIndexMedium, + size_t loadIndexHigh, + 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<double>& distances, + CullResult& cullResult); + bool _meetsSse( + const std::vector<ViewState>& frustums, + const Tile& tile, + const std::vector<double>& 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. + * @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); + + /** + * @brief Queues load of tiles that are _required_ to be loaded before the + * given tile can be refined in "Forbid Holes" mode. + * + * The queued tiles may include descedents, too, if any children are set to + * Unconditionally Refine ({@link Tile::getUnconditionallyRefine}). + * + * This method should only be called if {@link TilesetOptions::forbidHoles} is enabled. + * + * @param frameState The state of the current frame. + * @param tile The tile that is potentially being refined. + * @param implicitInfo The implicit traversal info. + * @param tilePriority The load priority of this tile. + * @return true Some of the required descendents are not yet loaded, so this + * tile _cannot_ yet be refined. + * @return false All of the required descendents (if there are any) are + * loaded, so this tile _can_ be refined. + */ + bool _queueLoadOfChildrenRequiredForForbidHoles( + const FrameState& frameState, + Tile& tile, + double tilePriority); + + void _processLoadQueue(); + 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; + + struct LoadRecord { + Tile* pTile; + + /** + * @brief The relative priority of loading this tile. + * + * Lower priority values load sooner. + */ + double priority; + + bool operator<(const LoadRecord& rhs) const noexcept { + return this->priority < rhs.priority; + } + }; + + std::vector<LoadRecord> _loadQueueHigh; + std::vector<LoadRecord> _loadQueueMedium; + std::vector<LoadRecord> _loadQueueLow; + Tile::LoadedLinkedList _loadedTiles; + + // Holds computed distances, to avoid allocating them on the heap during tile + // selection. + std::vector<double> _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<const TileOcclusionRendererProxy*> _childOcclusionProxies; + + CesiumUtility::IntrusivePointer<TilesetContentManager> + _pTilesetContentManager; + + void addTileToLoadQueue( + std::vector<LoadRecord>& loadQueue, + Tile& tile, + double tilePriority); + void processQueue( + std::vector<Tileset::LoadRecord>& queue, + int32_t maximumLoadsInProgress); + + 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 0000000000000000000000000000000000000000..5b767456b64374ab4553102d1dc5796d4426a2c4 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/Cesium3DTilesSelection/TilesetContentLoader.h @@ -0,0 +1,139 @@ +#pragma once + +#include "BoundingVolume.h" +#include "Library.h" +#include "RasterOverlayDetails.h" +#include "TileContent.h" +#include "TileLoadResult.h" +#include "TilesetOptions.h" + +#include <CesiumAsync/AsyncSystem.h> +#include <CesiumAsync/Future.h> +#include <CesiumAsync/IAssetAccessor.h> +#include <CesiumGeometry/Axis.h> +#include <CesiumGltf/Model.h> + +#include <spdlog/logger.h> + +#include <functional> +#include <memory> +#include <optional> +#include <vector> + +namespace Cesium3DTilesSelection { +class Tile; + +/** + * @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. + */ + TileLoadInput( + const Tile& tile, + const TilesetContentOptions& contentOptions, + const CesiumAsync::AsyncSystem& asyncSystem, + const std::shared_ptr<CesiumAsync::IAssetAccessor>& pAssetAccessor, + const std::shared_ptr<spdlog::logger>& pLogger, + const std::vector<CesiumAsync::IAssetAccessor::THeader>& requestHeaders); + + /** + * @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<CesiumAsync::IAssetAccessor>& pAssetAccessor; + + /** + * @brief The logger that receives details of loading errors and warnings. + */ + const std::shared_ptr<spdlog::logger>& pLogger; + + /** + * @brief The request headers that will be attached to the request. + */ + const std::vector<CesiumAsync::IAssetAccessor::THeader>& requestHeaders; +}; + +/** + * @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<Tile> 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<TileLoadResult> + 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. + * @return The {@link TileChildrenResult} that stores the tile's children + */ + virtual TileChildrenResult createTileChildren(const Tile& tile) = 0; +}; +} // 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 0000000000000000000000000000000000000000..95cb9cad4194618ed26962752af0931c2b9b4a44 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/Cesium3DTilesSelection/TilesetExternals.h @@ -0,0 +1,71 @@ +#pragma once + +#include "Library.h" +#include "TileOcclusionRendererProxy.h" +#include "spdlog-cesium.h" + +#include <CesiumAsync/AsyncSystem.h> + +#include <memory> + +namespace CesiumAsync { +class IAssetAccessor; +class ITaskProcessor; +} // namespace CesiumAsync + +namespace Cesium3DTilesSelection { +class CreditSystem; +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<CesiumAsync::IAssetAccessor> pAssetAccessor; + + /** + * @brief An external {@link IPrepareRendererResources}. + */ + std::shared_ptr<IPrepareRendererResources> 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 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<CreditSystem> pCreditSystem; + + /** + * @brief A spdlog logger that will receive log messages. + * + * If not specified, defaults to `spdlog::default_logger()`. + */ + std::shared_ptr<spdlog::logger> 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<TileOcclusionRendererProxyPool> pTileOcclusionProxyPool = + nullptr; +}; + +} // 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 0000000000000000000000000000000000000000..a1ac6dba02f116c3b3b18bea66ca1e867c429f03 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/Cesium3DTilesSelection/TilesetLoadFailureDetails.h @@ -0,0 +1,57 @@ +#pragma once + +#include <memory> +#include <string> + +namespace CesiumAsync { +class IAssetRequest; +} + +namespace Cesium3DTilesSelection { + +class Tileset; + +/** + * @brief The type of load that failed in {@link TilesetLoadFailureDetails}. + */ +enum class TilesetLoadType { + /** + * @brief An unknown load error. + */ + Unknown, + + /** + * @brief A Cesium ion asset endpoint. + */ + CesiumIon, + + /** + * @brief The root tileset.json. + */ + TilesetJson +}; + +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/TilesetOptions.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/Cesium3DTilesSelection/TilesetOptions.h new file mode 100644 index 0000000000000000000000000000000000000000..ebfd24c836abe2943f6c4fd799598d634f8075af --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/Cesium3DTilesSelection/TilesetOptions.h @@ -0,0 +1,315 @@ +#pragma once + +#include "Library.h" + +#include <CesiumGltf/Ktx2TranscodeTargets.h> + +#include <functional> +#include <memory> +#include <optional> +#include <string> +#include <vector> + +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 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<std::string> 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<FogDensityAtHeight> 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<std::shared_ptr<ITileExcluder>> 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<void(const TilesetLoadFailureDetails&)> loadErrorCallback; + + /** + * @brief Whether to keep tiles loaded during a transition period when + * switching to a different LOD tile. + * + * For each tile, TileContentLoadResult::lodTransitionFadePercentage 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 prepareInLoadThread}. + * + * This object is copied and given to tile preparation threads, + * so it must be inexpensive to copy. + */ + std::any rendererOptions; +}; + +} // 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 0000000000000000000000000000000000000000..0db7ed742798be5f533811bc44775b9aaef0077b --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/Cesium3DTilesSelection/ViewState.h @@ -0,0 +1,181 @@ +#pragma once + +#include "BoundingVolume.h" +#include "Library.h" + +#include <CesiumGeometry/CullingVolume.h> +#include <CesiumGeometry/Plane.h> +#include <CesiumGeospatial/Cartographic.h> + +#include <glm/mat3x3.hpp> +#include <glm/vec2.hpp> +#include <glm/vec3.hpp> + +#include <vector> + +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 = + CesiumGeospatial::Ellipsoid::WGS84); + + /** + * @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<CesiumGeospatial::Cartographic>& + 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<CesiumGeospatial::Cartographic>& + positionCartographic); + + const glm::dvec3 _position; + const glm::dvec3 _direction; + const glm::dvec3 _up; + const glm::dvec2 _viewportSize; + const double _horizontalFieldOfView; + const double _verticalFieldOfView; + + const double _sseDenominator; + const std::optional<CesiumGeospatial::Cartographic> _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 0000000000000000000000000000000000000000..6bf215252d078eeaecc01f7b9c8469a60f746096 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/Cesium3DTilesSelection/ViewUpdateResult.h @@ -0,0 +1,56 @@ +#pragma once + +#include "Library.h" + +#include <cstdint> +#include <unordered_set> +#include <vector> + +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<Tile*> 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<Tile*> tilesFadingOut; + + //! @cond Doxygen_Suppress + uint32_t tilesLoadingLowPriority = 0; + uint32_t tilesLoadingMediumPriority = 0; + uint32_t tilesLoadingHighPriority = 0; + + uint32_t tilesVisited = 0; + uint32_t culledTilesVisited = 0; + uint32_t tilesCulled = 0; + uint32_t tilesOccluded = 0; + uint32_t tilesWaitingForOcclusionResults = 0; + uint32_t maxDepthVisited = 0; + //! @endcond +}; + +} // namespace Cesium3DTilesSelection diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/Cesium3DTilesSelection/WebMapServiceRasterOverlay.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/Cesium3DTilesSelection/WebMapServiceRasterOverlay.h new file mode 100644 index 0000000000000000000000000000000000000000..2d5402da9865b21a43acfb1ba9b13f281301cd15 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/Cesium3DTilesSelection/WebMapServiceRasterOverlay.h @@ -0,0 +1,110 @@ +#pragma once + +#include "Library.h" +#include "RasterOverlay.h" + +#include <CesiumAsync/IAssetRequest.h> +#include <CesiumGeometry/QuadtreeTilingScheme.h> +#include <CesiumGeospatial/Ellipsoid.h> +#include <CesiumGeospatial/GlobeRectangle.h> +#include <CesiumGeospatial/Projection.h> + +#include <functional> +#include <memory> + +namespace Cesium3DTilesSelection { + +class CreditSystem; + +/** + * @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<std::string> 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 CESIUM3DTILESSELECTION_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<CesiumAsync::IAssetAccessor::THeader>& headers = {}, + const WebMapServiceRasterOverlayOptions& wmsOptions = {}, + const RasterOverlayOptions& overlayOptions = {}); + virtual ~WebMapServiceRasterOverlay() override; + + virtual CesiumAsync::Future<CreateTileProviderResult> createTileProvider( + const CesiumAsync::AsyncSystem& asyncSystem, + const std::shared_ptr<CesiumAsync::IAssetAccessor>& pAssetAccessor, + const std::shared_ptr<CreditSystem>& pCreditSystem, + const std::shared_ptr<IPrepareRendererResources>& + pPrepareRendererResources, + const std::shared_ptr<spdlog::logger>& pLogger, + CesiumUtility::IntrusivePointer<const RasterOverlay> pOwner) + const override; + +private: + std::string _baseUrl; + std::vector<CesiumAsync::IAssetAccessor::THeader> _headers; + WebMapServiceRasterOverlayOptions _options; +}; + +} // namespace Cesium3DTilesSelection diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/Cesium3DTilesSelection/registerAllTileContentTypes.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/Cesium3DTilesSelection/registerAllTileContentTypes.h new file mode 100644 index 0000000000000000000000000000000000000000..ac0ef9ee68c1fbca1e9b1c0f3ceb636b490fa595 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/Cesium3DTilesSelection/registerAllTileContentTypes.h @@ -0,0 +1,14 @@ +#include "Library.h" + +namespace Cesium3DTilesSelection { + +/** + * @brief Register all {@link Tile} content types that can be loaded. + * + * This is supposed to be called during the initialization, before + * any {@link Tileset} is loaded. It will register loaders for the + * different types of tiles that can be encountered. + */ +CESIUM3DTILESSELECTION_API void registerAllTileContentTypes(); + +} // 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 0000000000000000000000000000000000000000..1ca388b46fd19f513544187416e5abb0dbf89926 --- /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 <spdlog/spdlog.h> + +#ifndef _MSC_VER +#pragma GCC diagnostic pop +#endif diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/Cesium3DTilesSelection/tinyxml-cesium.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/Cesium3DTilesSelection/tinyxml-cesium.h new file mode 100644 index 0000000000000000000000000000000000000000..dafd469de5fcc532278e56993d15d6e6f00da38d --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/Cesium3DTilesSelection/tinyxml-cesium.h @@ -0,0 +1,12 @@ +#pragma once + +#ifndef _MSC_VER +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wsign-conversion" +#endif + +#include <tinyxml2.h> + +#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 0000000000000000000000000000000000000000..ea4f4c77d2f8add5ab7c9be990abc38170be4169 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/Cesium3DTilesWriter/Library.h @@ -0,0 +1,16 @@ +#pragma once + +/** + * @brief Classes for writing [3D Tiles](https://github.com/CesiumGS/3d-tiles). + */ +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 0000000000000000000000000000000000000000..279befd8facc384049f379976a7571ebff719302 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/Cesium3DTilesWriter/SchemaWriter.h @@ -0,0 +1,81 @@ +#pragma once + +#include "Cesium3DTilesWriter/Library.h" + +#include <CesiumJsonWriter/ExtensionWriterContext.h> + +// forward declarations +namespace Cesium3DTiles { +struct Schema; +} + +namespace Cesium3DTilesWriter { + +/** + * @brief The result of writing a schema with + * {@link SchemaWriterWriter::writeSchema}. + */ +struct CESIUM3DTILESWRITER_API SchemaWriterResult { + /** + * @brief The final generated std::vector<std::byte> of the schema JSON. + */ + std::vector<std::byte> schemaBytes; + + /** + * @brief Errors, if any, that occurred during the write process. + */ + std::vector<std::string> errors; + + /** + * @brief Warnings, if any, that occurred during the write process. + */ + std::vector<std::string> 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 0000000000000000000000000000000000000000..5bda0ff744a38b98cdc83e91c844100b6f1ef0ed --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/Cesium3DTilesWriter/SubtreeWriter.h @@ -0,0 +1,81 @@ +#pragma once + +#include "Cesium3DTilesWriter/Library.h" + +#include <CesiumJsonWriter/ExtensionWriterContext.h> + +// forward declarations +namespace Cesium3DTiles { +struct Subtree; +} + +namespace Cesium3DTilesWriter { + +/** + * @brief The result of writing a subtree with + * {@link SubtreeWriterWriter::writeSubtree}. + */ +struct CESIUM3DTILESWRITER_API SubtreeWriterResult { + /** + * @brief The final generated std::vector<std::byte> of the subtree JSON. + */ + std::vector<std::byte> subtreeBytes; + + /** + * @brief Errors, if any, that occurred during the write process. + */ + std::vector<std::string> errors; + + /** + * @brief Warnings, if any, that occurred during the write process. + */ + std::vector<std::string> 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 0000000000000000000000000000000000000000..2ce548e3a2a358c4c1863cc72fe5549036043fd7 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/Cesium3DTilesWriter/TilesetWriter.h @@ -0,0 +1,81 @@ +#pragma once + +#include "Cesium3DTilesWriter/Library.h" + +#include <CesiumJsonWriter/ExtensionWriterContext.h> + +// 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<std::byte> of the tileset. + */ + std::vector<std::byte> tilesetBytes; + + /** + * @brief Errors, if any, that occurred during the write process. + */ + std::vector<std::string> errors; + + /** + * @brief Warnings, if any, that occurred during the write process. + */ + std::vector<std::string> 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 0000000000000000000000000000000000000000..76f9d5696eed040b86c36c8933f1add2e304ad86 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumAsync/AsyncSystem.h @@ -0,0 +1,329 @@ +#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 <CesiumUtility/Tracing.h> + +#include <memory> + +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<ITaskProcessor>& 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 <typename T, typename Func> Future<T> createFuture(Func&& f) const { + std::shared_ptr<async::event_task<T>> pEvent = + std::make_shared<async::event_task<T>>(); + + Promise<T> promise(this->_pSchedulers, pEvent); + + try { + f(promise); + } catch (...) { + promise.reject(std::current_exception()); + } + + return Future<T>(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<T>::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 <typename T> Promise<T> createPromise() const { + return Promise<T>( + this->_pSchedulers, + std::make_shared<async::event_task<T>>()); + } + + /** + * @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 <typename Func> + CesiumImpl::ContinuationFutureType_t<Func, void> + runInWorkerThread(Func&& f) const { + static const char* tracingName = "waiting for worker thread"; + + CESIUM_TRACE_BEGIN_IN_TRACK(tracingName); + + return CesiumImpl::ContinuationFutureType_t<Func, void>( + this->_pSchedulers, + async::spawn( + this->_pSchedulers->workerThread.immediate, + CesiumImpl::WithTracing<void>::end( + tracingName, + std::forward<Func>(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 <typename Func> + CesiumImpl::ContinuationFutureType_t<Func, void> + runInMainThread(Func&& f) const { + static const char* tracingName = "waiting for main thread"; + + CESIUM_TRACE_BEGIN_IN_TRACK(tracingName); + + return CesiumImpl::ContinuationFutureType_t<Func, void>( + this->_pSchedulers, + async::spawn( + this->_pSchedulers->mainThread.immediate, + CesiumImpl::WithTracing<void>::end( + tracingName, + std::forward<Func>(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 <typename Func> + CesiumImpl::ContinuationFutureType_t<Func, void> + 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<Func, void>( + this->_pSchedulers, + async::spawn( + threadPool._pScheduler->immediate, + CesiumImpl::WithTracing<void>::end( + tracingName, + std::forward<Func>(f)))); + } + + /** + * @brief Creates a Future that resolves when every Future in a vector + * resolves, and rejects when any Future in the vector rejects. + * + * 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 <typename T> + Future<std::vector<T>> all(std::vector<Future<T>>&& futures) const { + return this->all<T, Future<T>>( + std::forward<std::vector<Future<T>>>(futures)); + } + + /** + * @brief Creates a Future that resolves when every Future in a vector + * resolves, and rejects when any Future in the vector rejects. + * + * 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 <typename T> + Future<std::vector<T>> all(std::vector<SharedFuture<T>>&& futures) const { + return this->all<T, SharedFuture<T>>( + std::forward<std::vector<SharedFuture<T>>>(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 <typename T> Future<T> createResolvedFuture(T&& value) const { + return Future<T>( + this->_pSchedulers, + async::make_task<T>(std::forward<T>(value))); + } + + /** + * @brief Creates a future that is already resolved and resolves to no value. + * + * @return The future. + */ + Future<void> createResolvedFuture() const { + return Future<void>(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 <typename T, typename TFutureType> + Future<std::vector<T>> all(std::vector<TFutureType>&& futures) const { + using TTaskType = decltype(TFutureType::_task); + std::vector<TTaskType> 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<std::vector<T>> task = + async::when_all(tasks.begin(), tasks.end()) + .then( + async::inline_scheduler(), + [](std::vector<TTaskType>&& tasks) { + // Get all the results. If any tasks rejected, we'll bail with + // an exception. + std::vector<T> results; + results.reserve(tasks.size()); + + for (auto it = tasks.begin(); it != tasks.end(); ++it) { + results.emplace_back(it->get()); + } + return results; + }); + return Future<std::vector<T>>(this->_pSchedulers, std::move(task)); + } + + std::shared_ptr<CesiumImpl::AsyncSystemSchedulers> _pSchedulers; + + template <typename T> 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 0000000000000000000000000000000000000000..20d1ca8037b082e80115b969d843ac9e87b1249a --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumAsync/CacheItem.h @@ -0,0 +1,119 @@ +#pragma once + +#include "HttpHeaders.h" +#include "Library.h" + +#include <gsl/span> + +#include <cstddef> +#include <ctime> +#include <map> +#include <vector> + +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<std::byte>&& 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<std::byte> 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 0000000000000000000000000000000000000000..24cd6ca28774a319bd2cb1e3f25feff29bca8c69 --- /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 <spdlog/fwd.h> + +#include <atomic> +#include <cstddef> +#include <memory> +#include <string> + +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<spdlog::logger>& pLogger, + const std::shared_ptr<IAssetAccessor>& pAssetAccessor, + const std::shared_ptr<ICacheDatabase>& pCacheDatabase, + int32_t requestsPerCachePrune = 10000); + + virtual ~CachingAssetAccessor() noexcept override; + + /** @copydoc IAssetAccessor::get */ + virtual Future<std::shared_ptr<IAssetRequest>> + get(const AsyncSystem& asyncSystem, + const std::string& url, + const std::vector<THeader>& headers) override; + + virtual Future<std::shared_ptr<IAssetRequest>> request( + const AsyncSystem& asyncSystem, + const std::string& verb, + const std::string& url, + const std::vector<THeader>& headers, + const gsl::span<const std::byte>& contentPayload) override; + + /** @copydoc IAssetAccessor::tick */ + virtual void tick() noexcept override; + +private: + int32_t _requestsPerCachePrune; + std::atomic<int32_t> _requestSinceLastPrune; + std::shared_ptr<spdlog::logger> _pLogger; + std::shared_ptr<IAssetAccessor> _pAssetAccessor; + std::shared_ptr<ICacheDatabase> _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 0000000000000000000000000000000000000000..7f234f3b832ed8733b80c118876cf3b7cfd83087 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumAsync/Future.h @@ -0,0 +1,302 @@ +#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 <CesiumUtility/Tracing.h> + +#include <variant> + +namespace CesiumAsync { + +namespace CesiumImpl { + +template <typename R> 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 <typename T> class Future final { +public: + /** + * @brief Move constructor + */ + Future(Future<T>&& rhs) noexcept + : _pSchedulers(std::move(rhs._pSchedulers)), + _task(std::move(rhs._task)) {} + + Future<T>& operator=(Future<T>&& rhs) noexcept { + this->_pSchedulers = std::move(rhs._pSchedulers); + this->_task = std::move(rhs._task); + return *this; + } + + Future(const Future<T>& rhs) = delete; + Future<T>& operator=(const Future<T>& 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 <typename Func> + CesiumImpl::ContinuationFutureType_t<Func, T> + thenInWorkerThread(Func&& f) && { + return std::move(*this).thenWithScheduler( + this->_pSchedulers->workerThread.immediate, + "waiting for worker thread", + std::forward<Func>(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 <typename Func> + CesiumImpl::ContinuationFutureType_t<Func, T> thenInMainThread(Func&& f) && { + return std::move(*this).thenWithScheduler( + this->_pSchedulers->mainThread.immediate, + "waiting for main thread", + std::forward<Func>(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 <typename Func> + CesiumImpl::ContinuationFutureType_t<Func, T> thenImmediately(Func&& f) && { + return CesiumImpl::ContinuationFutureType_t<Func, T>( + this->_pSchedulers, + _task.then( + async::inline_scheduler(), + CesiumImpl::WithTracing<T>::end(nullptr, std::forward<Func>(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 f The function. + * @return A future that resolves after the supplied function completes. + */ + template <typename Func> + CesiumImpl::ContinuationFutureType_t<Func, T> + thenInThreadPool(const ThreadPool& threadPool, Func&& f) && { + return std::move(*this).thenWithScheduler( + threadPool._pScheduler->immediate, + "waiting for thread pool thread", + std::forward<Func>(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 <typename Func> Future<T> catchInMainThread(Func&& f) && { + return std::move(*this).catchWithScheduler( + this->_pSchedulers->mainThread.immediate, + std::forward<Func>(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 <typename Func> Future<T> catchImmediately(Func&& f) && { + return std::move(*this).catchWithScheduler( + async::inline_scheduler(), + std::forward<Func>(f)); + } + + /** + * @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. + * + * @return The value if the future resolves successfully. + * @throws An exception if the future rejected. + */ + T wait() { return this->_task.get(); } + + /** + * @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<T> share() && { + return SharedFuture<T>(this->_pSchedulers, this->_task.share()); + } + +private: + Future( + const std::shared_ptr<CesiumImpl::AsyncSystemSchedulers>& pSchedulers, + async::task<T>&& task) noexcept + : _pSchedulers(pSchedulers), _task(std::move(task)) {} + + template <typename Func, typename Scheduler> + CesiumImpl::ContinuationFutureType_t<Func, 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<T>::begin(tracingName, std::forward<Func>(f))); +#else + auto& task = this->_task; +#endif + + return CesiumImpl::ContinuationFutureType_t<Func, T>( + this->_pSchedulers, + task.then( + scheduler, + CesiumImpl::WithTracing<T>::end( + tracingName, + std::forward<Func>(f)))); + } + + template <typename Func, typename Scheduler> + CesiumImpl::ContinuationFutureType_t<Func, std::exception> + catchWithScheduler(Scheduler& scheduler, Func&& f) && { + return CesiumImpl::ContinuationFutureType_t<Func, std::exception>( + this->_pSchedulers, + this->_task.then( + async::inline_scheduler(), + CesiumImpl::CatchFunction<Func, T, Scheduler>{ + scheduler, + std::forward<Func>(f)})); + } + + std::shared_ptr<CesiumImpl::AsyncSystemSchedulers> _pSchedulers; + async::task<T> _task; + + friend class AsyncSystem; + + template <typename R> friend struct CesiumImpl::ParameterizedTaskUnwrapper; + + friend struct CesiumImpl::TaskUnwrapper; + + template <typename R> friend class Future; + template <typename R> friend class SharedFuture; + template <typename R> friend class Promise; +}; + +} // 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 0000000000000000000000000000000000000000..bd287489223b63b36fad509408c4fa8ab9d45639 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumAsync/HttpHeaders.h @@ -0,0 +1,24 @@ +#pragma once + +#include <map> +#include <string> + +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 { + 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<std::string, std::string, CaseInsensitiveCompare>; +} // 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 0000000000000000000000000000000000000000..415e9e63c97ae5e54fa50616cebb00430d6d5649 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumAsync/IAssetAccessor.h @@ -0,0 +1,73 @@ +#pragma once + +#include "AsyncSystem.h" +#include "IAssetRequest.h" +#include "Library.h" + +#include <gsl/span> + +#include <cstddef> +#include <memory> +#include <string> +#include <vector> + +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<std::string, std::string> 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<std::shared_ptr<IAssetRequest>> + get(const AsyncSystem& asyncSystem, + const std::string& url, + const std::vector<THeader>& 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<std::shared_ptr<IAssetRequest>> request( + const AsyncSystem& asyncSystem, + const std::string& verb, + const std::string& url, + const std::vector<THeader>& headers = std::vector<THeader>(), + const gsl::span<const std::byte>& 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 0000000000000000000000000000000000000000..870aa1f43f670ca7795d8ef0b2f2c45fa1f2a564 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumAsync/IAssetRequest.h @@ -0,0 +1,45 @@ +#pragma once + +#include "HttpHeaders.h" +#include "Library.h" + +#include <functional> +#include <string> + +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 0000000000000000000000000000000000000000..10519057806beb521d144c174ffdb21144ae2c85 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumAsync/IAssetResponse.h @@ -0,0 +1,45 @@ +#pragma once + +#include "HttpHeaders.h" +#include "Library.h" + +#include <gsl/span> + +#include <cstddef> +#include <map> +#include <string> + +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 gsl::span<const std::byte> 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 0000000000000000000000000000000000000000..b4f83a428ebdde86243f98a2707fee9311efe35b --- /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 <cstddef> +#include <optional> + +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<CacheItem> 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 gsl::span<const std::byte>& 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 0000000000000000000000000000000000000000..916c3ab3cceae8e48e0577266bb403eacd8750c1 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumAsync/ITaskProcessor.h @@ -0,0 +1,29 @@ +#pragma once + +#include "Library.h" + +#include <functional> + +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<void()> 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 0000000000000000000000000000000000000000..bed6f49ad39e1e8410e81c74586093fa86c19230 --- /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 doxgen warnings for Impl namespace +//! @cond Doxygen_Suppress + +class AsyncSystemSchedulers { +public: + AsyncSystemSchedulers(const std::shared_ptr<ITaskProcessor>& pTaskProcessor) + : mainThread(), workerThread(pTaskProcessor) {} + + QueuedScheduler mainThread; + TaskScheduler workerThread; +}; + +//! @endcond +// End omitting doxgen 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 0000000000000000000000000000000000000000..6045909adb0f7b677a8980f85f1c1760530b8285 --- /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<T>&&> +struct CatchFunction { + Scheduler& scheduler; + Func f; + + async::task<T> 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) { + 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<decltype(ptrToException), std::exception_ptr>( + std::move(ptrToException))); + } + } +}; + +template <typename Func, typename Scheduler, typename TaskParameter> +struct CatchFunction<Func, void, Scheduler, TaskParameter> { + Scheduler& scheduler; + Func f; + + async::task<void> 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) { + 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<decltype(ptrToException), std::exception_ptr>( + 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 0000000000000000000000000000000000000000..b9215cb5346ee925fe2632b271b3f081d5fe3dd7 --- /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 <typename T> class Future; + +namespace CesiumImpl { +// Begin omitting doxgen warnings for Impl namespace +//! @cond Doxygen_Suppress + +template <typename Func, typename T> struct ContinuationFutureType { + using type = Future<typename RemoveFuture< + typename ContinuationReturnType<Func, T>::type>::type>; +}; + +template <typename Func, typename T> +using ContinuationFutureType_t = typename ContinuationFutureType<Func, T>::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 0000000000000000000000000000000000000000..9bc938884eddb9ce39e4f6ff4c46a59db69f51b9 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumAsync/Impl/ContinuationReturnType.h @@ -0,0 +1,21 @@ +#pragma once + +#include <type_traits> + +namespace CesiumAsync { +namespace CesiumImpl { +// Begin omitting doxgen warnings for Impl namespace +//! @cond Doxygen_Suppress + +template <typename Func, typename T> struct ContinuationReturnType { + using type = typename std::invoke_result<Func, T>::type; +}; + +template <typename Func> struct ContinuationReturnType<Func, void> { + using type = typename std::invoke_result<Func>::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 0000000000000000000000000000000000000000..0bdaa91e33f4356db90fa4627cdb3c992a985c73 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumAsync/Impl/ImmediateScheduler.h @@ -0,0 +1,91 @@ +#pragma once + +#include "cesium-async++.h" + +#include <spdlog/spdlog.h> + +namespace CesiumAsync { +namespace CesiumImpl { + +template <typename TScheduler> 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<TScheduler*>& inSuitable = + ImmediateScheduler<TScheduler>::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<TScheduler*>& inSuitable = + ImmediateScheduler<TScheduler>::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<TScheduler*>& inSuitable = + ImmediateScheduler<TScheduler>::getSchedulersCurrentlyDispatching(); + assert(!inSuitable.empty()); + 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<TScheduler*>& + 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<TScheduler*> schedulersCurrentlyDispatching; + return schedulersCurrentlyDispatching; + } +}; + +} // 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 0000000000000000000000000000000000000000..6db6d4fdbc73e51cc4a55e118ab047abd11aa374 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumAsync/Impl/QueuedScheduler.h @@ -0,0 +1,22 @@ +#pragma once + +#include "ImmediateScheduler.h" +#include "cesium-async++.h" + +namespace CesiumAsync { +namespace CesiumImpl { + +class QueuedScheduler { +public: + void schedule(async::task_run_handle t); + void dispatchQueuedContinuations(); + bool dispatchZeroOrOneContinuation(); + + ImmediateScheduler<QueuedScheduler> immediate{this}; + +private: + async::fifo_scheduler _scheduler; +}; + +} // 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 0000000000000000000000000000000000000000..0602ac619e05d84c238da3c997789a1191983081 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumAsync/Impl/RemoveFuture.h @@ -0,0 +1,35 @@ +#pragma once + +#include "cesium-async++.h" + +namespace CesiumAsync { + +template <class T> class Future; +template <class T> class SharedFuture; + +namespace CesiumImpl { +// Begin omitting doxgen warnings for Impl namespace +//! @cond Doxygen_Suppress + +template <typename T> struct RemoveFuture { typedef T type; }; +template <typename T> struct RemoveFuture<Future<T>> { typedef T type; }; +template <typename T> struct RemoveFuture<const Future<T>> { typedef T type; }; +template <typename T> struct RemoveFuture<SharedFuture<T>> { typedef T type; }; +template <typename T> struct RemoveFuture<const SharedFuture<T>> { + typedef T type; +}; +template <typename T> struct RemoveFuture<async::task<T>> { typedef T type; }; +template <typename T> struct RemoveFuture<const async::task<T>> { + typedef T type; +}; +template <typename T> struct RemoveFuture<async::shared_task<T>> { + typedef T type; +}; +template <typename T> struct RemoveFuture<const async::shared_task<T>> { + 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 0000000000000000000000000000000000000000..2da1366fd92d5569a6526333653fbe79a443a6d9 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumAsync/Impl/TaskScheduler.h @@ -0,0 +1,23 @@ +#pragma once + +#include "../ITaskProcessor.h" +#include "ImmediateScheduler.h" + +#include <memory> + +namespace CesiumAsync { +namespace CesiumImpl { + +class TaskScheduler { +public: + TaskScheduler(const std::shared_ptr<ITaskProcessor>& pTaskProcessor); + void schedule(async::task_run_handle t); + + ImmediateScheduler<TaskScheduler> immediate{this}; + +private: + std::shared_ptr<ITaskProcessor> _pTaskProcessor; +}; + +} // 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 0000000000000000000000000000000000000000..3ad503653456a65778b0600811d9707a3a992a2d --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumAsync/Impl/WithTracing.h @@ -0,0 +1,124 @@ +#pragma once + +#include "unwrapFuture.h" + +#include <CesiumUtility/Tracing.h> + +namespace CesiumAsync { +namespace CesiumImpl { +// Begin omitting doxgen warnings for Impl namespace +//! @cond Doxygen_Suppress + +template <typename T> struct WithTracing { + template <typename Func> + 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<Func, T>(std::forward<Func>(f)); +#endif + } + + template <typename Func> + static auto end([[maybe_unused]] const char* tracingName, Func&& f) { +#if CESIUM_TRACING_ENABLED + return [tracingName, + f = CesiumImpl::unwrapFuture<Func, T>(std::forward<Func>(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<Func, T>(std::forward<Func>(f)); +#endif + } +}; + +template <typename T> struct WithTracingShared { + template <typename Func> + 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<Func, T>(std::forward<Func>(f)); +#endif + } + + template <typename Func> + static auto end([[maybe_unused]] const char* tracingName, Func&& f) { +#if CESIUM_TRACING_ENABLED + return [tracingName, + f = CesiumImpl::unwrapSharedFuture<Func, T>(std::forward<Func>(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<Func, T>(std::forward<Func>(f)); +#endif + } +}; + +template <> struct WithTracing<void> { + template <typename Func> + 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<Func>(std::forward<Func>(f)); +#endif + } + + template <typename Func> + static auto end([[maybe_unused]] const char* tracingName, Func&& f) { +#if CESIUM_TRACING_ENABLED + return [tracingName, + f = CesiumImpl::unwrapFuture<Func>(std::forward<Func>(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<Func>(std::forward<Func>(f)); +#endif + } +}; + +// With a void Future, shared and non-shared are identical. +template <> struct WithTracingShared<void> : public WithTracing<void> {}; + +//! @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 0000000000000000000000000000000000000000..72227957b644361816441026c95e54c88b4778c3 --- /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) +#endif + +#ifndef _MSC_VER +#pragma GCC diagnostic ignored "-Wshadow" +#endif + +#include <async++.h> + +#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 0000000000000000000000000000000000000000..b9ac5cdd315fc54eb4bd66e74f59af3df9e677dc --- /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 <typename Func> static Func unwrap(Func&& f) { + return std::forward<Func>(f); + } + + template <typename Func> static Func unwrapShared(Func&& f) { + return std::forward<Func>(f); + } +}; + +template <typename T> struct ParameterizedTaskUnwrapper { + template <typename Func> static auto unwrap(Func&& f) { + return [f = std::forward<Func>(f)](T&& t) mutable { + return f(std::move(t))._task; + }; + } + + template <typename Func> static auto unwrapShared(Func&& f) { + return + [f = std::forward<Func>(f)](const T& t) mutable { return f(t)._task; }; + } +}; + +struct TaskUnwrapper { + template <typename Func> static auto unwrap(Func&& f) { + return [f = std::forward<Func>(f)]() mutable { return f()._task; }; + } +}; + +template <typename Func, typename T> auto unwrapFuture(Func&& f) { + return std::conditional< + std::is_same< + typename ContinuationReturnType<Func, T>::type, + typename RemoveFuture< + typename ContinuationFutureType<Func, T>::type>::type>::value, + IdentityUnwrapper, + ParameterizedTaskUnwrapper<T>>::type::unwrap(std::forward<Func>(f)); +} + +template <typename Func, typename T> auto unwrapSharedFuture(Func&& f) { + return std::conditional< + std::is_same< + typename ContinuationReturnType<Func, T>::type, + typename RemoveFuture< + typename ContinuationFutureType<Func, T>::type>::type>::value, + IdentityUnwrapper, + ParameterizedTaskUnwrapper<T>>::type::unwrapShared(std::forward<Func>(f)); +} + +template <typename Func> auto unwrapFuture(Func&& f) { + return std::conditional< + std::is_same< + typename ContinuationReturnType<Func, void>::type, + typename RemoveFuture< + typename ContinuationFutureType<Func, void>::type>::type>::value, + IdentityUnwrapper, + TaskUnwrapper>::type::unwrap(std::forward<Func>(f)); +} + +template <typename Func> auto unwrapSharedFuture(Func&& f) { + return unwrapFuture(std::forward<Func>(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 0000000000000000000000000000000000000000..cd308e10bd1c026b23758ee0e3e1f23672057f48 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumAsync/Library.h @@ -0,0 +1,16 @@ +#pragma once + +/** + * @brief Classes that support asynchronous operations. + */ +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/Promise.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumAsync/Promise.h new file mode 100644 index 0000000000000000000000000000000000000000..ae3618f03ff9c05f90bc9398cc232992d6a63648 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumAsync/Promise.h @@ -0,0 +1,103 @@ +#pragma once + +#include "Impl/AsyncSystemSchedulers.h" +#include "Impl/cesium-async++.h" + +#include <exception> +#include <memory> + +namespace CesiumAsync { + +template <typename T> 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 <typename T> 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 <typename TException> 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<T> getFuture() const { + return Future<T>(this->_pSchedulers, this->_pEvent->get_task()); + } + +private: + Promise( + const std::shared_ptr<CesiumImpl::AsyncSystemSchedulers>& pSchedulers, + const std::shared_ptr<async::event_task<T>>& pEvent) noexcept + : _pSchedulers(pSchedulers), _pEvent(pEvent) {} + + std::shared_ptr<CesiumImpl::AsyncSystemSchedulers> _pSchedulers; + std::shared_ptr<async::event_task<T>> _pEvent; + + friend class AsyncSystem; +}; + +// Specialization for promises that resolve to no value. +template <> class Promise<void> { +public: + void resolve() const { this->_pEvent->set(); } + template <typename TException> void reject(TException error) const { + this->_pEvent->set_exception(std::make_exception_ptr(error)); + } + void reject(const std::exception_ptr& error) const { + this->_pEvent->set_exception(error); + } + Future<void> getFuture() const { + return Future<void>(this->_pSchedulers, this->_pEvent->get_task()); + } + +private: + Promise( + const std::shared_ptr<CesiumImpl::AsyncSystemSchedulers>& pSchedulers, + const std::shared_ptr<async::event_task<void>>& pEvent) noexcept + : _pSchedulers(pSchedulers), _pEvent(pEvent) {} + + std::shared_ptr<CesiumImpl::AsyncSystemSchedulers> _pSchedulers; + std::shared_ptr<async::event_task<void>> _pEvent; + + friend class AsyncSystem; +}; + +} // 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 0000000000000000000000000000000000000000..53160442477a115a2429dea3de8c35dd5c972393 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumAsync/SharedFuture.h @@ -0,0 +1,289 @@ +#pragma once + +#include "Impl/AsyncSystemSchedulers.h" +#include "Impl/CatchFunction.h" +#include "Impl/ContinuationFutureType.h" +#include "Impl/WithTracing.h" +#include "ThreadPool.h" + +#include <CesiumUtility/Tracing.h> + +#include <type_traits> +#include <variant> + +namespace CesiumAsync { + +namespace CesiumImpl { + +template <typename R> 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 <typename T> 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 <typename Func> + CesiumImpl::ContinuationFutureType_t<Func, T> thenInWorkerThread(Func&& f) { + return this->thenWithScheduler( + this->_pSchedulers->workerThread.immediate, + "waiting for worker thread", + std::forward<Func>(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 <typename Func> + CesiumImpl::ContinuationFutureType_t<Func, T> thenInMainThread(Func&& f) { + return this->thenWithScheduler( + this->_pSchedulers->mainThread.immediate, + "waiting for main thread", + std::forward<Func>(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 <typename Func> + CesiumImpl::ContinuationFutureType_t<Func, T> thenImmediately(Func&& f) { + return CesiumImpl::ContinuationFutureType_t<Func, T>( + this->_pSchedulers, + _task.then( + async::inline_scheduler(), + CesiumImpl::WithTracingShared<T>::end( + nullptr, + std::forward<Func>(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 f The function. + * @return A future that resolves after the supplied function completes. + */ + template <typename Func> + CesiumImpl::ContinuationFutureType_t<Func, T> + thenInThreadPool(const ThreadPool& threadPool, Func&& f) { + return this->thenWithScheduler( + threadPool._pScheduler->immediate, + "waiting for thread pool thread", + std::forward<Func>(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 <typename Func> Future<T> catchInMainThread(Func&& f) { + return this->catchWithScheduler( + this->_pSchedulers->mainThread.immediate, + std::forward<Func>(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 <typename Func> Future<T> catchImmediately(Func&& f) { + return this->catchWithScheduler( + async::inline_scheduler(), + std::forward<Func>(f)); + } + + /** + * @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. + * + * @return The value if the future resolves successfully. + * @throws An exception if the future rejected. + */ + template < + typename U = T, + std::enable_if_t<std::is_same_v<U, T>, int> = 0, + std::enable_if_t<!std::is_same_v<U, void>, int> = 0> + const U& wait() const { + return this->_task.get(); + } + + template < + typename U = T, + std::enable_if_t<std::is_same_v<U, T>, int> = 0, + std::enable_if_t<std::is_same_v<U, void>, int> = 0> + void wait() const { + this->_task.get(); + } + + /** + * @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<CesiumImpl::AsyncSystemSchedulers>& pSchedulers, + async::shared_task<T>&& task) noexcept + : _pSchedulers(pSchedulers), _task(std::move(task)) {} + + template <typename Func, typename Scheduler> + CesiumImpl::ContinuationFutureType_t<Func, 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<T>::begin( + tracingName, + std::forward<Func>(f))); +#else + auto& task = this->_task; +#endif + + return CesiumImpl::ContinuationFutureType_t<Func, T>( + this->_pSchedulers, + task.then( + scheduler, + CesiumImpl::WithTracingShared<T>::end( + tracingName, + std::forward<Func>(f)))); + } + + template <typename Func, typename Scheduler> + CesiumImpl::ContinuationFutureType_t<Func, std::exception> + catchWithScheduler(Scheduler& scheduler, Func&& f) { + return CesiumImpl::ContinuationFutureType_t<Func, std::exception>( + this->_pSchedulers, + this->_task.then( + async::inline_scheduler(), + CesiumImpl:: + CatchFunction<Func, T, Scheduler, const async::shared_task<T>&>{ + scheduler, + std::forward<Func>(f)})); + } + + std::shared_ptr<CesiumImpl::AsyncSystemSchedulers> _pSchedulers; + async::shared_task<T> _task; + + friend class AsyncSystem; + + template <typename R> friend struct CesiumImpl::ParameterizedTaskUnwrapper; + + friend struct CesiumImpl::TaskUnwrapper; + + template <typename R> friend class Future; + template <typename R> 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 0000000000000000000000000000000000000000..2d6f4ad6f512de8536759e6653683c3da5b4bfd0 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumAsync/SqliteCache.h @@ -0,0 +1,64 @@ +#pragma once + +#include "ICacheDatabase.h" + +#include <spdlog/fwd.h> + +#include <cstddef> +#include <memory> +#include <optional> +#include <string> + +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<spdlog::logger>& pLogger, + const std::string& databaseName, + uint64_t maxItems = 4096); + ~SqliteCache(); + + /** @copydoc ICacheDatabase::getEntry*/ + virtual std::optional<CacheItem> + 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 gsl::span<const std::byte>& responseData) override; + + /** @copydoc ICacheDatabase::prune*/ + virtual bool prune() override; + + /** @copydoc ICacheDatabase::clearAll*/ + virtual bool clearAll() override; + +private: + struct Impl; + std::unique_ptr<Impl> _pImpl; + void createConnection() const; + void destroyDatabase(); +}; +} // 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 0000000000000000000000000000000000000000..fe8969d433c278a7b82a93a45b6650effa13ddc8 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumAsync/ThreadPool.h @@ -0,0 +1,51 @@ +#pragma once + +#include "Impl/ImmediateScheduler.h" +#include "Impl/cesium-async++.h" +#include "Library.h" + +#include <memory> + +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: + ThreadPool(int32_t numberOfThreads); + +private: + struct Scheduler { + Scheduler(int32_t numberOfThreads); + void schedule(async::task_run_handle t); + + CesiumImpl::ImmediateScheduler<Scheduler> 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<Scheduler>::SchedulerScope + _scope; + + std::shared_ptr<Scheduler> _pScheduler; + + template <typename T> friend class Future; + template <typename T> friend class SharedFuture; + friend class AsyncSystem; +}; + +} // namespace CesiumAsync 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 0000000000000000000000000000000000000000..6c50591f99da15f876e886cf559141f9a60e1a2f --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGeometry/Availability.h @@ -0,0 +1,120 @@ +#pragma once + +#include "Library.h" + +#include <gsl/span> + +#include <cstdint> +#include <memory> +#include <optional> +#include <utility> +#include <variant> +#include <vector> + +namespace CesiumGeometry { + +namespace AvailabilityUtilities { +uint8_t countOnesInByte(uint8_t _byte); +uint32_t countOnesInBuffer(gsl::span<const std::byte> buffer); +} // namespace AvailabilityUtilities + +struct CESIUMGEOMETRY_API ConstantAvailability { + bool constant; +}; + +struct CESIUMGEOMETRY_API SubtreeBufferView { + uint32_t byteOffset; + uint32_t byteLength; + uint8_t buffer; +}; + +typedef std::variant<ConstantAvailability, SubtreeBufferView> AvailabilityView; + +struct CESIUMGEOMETRY_API AvailabilitySubtree { + AvailabilityView tileAvailability; + AvailabilityView contentAvailability; + AvailabilityView subtreeAvailability; + std::vector<std::vector<std::byte>> buffers; +}; + +/** + * @brief Availability nodes wrap subtree 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<AvailabilitySubtree> subtree; + + /** + * @brief The child nodes for this subtree node. + */ + std::vector<std::unique_ptr<AvailabilityNode>> 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; +}; + +struct CESIUMGEOMETRY_API AvailabilityTree { + std::unique_ptr<AvailabilityNode> pRoot; +}; + +class CESIUMGEOMETRY_API AvailabilityAccessor { +public: + AvailabilityAccessor( + const AvailabilityView& view, + const AvailabilitySubtree& subtree) noexcept; + + bool isBufferView() const noexcept { + return pBufferView != nullptr && bufferAccessor; + } + + bool isConstant() const noexcept { return pConstant != nullptr; } + + /** + * @brief Unsafe if isConstant is false. + */ + bool getConstant() const { return pConstant->constant; } + + /** + * @brief Unsafe is isBufferView is false. + */ + const gsl::span<const std::byte>& getBufferAccessor() const { + return *bufferAccessor; + } + + /** + * @brief Unsafe if isBufferView is false. + */ + const std::byte& operator[](size_t i) const { + return bufferAccessor.value()[i]; + } + + /** + * @brief Unsafe if isBufferView is false; + */ + size_t size() const { return pBufferView->byteLength; } + +private: + const SubtreeBufferView* pBufferView; + const ConstantAvailability* pConstant; + std::optional<gsl::span<const std::byte>> 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 0000000000000000000000000000000000000000..dd7cdd3c3e9f99074aaf4c5d8a6c37849ea37f05 --- /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 0000000000000000000000000000000000000000..ad09f6febdb7f9d53246bf7d384454463367ff58 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGeometry/AxisAlignedBox.h @@ -0,0 +1,101 @@ +#pragma once + +#include "Library.h" + +#include <glm/vec3.hpp> + +namespace CesiumGeometry { + +struct CESIUMGEOMETRY_API AxisAlignedBox final { + + 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) {} + + 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; + + 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/AxisTransforms.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGeometry/AxisTransforms.h new file mode 100644 index 0000000000000000000000000000000000000000..c4908d726632dcee634aa74489e6a55da17da2c8 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGeometry/AxisTransforms.h @@ -0,0 +1,51 @@ +#pragma once + +#include "Library.h" + +#include <glm/mat3x3.hpp> + +namespace CesiumGeometry { + +/** + * @brief Coordinate system conversion matrices + */ +struct CESIUMGEOMETRY_API AxisTransforms 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; +}; + +} // 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 0000000000000000000000000000000000000000..f65e49f35067718afff62ed4f89ee29ce7a6c2e4 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGeometry/BoundingSphere.h @@ -0,0 +1,69 @@ +#pragma once + +#include "CullingResult.h" +#include "Library.h" + +#include <glm/vec3.hpp> + +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; + +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 0000000000000000000000000000000000000000..4def30310dbf3464ad1da22bfb5b3124496e1308 --- /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 0000000000000000000000000000000000000000..7bf5717ca9542925acbe480bc84c129dca4b9342 --- /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 0000000000000000000000000000000000000000..204c61ecf4977e01e18e9cb6a35ccdff70492d61 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGeometry/IntersectionTests.h @@ -0,0 +1,31 @@ +#pragma once + +#include "Library.h" + +#include <glm/vec3.hpp> + +#include <optional> + +namespace CesiumGeometry { +class Ray; +class Plane; + +/** + * @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<glm::dvec3> + rayPlane(const Ray& ray, const Plane& plane) noexcept; +}; + +} // 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 0000000000000000000000000000000000000000..50a7029ccc3423fae637e8bc658a42daba03d9a9 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGeometry/Library.h @@ -0,0 +1,16 @@ +#pragma once + +/** + * @brief Basic geometry classes for Cesium + */ +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 0000000000000000000000000000000000000000..2fd8e9943753ad9bbc1e664e1a5f0d328242b759 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGeometry/OctreeAvailability.h @@ -0,0 +1,164 @@ +#pragma once + +#include "Availability.h" +#include "Library.h" +#include "OctreeTileID.h" +#include "TileAvailabilityFlags.h" + +#include <gsl/span> + +#include <cstddef> +#include <memory> +#include <vector> + +namespace CesiumGeometry { + +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<uint32_t> 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. + */ + 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<AvailabilityNode> _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 0000000000000000000000000000000000000000..7fa15a3945bc4ecc82d944ea14b4d45c24840140 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGeometry/OctreeTileID.h @@ -0,0 +1,76 @@ +#pragma once + +#include "Library.h" + +#include <cstdint> + +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 0000000000000000000000000000000000000000..047498a2875c8f5e60a650cb8a760f7cf034ff18 --- /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 <glm/vec3.hpp> + +#include <optional> + +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<CesiumGeometry::OctreeTileID> + 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 0000000000000000000000000000000000000000..e8208849213f8d2d6b985aa81a01e873a8c5c813 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGeometry/OrientedBoundingBox.h @@ -0,0 +1,115 @@ +#pragma once + +#include "CullingResult.h" +#include "Library.h" + +#include <glm/mat3x3.hpp> +#include <glm/vec3.hpp> + +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 0x0x0 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 transformation matrix, to rotate and scale the box to the + * right position and size. + */ + 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 bounding + * box. + * + * @param position The position. + * @return Whether the position is contained within the bounding box. + */ + bool contains(const glm::dvec3& position) const 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 0000000000000000000000000000000000000000..0fef46c6e625dae8676b00bd4458ebee737cd396 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGeometry/Plane.h @@ -0,0 +1,111 @@ +#pragma once + +#include "Library.h" + +#include <glm/vec3.hpp> + +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 0000000000000000000000000000000000000000..77341fa9b789fbdc35c7f74b33cd73aaf7a46898 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGeometry/QuadtreeAvailability.h @@ -0,0 +1,165 @@ +#pragma once + +#include "Availability.h" +#include "Library.h" +#include "QuadtreeTileID.h" +#include "TileAvailabilityFlags.h" + +#include <gsl/span> + +#include <cstddef> +#include <memory> +#include <vector> + +namespace CesiumGeometry { + +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<uint32_t> 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<AvailabilityNode> _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 0000000000000000000000000000000000000000..7713b56ab2346fce20dc22e8553efc7c9536d138 --- /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 <glm/vec2.hpp> + +#include <memory> +#include <vector> + +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<QuadtreeNode> ll; + std::unique_ptr<QuadtreeNode> lr; + std::unique_ptr<QuadtreeNode> ul; + std::unique_ptr<QuadtreeNode> ur; + + std::vector<RectangleWithLevel> rectangles; + }; + + QuadtreeTilingScheme _tilingScheme; + uint32_t _maximumLevel; + std::vector<std::unique_ptr<QuadtreeNode>> _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 0000000000000000000000000000000000000000..71cf1fa42cad2406d577bfa12ad9d0d1a92e58dd --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGeometry/QuadtreeTileID.h @@ -0,0 +1,120 @@ +#pragma once + +#include "Library.h" + +#include <cstdint> +#include <functional> + +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<CesiumGeometry::QuadtreeTileID> { + + /** + * @brief A specialization of the `std::hash` template for + * {@link CesiumGeometry::QuadtreeTileID} objects. + */ + size_t operator()(const CesiumGeometry::QuadtreeTileID& key) const noexcept { + // TODO: is this hash function any good? Probably not. + std::hash<uint32_t> h; + return h(key.level) ^ (h(key.x) << 1) ^ (h(key.y) << 2); + } +}; +} // 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 0000000000000000000000000000000000000000..5330a711698792b3aaca74978a5eda6cd8db224f --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGeometry/QuadtreeTileRectangularRange.h @@ -0,0 +1,39 @@ +#pragma once + +#include <cstdint> + +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 0000000000000000000000000000000000000000..545177ea03af1ebacf451173eaed387e3d62036d --- /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 <glm/vec2.hpp> + +#include <optional> + +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<CesiumGeometry::QuadtreeTileID> + 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 0000000000000000000000000000000000000000..06b1c336fd1554bfc0b84126a5a98e3801818562 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGeometry/Ray.h @@ -0,0 +1,44 @@ +#pragma once + +#include "Library.h" + +#include <glm/vec3.hpp> + +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 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 0000000000000000000000000000000000000000..22bb405439f14ac8b7556783c3b70373fb89232e --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGeometry/Rectangle.h @@ -0,0 +1,207 @@ +#pragma once + +#include "Library.h" + +#include <glm/vec2.hpp> + +#include <optional> + +namespace CesiumGeometry { + +/** + * @brief A 2D rectangle + */ +struct CESIUMGEOMETRY_API Rectangle final { + /** + * @brief Creates a new instance with all coordinate values set to 0.0. + * + * @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() 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<Rectangle> + 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 0000000000000000000000000000000000000000..291753350a95657e200ce2694ecf2e6917777494 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGeometry/TileAvailabilityFlags.h @@ -0,0 +1,40 @@ +#pragma once + +#include "Library.h" + +#include <cstdint> + +namespace CesiumGeometry { + +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/clipTriangleAtAxisAlignedThreshold.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGeometry/clipTriangleAtAxisAlignedThreshold.h new file mode 100644 index 0000000000000000000000000000000000000000..8c4d4b598fff22fa6537f9571952b59202b41c34 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGeometry/clipTriangleAtAxisAlignedThreshold.h @@ -0,0 +1,96 @@ +#pragma once + +#include <glm/glm.hpp> + +#include <variant> +#include <vector> + +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; + + 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<double>::epsilon(); + } + + 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<int, InterpolatedVertex>; + +/** + * @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<TriangleClipVertex>& 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 0000000000000000000000000000000000000000..e6a09df251ae931d34bce34b830f72247c30ece5 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGeospatial/BoundingRegion.h @@ -0,0 +1,151 @@ +#pragma once + +#include "Ellipsoid.h" +#include "GlobeRectangle.h" +#include "Library.h" + +#include <CesiumGeometry/CullingResult.h> +#include <CesiumGeometry/OrientedBoundingBox.h> + +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 = Ellipsoid::WGS84); + + /** + * @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 = Ellipsoid::WGS84) 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 = Ellipsoid::WGS84) 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. + * @return The union. + */ + BoundingRegion computeUnion(const BoundingRegion& other) 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 0000000000000000000000000000000000000000..bc784347457402c97f5a0e196c435b1dd5070a88 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGeospatial/BoundingRegionBuilder.h @@ -0,0 +1,87 @@ +#pragma once + +#include "BoundingRegion.h" +#include "Library.h" + +namespace CesiumGeospatial { + +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; + + /** + * @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 0000000000000000000000000000000000000000..56fc6838d628b6fc3ce3b08376e2e7a62edc2849 --- /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 = Ellipsoid::WGS84) 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 = Ellipsoid::WGS84) 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 0000000000000000000000000000000000000000..a7dbae30cd5f0049984ba6e3bde15430529f4e8e --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGeospatial/Cartographic.h @@ -0,0 +1,64 @@ +#pragma once + +#include "Library.h" + +#include <CesiumUtility/Math.h> + +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 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 0000000000000000000000000000000000000000..4a624c7251c3a76ae6700fef65a6096c463ebed8 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGeospatial/CartographicPolygon.h @@ -0,0 +1,73 @@ +#pragma once + +#include "GlobeRectangle.h" +#include "Library.h" + +#include <glm/vec2.hpp> + +#include <optional> +#include <string> +#include <vector> + +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 Tileset} + * objects. + * + * @param polygon An array of longitude-latitude points in radians defining + * the perimeter of the 2D polygon. + */ + CartographicPolygon(const std::vector<glm::dvec2>& 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<glm::dvec2>& 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<uint32_t>& 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<CesiumGeospatial::GlobeRectangle>& + getBoundingRectangle() const { + return this->_boundingRectangle; + } + +private: + std::vector<glm::dvec2> _vertices; + std::vector<uint32_t> _indices; + std::optional<CesiumGeospatial::GlobeRectangle> _boundingRectangle; +}; + +} // 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 0000000000000000000000000000000000000000..2c4764f358789262ffc733cc5b83d6e8d47b28a9 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGeospatial/Ellipsoid.h @@ -0,0 +1,161 @@ +#pragma once + +#include "Cartographic.h" +#include "Library.h" + +#include <CesiumUtility/Math.h> + +#include <glm/vec3.hpp> + +#include <optional> + +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 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<Cartographic> + 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<glm::dvec3> + scaleToGeodeticSurface(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 0000000000000000000000000000000000000000..cca54c04536b251397dcc007d9411f5f2e689277 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGeospatial/EllipsoidTangentPlane.h @@ -0,0 +1,112 @@ +#pragma once + +#include "Ellipsoid.h" +#include "Library.h" + +#include <CesiumGeometry/Plane.h> + +#include <glm/mat4x4.hpp> +#include <glm/vec2.hpp> +#include <glm/vec3.hpp> + +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 = Ellipsoid::WGS84); + + /** + * @brief Creates a new instance. + * + * @param eastNorthUpToFixedFrame A transform that was computed with + * {@link Transforms::eastNorthUpToFixedFrame}. + * @param ellipsoid The ellipsoid. Default value: {@link Ellipsoid::WGS84}. + */ + EllipsoidTangentPlane( + const glm::dmat4& eastNorthUpToFixedFrame, + const Ellipsoid& ellipsoid = Ellipsoid::WGS84); + + /** + * @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); + + 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 0000000000000000000000000000000000000000..0dabeb977417aa2e579867a214b87c65415d281d --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGeospatial/GeographicProjection.h @@ -0,0 +1,154 @@ +#pragma once + +#include "Ellipsoid.h" +#include "GlobeRectangle.h" +#include "Library.h" + +#include <CesiumUtility/Math.h> + +#include <glm/vec2.hpp> +#include <glm/vec3.hpp> + +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 = Ellipsoid::WGS84) 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 = Ellipsoid::WGS84) 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/GlobeRectangle.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGeospatial/GlobeRectangle.h new file mode 100644 index 0000000000000000000000000000000000000000..7eef7753f2aeda5786e4098ff4e6d124d8cfe2a5 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGeospatial/GlobeRectangle.h @@ -0,0 +1,239 @@ +#pragma once + +#include "Cartographic.h" +#include "Library.h" + +#include <CesiumGeometry/Rectangle.h> +#include <CesiumUtility/Math.h> + +#include <optional> + +namespace CesiumGeospatial { + +/** + * @brief A two-dimensional, recangular 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 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<GlobeRectangle> + 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; + +private: + double _west; + double _south; + double _east; + double _north; +}; +} // 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 0000000000000000000000000000000000000000..423b64ad853fd339c76ae115f4d3126f8759f303 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGeospatial/Library.h @@ -0,0 +1,16 @@ +#pragma once + +/** + * @brief Classes for geospatial computations in Cesium + */ +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 0000000000000000000000000000000000000000..b135564797cb21231d9260b1627a8d429df10c08 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGeospatial/LocalHorizontalCoordinateSystem.h @@ -0,0 +1,146 @@ +#pragma once + +#include "Ellipsoid.h" +#include "Library.h" + +#include <glm/mat4x4.hpp> +#include <glm/vec3.hpp> + +namespace CesiumGeospatial { +class Cartographic; +} + +namespace CesiumGeospatial { + +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, + const Ellipsoid& ellipsoid = Ellipsoid::WGS84); + + /** + * @brief Create a new coordinate system centered at a Earth-Centered, + * Earth-Fixed position. + * + * @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 glm::dvec3& originEcef, + LocalDirection xAxisDirection = LocalDirection::East, + LocalDirection yAxisDirection = LocalDirection::North, + LocalDirection zAxisDirection = LocalDirection::Up, + double scaleToMeters = 1.0, + const Ellipsoid& ellipsoid = Ellipsoid::WGS84); + + /** + * @brief Gets the transformation matrix from the local horizontal coordinate + * system managed by this instance to the Earth-Centered, Earth-fixed + * coordinate system. + * + * @return The transformation. + */ + const glm::dmat4& getLocalToEcefTransformation() const noexcept { + return this->_localToEcef; + } + + /** + * @brief Gets the transformation matrix from the Earth-Centered, Earth-Fixed + * (ECEF) coordinate system 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 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; + + /** + * @brief Converts a position in the 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; + + /** + * @brief Converts a direction in the local horizontal coordinate system + * managed by this instance to Earth-Centered, Earth-Fixed (ECEF). + * + * Because the vector is treated as a direction only, the translation portion + * of the transformation is ignored. + * + * @param localPosition The direction in the local coordinate system. + * @return The equivalent direction in the ECEF coordinate system. + */ + glm::dvec3 localDirectionToEcef(const glm::dvec3& localDirection) const; + + /** + * @brief Converts a direction in the 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 ecefPosition The direction in the ECEF coordinate system. + * @return The equivalent direction in the local coordinate system. + */ + glm::dvec3 ecefDirectionToLocal(const glm::dvec3& ecefDirection) const; + +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 0000000000000000000000000000000000000000..6f8c05e926400aeda46515f9e945dc12254a101c --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGeospatial/Projection.h @@ -0,0 +1,132 @@ +#pragma once + +#include "BoundingRegion.h" +#include "CesiumGeometry/AxisAlignedBox.h" +#include "CesiumGeometry/Rectangle.h" +#include "GeographicProjection.h" +#include "WebMercatorProjection.h" + +#include <glm/vec2.hpp> + +#include <variant> + +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<GeographicProjection, WebMercatorProjection> 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 boundingRegion 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. + * @return The unprojected bounding region. + */ +BoundingRegion unprojectRegionSimple( + const Projection& projection, + const CesiumGeometry::AxisAlignedBox& box); + +/** + * @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 = Ellipsoid::WGS84); + +} // 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 0000000000000000000000000000000000000000..e8978902c7d35d9a719ae43add22260cb78da303 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGeospatial/S2CellBoundingVolume.h @@ -0,0 +1,114 @@ +#pragma once + +#include "BoundingRegion.h" +#include "Ellipsoid.h" +#include "S2CellID.h" + +#include <CesiumGeometry/CullingResult.h> +#include <CesiumGeometry/Plane.h> + +#include <glm/vec3.hpp> +#include <gsl/span> + +#include <array> +#include <string_view> + +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. + * + * @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. + */ +class CESIUMGEOSPATIAL_API S2CellBoundingVolume final { +public: + S2CellBoundingVolume( + const S2CellID& cellID, + double minimumHeight, + double maximumHeight, + const Ellipsoid& ellipsoid = Ellipsoid::WGS84); + + /** + * @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. + */ + gsl::span<const glm::dvec3> 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. + */ + gsl::span<const CesiumGeometry::Plane> getBoundingPlanes() const noexcept; + + /** + * @brief Computes the bounding begion that best fits this S2 cell volume. + * + * @return The bounding region. + */ + BoundingRegion computeBoundingRegion() const noexcept; + +private: + S2CellID _cellID; + double _minimumHeight; + double _maximumHeight; + glm::dvec3 _center; + std::array<CesiumGeometry::Plane, 6> _boundingPlanes; + std::array<glm::dvec3, 8> _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 0000000000000000000000000000000000000000..c98a092c953a832a4bf015e33550a9b241ff6aef --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGeospatial/S2CellID.h @@ -0,0 +1,172 @@ +#pragma once + +#include "Cartographic.h" +#include "GlobeRectangle.h" +#include "Library.h" + +#include <array> +#include <cstdint> +#include <string_view> + +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<Cartographic, 4> 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/Transforms.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGeospatial/Transforms.h new file mode 100644 index 0000000000000000000000000000000000000000..2b15148098e66d9586837f6b4dd14606c31aabcd --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGeospatial/Transforms.h @@ -0,0 +1,39 @@ +#pragma once + +#include "Ellipsoid.h" +#include "Library.h" + +#include <glm/mat4x4.hpp> +#include <glm/vec3.hpp> + +namespace CesiumGeospatial { + +/** + * @brief Transforms positions to various reference frames. + */ +class CESIUMGEOSPATIAL_API Transforms 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: <ul> + * <li>The `x` axis points in the local east direction.</li> + * <li>The `y` axis points in the local north direction.</li> + * <li>The `z` axis points in the direction of the ellipsoid surface normal + * which passes through the position.</li> + * </ul> + * + * @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 = Ellipsoid::WGS84) noexcept; +}; + +} // 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 0000000000000000000000000000000000000000..ee71d9f1e945b25873c4ad7707ad9b947eeba3cc --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGeospatial/WebMercatorProjection.h @@ -0,0 +1,175 @@ +#pragma once + +#include "Ellipsoid.h" +#include "GlobeRectangle.h" +#include "Library.h" + +#include <glm/vec2.hpp> +#include <glm/vec3.hpp> + +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 = Ellipsoid::WGS84) 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 = Ellipsoid::WGS84) 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/CesiumGltf/Accessor.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltf/Accessor.h new file mode 100644 index 0000000000000000000000000000000000000000..a49c2e8469697ebeb1fb50845cf6265d5ab37aee --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltf/Accessor.h @@ -0,0 +1,95 @@ +#pragma once + +#include "CesiumGltf/AccessorSpec.h" +#include "CesiumGltf/Library.h" + +#include <cstdint> + +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; + + /** + * @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 0000000000000000000000000000000000000000..ab390fbb3ebd5a9a861a523514190ac72dcc4a3f --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltf/AccessorSparse.h @@ -0,0 +1,40 @@ +// This file was generated by generate-classes. +// DO NOT EDIT THIS FILE! +#pragma once + +#include "CesiumGltf/AccessorSparseIndices.h" +#include "CesiumGltf/AccessorSparseValues.h" +#include "CesiumGltf/Library.h" + +#include <CesiumUtility/ExtensibleObject.h> + +#include <cstdint> + +namespace CesiumGltf { +/** + * @brief Sparse storage of accessor values that deviate from their + * initialization value. + */ +struct CESIUMGLTF_API AccessorSparse final + : public CesiumUtility::ExtensibleObject { + static inline 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; +}; +} // 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 0000000000000000000000000000000000000000..770ff5e44aac78c9705b0f54a2e7e9843b5b2273 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltf/AccessorSparseIndices.h @@ -0,0 +1,53 @@ +// This file was generated by generate-classes. +// DO NOT EDIT THIS FILE! +#pragma once + +#include "CesiumGltf/Library.h" + +#include <CesiumUtility/ExtensibleObject.h> + +#include <cstdint> + +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 { + static inline constexpr const char* TypeName = "AccessorSparseIndices"; + + /** + * @brief Known values for The indices data type. + */ + struct ComponentType { + static constexpr int32_t UNSIGNED_BYTE = 5121; + + static constexpr int32_t UNSIGNED_SHORT = 5123; + + 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; +}; +} // 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 0000000000000000000000000000000000000000..07d0d831dceda68fff3ca02efd363fc807431604 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltf/AccessorSparseValues.h @@ -0,0 +1,35 @@ +// This file was generated by generate-classes. +// DO NOT EDIT THIS FILE! +#pragma once + +#include "CesiumGltf/Library.h" + +#include <CesiumUtility/ExtensibleObject.h> + +#include <cstdint> + +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 { + static inline 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; +}; +} // 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 0000000000000000000000000000000000000000..5a5c1a57f1b9e35e7f260728c5223dfed0d8a841 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltf/AccessorSpec.h @@ -0,0 +1,155 @@ +// This file was generated by generate-classes. +// DO NOT EDIT THIS FILE! +#pragma once + +#include "CesiumGltf/AccessorSparse.h" +#include "CesiumGltf/Library.h" +#include "CesiumGltf/NamedObject.h" + +#include <cstdint> +#include <optional> +#include <vector> + +namespace CesiumGltf { +/** + * @brief A typed view into a buffer view that contains raw binary data. + */ +struct CESIUMGLTF_API AccessorSpec : public CesiumGltf::NamedObject { + static inline constexpr const char* TypeName = "Accessor"; + + /** + * @brief Known values for The datatype of the accessor's components. + */ + struct ComponentType { + static constexpr int32_t BYTE = 5120; + + static constexpr int32_t UNSIGNED_BYTE = 5121; + + static constexpr int32_t SHORT = 5122; + + static constexpr int32_t UNSIGNED_SHORT = 5123; + + static constexpr int32_t UNSIGNED_INT = 5125; + + static constexpr int32_t FLOAT = 5126; + }; + + /** + * @brief Known values for Specifies if the accessor's elements are scalars, + * vectors, or matrices. + */ + struct Type { + inline static const std::string SCALAR = "SCALAR"; + + inline static const std::string VEC2 = "VEC2"; + + inline static const std::string VEC3 = "VEC3"; + + inline static const std::string VEC4 = "VEC4"; + + inline static const std::string MAT2 = "MAT2"; + + inline static const std::string MAT3 = "MAT3"; + + 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<double> 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<double> min; + + /** + * @brief Sparse storage of elements that deviate from their initialization + * value. + */ + std::optional<CesiumGltf::AccessorSparse> sparse; + +private: + /** + * @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/AccessorView.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltf/AccessorView.h new file mode 100644 index 0000000000000000000000000000000000000000..7d2dc138f4b561ecf8a410067a0c166b66a2544f --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltf/AccessorView.h @@ -0,0 +1,480 @@ +#pragma once + +#include "CesiumGltf/Model.h" + +#include <cstddef> +#include <stdexcept> + +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 {@link Accessor:type} is invalid. + */ + InvalidType, + + /** + * @brief The {@link Accessor::componentType} is invalid. + */ + InvalidComponentType, +}; + +/** + * @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 T> 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<const T*>( + 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; } + +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<std::byte>& 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); + 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 <typename T> 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 <typename T> 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 <typename T> 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 <typename T> 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 <typename T> 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 <typename T> 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 <typename T> struct MAT4 { + /** + * @brief The component values of this element. + */ + T value[16]; + }; + +#pragma pack(pop) +}; + +namespace CesiumImpl { +template <typename TCallback, typename TElement> +std::invoke_result_t<TCallback, AccessorView<AccessorTypes::SCALAR<TElement>>> +createAccessorView( + const Model& model, + const Accessor& accessor, + TCallback&& callback) { + if (accessor.type == Accessor::Type::SCALAR) { + return callback( + AccessorView<AccessorTypes::SCALAR<TElement>>(model, accessor)); + } + if (accessor.type == Accessor::Type::VEC2) { + return callback( + AccessorView<AccessorTypes::VEC2<TElement>>(model, accessor)); + } + if (accessor.type == Accessor::Type::VEC3) { + return callback( + AccessorView<AccessorTypes::VEC3<TElement>>(model, accessor)); + } + if (accessor.type == Accessor::Type::VEC4) { + return callback( + AccessorView<AccessorTypes::VEC4<TElement>>(model, accessor)); + } + if (accessor.type == Accessor::Type::MAT2) { + return callback( + AccessorView<AccessorTypes::MAT2<TElement>>(model, accessor)); + } + if (accessor.type == Accessor::Type::MAT3) { + return callback( + AccessorView<AccessorTypes::MAT3<TElement>>(model, accessor)); + } + if (accessor.type == Accessor::Type::MAT4) { + return callback( + AccessorView<AccessorTypes::MAT4<TElement>>(model, accessor)); + } + // TODO Print a warning here??? + return callback(AccessorView<AccessorTypes::SCALAR<TElement>>( + AccessorViewStatus::InvalidComponentType)); +} +} // 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<AccessorTypes::SCALAR<float>>` 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 <typename TCallback> +std::invoke_result_t<TCallback, AccessorView<AccessorTypes::SCALAR<float>>> +createAccessorView( + const Model& model, + const Accessor& accessor, + TCallback&& callback) { + switch (accessor.componentType) { + case Accessor::ComponentType::BYTE: + return ::CesiumGltf::CesiumImpl::createAccessorView<TCallback, int8_t>( + model, + accessor, + std::forward<TCallback>(callback)); + case Accessor::ComponentType::UNSIGNED_BYTE: + return ::CesiumGltf::CesiumImpl::createAccessorView<TCallback, uint8_t>( + model, + accessor, + std::forward<TCallback>(callback)); + case Accessor::ComponentType::SHORT: + return ::CesiumGltf::CesiumImpl::createAccessorView<TCallback, int16_t>( + model, + accessor, + std::forward<TCallback>(callback)); + case Accessor::ComponentType::UNSIGNED_SHORT: + return ::CesiumGltf::CesiumImpl::createAccessorView<TCallback, uint16_t>( + model, + accessor, + std::forward<TCallback>(callback)); + case Accessor::ComponentType::UNSIGNED_INT: + return ::CesiumGltf::CesiumImpl::createAccessorView<TCallback, uint32_t>( + model, + accessor, + std::forward<TCallback>(callback)); + case Accessor::ComponentType::FLOAT: + return ::CesiumGltf::CesiumImpl::createAccessorView<TCallback, float>( + model, + accessor, + std::forward<TCallback>(callback)); + default: + return callback(AccessorView<AccessorTypes::SCALAR<float>>( + 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<AccessorTypes::SCALAR<float>>` 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 <typename TCallback> +std::invoke_result_t<TCallback, AccessorView<AccessorTypes::SCALAR<float>>> +createAccessorView( + const Model& model, + int32_t accessorIndex, + TCallback&& callback) { + const Accessor* pAccessor = Model::getSafe(&model.accessors, accessorIndex); + if (!pAccessor) { + return callback(AccessorView<AccessorTypes::SCALAR<float>>( + 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 0000000000000000000000000000000000000000..063fe2a9400b7d7d853fbe4c58c45dbf5fa852d2 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltf/AccessorWriter.h @@ -0,0 +1,50 @@ +#pragma once + +#include "CesiumGltf/AccessorView.h" + +namespace CesiumGltf { + +/** + * @brief Provides write access to an {@link AccessorView}. + */ +template <class T> class AccessorWriter final { +private: + AccessorView<T> _accessor; + +public: + AccessorWriter() : _accessor() {} + + /** @copydoc AccessorView::AccessorView(const + * uint8_t*,int64_t,int64_t,int64_t) */ + AccessorWriter(uint8_t* 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<T&>(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(); + } +}; + +} // 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 0000000000000000000000000000000000000000..8093deed0a23724fe11ea021a9fecc51f956a801 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltf/Animation.h @@ -0,0 +1,33 @@ +// This file was generated by generate-classes. +// DO NOT EDIT THIS FILE! +#pragma once + +#include "CesiumGltf/AnimationChannel.h" +#include "CesiumGltf/AnimationSampler.h" +#include "CesiumGltf/Library.h" +#include "CesiumGltf/NamedObject.h" + +#include <vector> + +namespace CesiumGltf { +/** + * @brief A keyframe animation. + */ +struct CESIUMGLTF_API Animation final : public CesiumGltf::NamedObject { + static inline 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<CesiumGltf::AnimationChannel> 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<CesiumGltf::AnimationSampler> samplers; +}; +} // 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 0000000000000000000000000000000000000000..5f6d48bfc14275cc9b628d7493d17a42883a0171 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltf/AnimationChannel.h @@ -0,0 +1,35 @@ +// This file was generated by generate-classes. +// DO NOT EDIT THIS FILE! +#pragma once + +#include "CesiumGltf/AnimationChannelTarget.h" +#include "CesiumGltf/Library.h" + +#include <CesiumUtility/ExtensibleObject.h> + +#include <cstdint> + +namespace CesiumGltf { +/** + * @brief An animation channel combines an animation sampler with a target + * property being animated. + */ +struct CESIUMGLTF_API AnimationChannel final + : public CesiumUtility::ExtensibleObject { + static inline 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; +}; +} // 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 0000000000000000000000000000000000000000..bbddc41956c39d7e62bf67f0fd18df09c59e5cca --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltf/AnimationChannelTarget.h @@ -0,0 +1,57 @@ +// This file was generated by generate-classes. +// DO NOT EDIT THIS FILE! +#pragma once + +#include "CesiumGltf/Library.h" + +#include <CesiumUtility/ExtensibleObject.h> + +#include <cstdint> + +namespace CesiumGltf { +/** + * @brief The descriptor of the animated property. + */ +struct CESIUMGLTF_API AnimationChannelTarget final + : public CesiumUtility::ExtensibleObject { + static inline 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 { + inline static const std::string translation = "translation"; + + inline static const std::string rotation = "rotation"; + + inline static const std::string scale = "scale"; + + 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; +}; +} // 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 0000000000000000000000000000000000000000..ed62598edf42cc6fad6d8c1c0fbb7fa731f4f7ab --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltf/AnimationSampler.h @@ -0,0 +1,53 @@ +// This file was generated by generate-classes. +// DO NOT EDIT THIS FILE! +#pragma once + +#include "CesiumGltf/Library.h" + +#include <CesiumUtility/ExtensibleObject.h> + +#include <cstdint> + +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 { + static inline constexpr const char* TypeName = "AnimationSampler"; + + /** + * @brief Known values for Interpolation algorithm. + */ + struct Interpolation { + inline static const std::string LINEAR = "LINEAR"; + + inline static const std::string STEP = "STEP"; + + 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; +}; +} // 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 0000000000000000000000000000000000000000..a233e355c59991f0a2c0500352c6208b95481bca --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltf/Asset.h @@ -0,0 +1,43 @@ +// This file was generated by generate-classes. +// DO NOT EDIT THIS FILE! +#pragma once + +#include "CesiumGltf/Library.h" + +#include <CesiumUtility/ExtensibleObject.h> + +#include <optional> +#include <string> + +namespace CesiumGltf { +/** + * @brief Metadata about the glTF asset. + */ +struct CESIUMGLTF_API Asset final : public CesiumUtility::ExtensibleObject { + static inline constexpr const char* TypeName = "Asset"; + + /** + * @brief A copyright message suitable for display to credit the content + * creator. + */ + std::optional<std::string> copyright; + + /** + * @brief Tool that generated this glTF model. Useful for debugging. + */ + std::optional<std::string> generator; + + /** + * @brief The glTF version in the form of `<major>.<minor>` that this asset + * targets. + */ + std::string version; + + /** + * @brief The minimum glTF version in the form of `<major>.<minor>` that this + * asset targets. This property **MUST NOT** be greater than the asset + * version. + */ + std::optional<std::string> minVersion; +}; +} // 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 0000000000000000000000000000000000000000..889b9ebc76d2b2cbd83f910e02da16a7500fa326 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltf/Buffer.h @@ -0,0 +1,16 @@ +#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 { + /** + * @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 0000000000000000000000000000000000000000..1aab061a16dd0fe40ac671143ab8fede4d6dd51a --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltf/BufferCesium.h @@ -0,0 +1,19 @@ +#pragma once + +#include "CesiumGltf/Library.h" + +#include <cstddef> +#include <vector> + +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<std::byte> 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 0000000000000000000000000000000000000000..1b8170e8d5dd6d15d0ec9e41fa9964172563c305 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltf/BufferSpec.h @@ -0,0 +1,39 @@ +// This file was generated by generate-classes. +// DO NOT EDIT THIS FILE! +#pragma once + +#include "CesiumGltf/Library.h" +#include "CesiumGltf/NamedObject.h" + +#include <cstdint> +#include <optional> +#include <string> + +namespace CesiumGltf { +/** + * @brief A buffer points to binary geometry, animation, or skins. + */ +struct CESIUMGLTF_API BufferSpec : public CesiumGltf::NamedObject { + static inline 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<std::string> uri; + + /** + * @brief The length of the buffer in bytes. + */ + int64_t byteLength = int64_t(); + +private: + /** + * @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 0000000000000000000000000000000000000000..9f15bd7801671063c740349efd719ba19f08c684 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltf/BufferView.h @@ -0,0 +1,61 @@ +// This file was generated by generate-classes. +// DO NOT EDIT THIS FILE! +#pragma once + +#include "CesiumGltf/Library.h" +#include "CesiumGltf/NamedObject.h" + +#include <cstdint> +#include <optional> + +namespace CesiumGltf { +/** + * @brief A view into a buffer generally representing a subset of the buffer. + */ +struct CESIUMGLTF_API BufferView final : public CesiumGltf::NamedObject { + static inline 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 { + static constexpr int32_t ARRAY_BUFFER = 34962; + + 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<int64_t> 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<int32_t> target; +}; +} // 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 0000000000000000000000000000000000000000..2efa29be8d71fce56a0a7d650ba1e853b11891e8 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltf/Camera.h @@ -0,0 +1,56 @@ +// This file was generated by generate-classes. +// DO NOT EDIT THIS FILE! +#pragma once + +#include "CesiumGltf/CameraOrthographic.h" +#include "CesiumGltf/CameraPerspective.h" +#include "CesiumGltf/Library.h" +#include "CesiumGltf/NamedObject.h" + +#include <optional> + +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 { + static inline constexpr const char* TypeName = "Camera"; + + /** + * @brief Known values for Specifies if the camera uses a perspective or + * orthographic projection. + */ + struct Type { + inline static const std::string perspective = "perspective"; + + 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<CesiumGltf::CameraOrthographic> 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<CesiumGltf::CameraPerspective> 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; +}; +} // 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 0000000000000000000000000000000000000000..f21b6aabc27e97bcb1d99279e01ff42bcc7dae46 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltf/CameraOrthographic.h @@ -0,0 +1,41 @@ +// This file was generated by generate-classes. +// DO NOT EDIT THIS FILE! +#pragma once + +#include "CesiumGltf/Library.h" + +#include <CesiumUtility/ExtensibleObject.h> + +namespace CesiumGltf { +/** + * @brief An orthographic camera containing properties to create an orthographic + * projection matrix. + */ +struct CESIUMGLTF_API CameraOrthographic final + : public CesiumUtility::ExtensibleObject { + static inline 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(); +}; +} // 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 0000000000000000000000000000000000000000..d89cc06980c8396dba83a29c597f5877145a7164 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltf/CameraPerspective.h @@ -0,0 +1,48 @@ +// This file was generated by generate-classes. +// DO NOT EDIT THIS FILE! +#pragma once + +#include "CesiumGltf/Library.h" + +#include <CesiumUtility/ExtensibleObject.h> + +#include <optional> + +namespace CesiumGltf { +/** + * @brief A perspective camera containing properties to create a perspective + * projection matrix. + */ +struct CESIUMGLTF_API CameraPerspective final + : public CesiumUtility::ExtensibleObject { + static inline 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<double> 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<double> zfar; + + /** + * @brief The floating-point distance to the near clipping plane. + */ + double znear = double(); +}; +} // 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 0000000000000000000000000000000000000000..e48709493763dae6a3c848b5d9f9cdc7c68187d2 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltf/Class.h @@ -0,0 +1,37 @@ +// This file was generated by generate-classes. +// DO NOT EDIT THIS FILE! +#pragma once + +#include "CesiumGltf/ClassProperty.h" +#include "CesiumGltf/Library.h" + +#include <CesiumUtility/ExtensibleObject.h> + +#include <optional> +#include <string> +#include <unordered_map> + +namespace CesiumGltf { +/** + * @brief A class containing a set of properties. + */ +struct CESIUMGLTF_API Class final : public CesiumUtility::ExtensibleObject { + static inline constexpr const char* TypeName = "Class"; + + /** + * @brief The name of the class, e.g. for display purposes. + */ + std::optional<std::string> name; + + /** + * @brief The description of the class. + */ + std::optional<std::string> description; + + /** + * @brief A dictionary, where each key is a property ID and each value is an + * object defining the property. + */ + std::unordered_map<std::string, CesiumGltf::ClassProperty> properties; +}; +} // 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 0000000000000000000000000000000000000000..106d0d1b1b1854c6041e2bba23e95975f70d5999 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltf/ClassProperty.h @@ -0,0 +1,181 @@ +// This file was generated by generate-classes. +// DO NOT EDIT THIS FILE! +#pragma once + +#include "CesiumGltf/Library.h" + +#include <CesiumUtility/ExtensibleObject.h> +#include <CesiumUtility/JsonValue.h> + +#include <cstdint> +#include <optional> +#include <string> + +namespace CesiumGltf { +/** + * @brief A class property. + */ +struct CESIUMGLTF_API ClassProperty final + : public CesiumUtility::ExtensibleObject { + static inline constexpr const char* TypeName = "ClassProperty"; + + /** + * @brief Known values for The property type. If `ENUM` is used, then + * `enumType` must also be specified. If `ARRAY` is used, then `componentType` + * must also be specified. `ARRAY` is a fixed-length array when + * `componentCount` is defined, and variable-length otherwise. + */ + struct Type { + inline static const std::string INT8 = "INT8"; + + inline static const std::string UINT8 = "UINT8"; + + inline static const std::string INT16 = "INT16"; + + inline static const std::string UINT16 = "UINT16"; + + inline static const std::string INT32 = "INT32"; + + inline static const std::string UINT32 = "UINT32"; + + inline static const std::string INT64 = "INT64"; + + inline static const std::string UINT64 = "UINT64"; + + inline static const std::string FLOAT32 = "FLOAT32"; + + inline static const std::string FLOAT64 = "FLOAT64"; + + inline static const std::string BOOLEAN = "BOOLEAN"; + + inline static const std::string STRING = "STRING"; + + inline static const std::string ENUM = "ENUM"; + + inline static const std::string ARRAY = "ARRAY"; + }; + + /** + * @brief Known values for When `type` is `ARRAY` this indicates the type of + * each component of the array. If `ENUM` is used, then `enumType` must also + * be specified. + */ + struct ComponentType { + inline static const std::string INT8 = "INT8"; + + inline static const std::string UINT8 = "UINT8"; + + inline static const std::string INT16 = "INT16"; + + inline static const std::string UINT16 = "UINT16"; + + inline static const std::string INT32 = "INT32"; + + inline static const std::string UINT32 = "UINT32"; + + inline static const std::string INT64 = "INT64"; + + inline static const std::string UINT64 = "UINT64"; + + inline static const std::string FLOAT32 = "FLOAT32"; + + inline static const std::string FLOAT64 = "FLOAT64"; + + inline static const std::string BOOLEAN = "BOOLEAN"; + + inline static const std::string STRING = "STRING"; + + inline static const std::string ENUM = "ENUM"; + }; + + /** + * @brief The name of the property, e.g. for display purposes. + */ + std::optional<std::string> name; + + /** + * @brief The description of the property. + */ + std::optional<std::string> description; + + /** + * @brief The property type. If `ENUM` is used, then `enumType` must also be + * specified. If `ARRAY` is used, then `componentType` must also be specified. + * `ARRAY` is a fixed-length array when `componentCount` is defined, and + * variable-length otherwise. + * + * Known values are defined in {@link Type}. + * + */ + std::string type = Type::INT8; + + /** + * @brief An enum ID as declared in the `enums` dictionary. This value must be + * specified when `type` or `componentType` is `ENUM`. + */ + std::optional<std::string> enumType; + + /** + * @brief When `type` is `ARRAY` this indicates the type of each component of + * the array. If `ENUM` is used, then `enumType` must also be specified. + * + * Known values are defined in {@link ComponentType}. + * + */ + std::optional<std::string> componentType; + + /** + * @brief The number of components per element for `ARRAY` elements. + */ + std::optional<int64_t> componentCount; + + /** + * @brief Specifies whether integer values are normalized. This applies both + * when `type` is an integer type, or when `type` is `ARRAY` with a + * `componentType` that is an integer type. For unsigned integer types, values + * are normalized between `[0.0, 1.0]`. For signed integer types, values are + * normalized between `[-1.0, 1.0]`. For all other types, this property is + * ignored. + */ + bool normalized = false; + + /** + * @brief Maximum allowed values for property values. Only applicable for + * numeric types and fixed-length arrays of numeric types. For numeric types + * this is a single number. For fixed-length arrays this is an array with + * `componentCount` number of elements. The `normalized` property has no + * effect on these values: they always correspond to the integer values. + */ + std::optional<CesiumUtility::JsonValue> max; + + /** + * @brief Minimum allowed values for property values. Only applicable for + * numeric types and fixed-length arrays of numeric types. For numeric types + * this is a single number. For fixed-length arrays this is an array with + * `componentCount` number of elements. The `normalized` property has no + * effect on these values: they always correspond to the integer values. + */ + std::optional<CesiumUtility::JsonValue> min; + + /** + * @brief A default value to use when the property value is not defined. If + * used, `optional` must be set to true. The type of the default value must + * match the property definition: For `BOOLEAN` use `true` or `false`. For + * `STRING` use a JSON string. For a numeric type use a JSON number. For + * `ENUM` use the enum `name`, not the integer value. For `ARRAY` use a JSON + * array containing values matching the `componentType`. + */ + std::optional<CesiumUtility::JsonValue> defaultProperty; + + /** + * @brief If true, this property is optional. + */ + bool optional = false; + + /** + * @brief An identifier that describes how this property should be + * interpreted. The semantic cannot be used by other properties in the class. + */ + std::optional<std::string> semantic; +}; +} // namespace CesiumGltf diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltf/ClassStatistics.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltf/ClassStatistics.h new file mode 100644 index 0000000000000000000000000000000000000000..83f8a59631ccdd6028b20c5a891db2f090a3288a --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltf/ClassStatistics.h @@ -0,0 +1,34 @@ +// This file was generated by generate-classes. +// DO NOT EDIT THIS FILE! +#pragma once + +#include "CesiumGltf/Library.h" +#include "CesiumGltf/PropertyStatistics.h" + +#include <CesiumUtility/ExtensibleObject.h> + +#include <cstdint> +#include <optional> +#include <unordered_map> + +namespace CesiumGltf { +/** + * @brief Statistics about features that conform to the class. + */ +struct CESIUMGLTF_API ClassStatistics final + : public CesiumUtility::ExtensibleObject { + static inline constexpr const char* TypeName = "ClassStatistics"; + + /** + * @brief The number of features that conform to the class. + */ + std::optional<int64_t> 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<std::string, CesiumGltf::PropertyStatistics> properties; +}; +} // 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 0000000000000000000000000000000000000000..2aac09e6a68e3f67cc616af02fa92723eb5ab480 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltf/Enum.h @@ -0,0 +1,66 @@ +// This file was generated by generate-classes. +// DO NOT EDIT THIS FILE! +#pragma once + +#include "CesiumGltf/EnumValue.h" +#include "CesiumGltf/Library.h" + +#include <CesiumUtility/ExtensibleObject.h> + +#include <optional> +#include <string> +#include <vector> + +namespace CesiumGltf { +/** + * @brief An object defining the values of an enum. + */ +struct CESIUMGLTF_API Enum final : public CesiumUtility::ExtensibleObject { + static inline constexpr const char* TypeName = "Enum"; + + /** + * @brief Known values for The type of the integer enum value. + */ + struct ValueType { + inline static const std::string INT8 = "INT8"; + + inline static const std::string UINT8 = "UINT8"; + + inline static const std::string INT16 = "INT16"; + + inline static const std::string UINT16 = "UINT16"; + + inline static const std::string INT32 = "INT32"; + + inline static const std::string UINT32 = "UINT32"; + + inline static const std::string INT64 = "INT64"; + + inline static const std::string UINT64 = "UINT64"; + }; + + /** + * @brief The name of the enum, e.g. for display purposes. + */ + std::optional<std::string> name; + + /** + * @brief The description of the enum. + */ + std::optional<std::string> 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<CesiumGltf::EnumValue> values; +}; +} // 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 0000000000000000000000000000000000000000..d1c505a4edc2d9b7985c7afd0ebef78e4d21e4e1 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltf/EnumValue.h @@ -0,0 +1,35 @@ +// This file was generated by generate-classes. +// DO NOT EDIT THIS FILE! +#pragma once + +#include "CesiumGltf/Library.h" + +#include <CesiumUtility/ExtensibleObject.h> + +#include <cstdint> +#include <optional> +#include <string> + +namespace CesiumGltf { +/** + * @brief An enum value. + */ +struct CESIUMGLTF_API EnumValue final : public CesiumUtility::ExtensibleObject { + static inline constexpr const char* TypeName = "EnumValue"; + + /** + * @brief The name of the enum value. + */ + std::string name; + + /** + * @brief The description of the enum value. + */ + std::optional<std::string> description; + + /** + * @brief The integer enum value. + */ + int64_t value = int64_t(); +}; +} // 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 0000000000000000000000000000000000000000..42ce3f1741d11be3b90cffb56d51c6678802eb50 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltf/ExtensionBufferExtMeshoptCompression.h @@ -0,0 +1,26 @@ +// This file was generated by generate-classes. +// DO NOT EDIT THIS FILE! +#pragma once + +#include "CesiumGltf/Library.h" + +#include <CesiumUtility/ExtensibleObject.h> + +namespace CesiumGltf { +/** + * @brief Compressed data for bufferView. + */ +struct CESIUMGLTF_API ExtensionBufferExtMeshoptCompression final + : public CesiumUtility::ExtensibleObject { + static inline constexpr const char* TypeName = + "ExtensionBufferExtMeshoptCompression"; + static inline 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; +}; +} // 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 0000000000000000000000000000000000000000..b258b64682fbb5149ad370a0172e6545c7ff6815 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltf/ExtensionBufferViewExtMeshoptCompression.h @@ -0,0 +1,86 @@ +// This file was generated by generate-classes. +// DO NOT EDIT THIS FILE! +#pragma once + +#include "CesiumGltf/Library.h" + +#include <CesiumUtility/ExtensibleObject.h> + +#include <cstdint> + +namespace CesiumGltf { +/** + * @brief Compressed data for bufferView. + */ +struct CESIUMGLTF_API ExtensionBufferViewExtMeshoptCompression final + : public CesiumUtility::ExtensibleObject { + static inline constexpr const char* TypeName = + "ExtensionBufferViewExtMeshoptCompression"; + static inline constexpr const char* ExtensionName = "EXT_meshopt_compression"; + + /** + * @brief Known values for The compression mode. + */ + struct Mode { + inline static const std::string ATTRIBUTES = "ATTRIBUTES"; + + inline static const std::string TRIANGLES = "TRIANGLES"; + + inline static const std::string INDICES = "INDICES"; + }; + + /** + * @brief Known values for The compression filter. + */ + struct Filter { + inline static const std::string NONE = "NONE"; + + inline static const std::string OCTAHEDRAL = "OCTAHEDRAL"; + + inline static const std::string QUATERNION = "QUATERNION"; + + 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; +}; +} // 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 0000000000000000000000000000000000000000..fdd9580e2221baafe2217c9b40ad6e2a996b7117 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltf/ExtensionCesiumRTC.h @@ -0,0 +1,25 @@ +// This file was generated by generate-classes. +// DO NOT EDIT THIS FILE! +#pragma once + +#include "CesiumGltf/Library.h" + +#include <CesiumUtility/ExtensibleObject.h> + +#include <vector> + +namespace CesiumGltf { +/** + * @brief glTF CESIUM_RTC extension. + */ +struct CESIUMGLTF_API ExtensionCesiumRTC final + : public CesiumUtility::ExtensibleObject { + static inline constexpr const char* TypeName = "ExtensionCesiumRTC"; + static inline constexpr const char* ExtensionName = "CESIUM_RTC"; + + /** + * @brief Center that vertex positions are relative to. + */ + std::vector<double> center; +}; +} // 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 0000000000000000000000000000000000000000..33d4a5222f4910edbfa01de0d8679a7f970d65ef --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltf/ExtensionCesiumTileEdges.h @@ -0,0 +1,44 @@ +// This file was generated by generate-classes. +// DO NOT EDIT THIS FILE! +#pragma once + +#include "CesiumGltf/Library.h" + +#include <CesiumUtility/ExtensibleObject.h> + +#include <cstdint> + +namespace CesiumGltf { +/** + * @brief `CESIUM_tile_edges` extension for a primitive in a glTF model. + */ +struct CESIUMGLTF_API ExtensionCesiumTileEdges final + : public CesiumUtility::ExtensibleObject { + static inline constexpr const char* TypeName = "ExtensionCesiumTileEdges"; + static inline 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; +}; +} // 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 0000000000000000000000000000000000000000..7fa25d1ad3f9c159a0563c702a2a0193f2e605cd --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltf/ExtensionExtInstanceFeatures.h @@ -0,0 +1,26 @@ +// This file was generated by generate-classes. +// DO NOT EDIT THIS FILE! +#pragma once + +#include "CesiumGltf/ExtensionExtInstanceFeaturesFeatureId.h" +#include "CesiumGltf/Library.h" + +#include <CesiumUtility/ExtensibleObject.h> + +#include <vector> + +namespace CesiumGltf { +/** + * @brief An object describing per-instance feature IDs. + */ +struct CESIUMGLTF_API ExtensionExtInstanceFeatures final + : public CesiumUtility::ExtensibleObject { + static inline constexpr const char* TypeName = "ExtensionExtInstanceFeatures"; + static inline constexpr const char* ExtensionName = "EXT_instance_features"; + + /** + * @brief An array of feature ID sets. + */ + std::vector<CesiumGltf::ExtensionExtInstanceFeaturesFeatureId> featureIds; +}; +} // 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 0000000000000000000000000000000000000000..b22161ba5294401f730d7f4ecddd89b9e799e3bf --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltf/ExtensionExtInstanceFeaturesFeatureId.h @@ -0,0 +1,53 @@ +// This file was generated by generate-classes. +// DO NOT EDIT THIS FILE! +#pragma once + +#include "CesiumGltf/Library.h" + +#include <CesiumUtility/ExtensibleObject.h> + +#include <cstdint> +#include <optional> +#include <string> + +namespace CesiumGltf { +/** + * @brief Feature IDs stored in a GPU mesh instancing attribute + */ +struct CESIUMGLTF_API ExtensionExtInstanceFeaturesFeatureId final + : public CesiumUtility::ExtensibleObject { + static inline 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<int64_t> 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<std::string> label; + + /** + * @brief An integer value used to construct a string in the format + * `_FEATURE_ID_<set index>` 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<int64_t> attribute; + + /** + * @brief The index of the property table containing per-feature property + * values. Only applicable when using the `EXT_structural_metadata` extension. + */ + std::optional<int64_t> propertyTable; +}; +} // 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 0000000000000000000000000000000000000000..397b3728279b62b1f880d64f5928463204558ff2 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltf/ExtensionExtMeshFeatures.h @@ -0,0 +1,26 @@ +// This file was generated by generate-classes. +// DO NOT EDIT THIS FILE! +#pragma once + +#include "CesiumGltf/ExtensionExtMeshFeaturesFeatureId.h" +#include "CesiumGltf/Library.h" + +#include <CesiumUtility/ExtensibleObject.h> + +#include <vector> + +namespace CesiumGltf { +/** + * @brief An object describing feature IDs for a mesh primitive. + */ +struct CESIUMGLTF_API ExtensionExtMeshFeatures final + : public CesiumUtility::ExtensibleObject { + static inline constexpr const char* TypeName = "ExtensionExtMeshFeatures"; + static inline constexpr const char* ExtensionName = "EXT_mesh_features"; + + /** + * @brief An array of feature ID sets. + */ + std::vector<CesiumGltf::ExtensionExtMeshFeaturesFeatureId> featureIds; +}; +} // namespace CesiumGltf diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltf/ExtensionExtMeshFeaturesFeatureId.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltf/ExtensionExtMeshFeaturesFeatureId.h new file mode 100644 index 0000000000000000000000000000000000000000..5895e8ea4412e75dd6f7720bf6dcaf6e7061c927 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltf/ExtensionExtMeshFeaturesFeatureId.h @@ -0,0 +1,59 @@ +// This file was generated by generate-classes. +// DO NOT EDIT THIS FILE! +#pragma once + +#include "CesiumGltf/ExtensionExtMeshFeaturesFeatureIdTexture.h" +#include "CesiumGltf/Library.h" + +#include <CesiumUtility/ExtensibleObject.h> + +#include <cstdint> +#include <optional> +#include <string> + +namespace CesiumGltf { +/** + * @brief Feature IDs stored in an attribute or texture. + */ +struct CESIUMGLTF_API ExtensionExtMeshFeaturesFeatureId final + : public CesiumUtility::ExtensibleObject { + static inline constexpr const char* TypeName = + "ExtensionExtMeshFeaturesFeatureId"; + + /** + * @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<int64_t> 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<std::string> label; + + /** + * @brief An integer value used to construct a string in the format + * `_FEATURE_ID_<set index>` which is a reference to a key in + * `mesh.primitives.attributes` (e.g. a value of `0` corresponds to + * `_FEATURE_ID_0`). + */ + std::optional<int64_t> attribute; + + /** + * @brief A texture containing feature IDs. + */ + std::optional<CesiumGltf::ExtensionExtMeshFeaturesFeatureIdTexture> texture; + + /** + * @brief The index of the property table containing per-feature property + * values. Only applicable when using the `EXT_structural_metadata` extension. + */ + std::optional<int64_t> propertyTable; +}; +} // namespace CesiumGltf diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltf/ExtensionExtMeshFeaturesFeatureIdTexture.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltf/ExtensionExtMeshFeaturesFeatureIdTexture.h new file mode 100644 index 0000000000000000000000000000000000000000..de709adf10ae2219af9f3e20efea586ad4cc8d8e --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltf/ExtensionExtMeshFeaturesFeatureIdTexture.h @@ -0,0 +1,28 @@ +// This file was generated by generate-classes. +// DO NOT EDIT THIS FILE! +#pragma once + +#include "CesiumGltf/Library.h" +#include "CesiumGltf/TextureInfo.h" + +#include <cstdint> +#include <vector> + +namespace CesiumGltf { +/** + * @brief A texture containing feature IDs + */ +struct CESIUMGLTF_API ExtensionExtMeshFeaturesFeatureIdTexture final + : public TextureInfo { + static inline constexpr const char* TypeName = + "ExtensionExtMeshFeaturesFeatureIdTexture"; + + /** + * @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<int64_t> channels = {0}; +}; +} // 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 0000000000000000000000000000000000000000..8cffbe096ea2da6688e2aaf8be8c5c51af00b157 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltf/ExtensionExtMeshGpuInstancing.h @@ -0,0 +1,35 @@ +// This file was generated by generate-classes. +// DO NOT EDIT THIS FILE! +#pragma once + +#include "CesiumGltf/Library.h" + +#include <CesiumUtility/ExtensibleObject.h> + +#include <cstdint> +#include <unordered_map> + +namespace CesiumGltf { +/** + * @brief glTF extension defines instance attributes for a node with a mesh. + */ +struct CESIUMGLTF_API ExtensionExtMeshGpuInstancing final + : public CesiumUtility::ExtensibleObject { + static inline constexpr const char* TypeName = + "ExtensionExtMeshGpuInstancing"; + static inline 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<std::string, int32_t> attributes; +}; +} // namespace CesiumGltf diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltf/ExtensionExtStructuralMetadataClass.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltf/ExtensionExtStructuralMetadataClass.h new file mode 100644 index 0000000000000000000000000000000000000000..caaed0ddf881c7d195f1111a094e695af1a73812 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltf/ExtensionExtStructuralMetadataClass.h @@ -0,0 +1,43 @@ +// This file was generated by generate-classes. +// DO NOT EDIT THIS FILE! +#pragma once + +#include "CesiumGltf/ExtensionExtStructuralMetadataClassProperty.h" +#include "CesiumGltf/Library.h" + +#include <CesiumUtility/ExtensibleObject.h> + +#include <optional> +#include <string> +#include <unordered_map> + +namespace CesiumGltf { +/** + * @brief A class containing a set of properties. + */ +struct CESIUMGLTF_API ExtensionExtStructuralMetadataClass final + : public CesiumUtility::ExtensibleObject { + static inline constexpr const char* TypeName = + "ExtensionExtStructuralMetadataClass"; + + /** + * @brief The name of the class, e.g. for display purposes. + */ + std::optional<std::string> name; + + /** + * @brief The description of the class. + */ + std::optional<std::string> 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< + std::string, + CesiumGltf::ExtensionExtStructuralMetadataClassProperty> + properties; +}; +} // namespace CesiumGltf diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltf/ExtensionExtStructuralMetadataClassProperty.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltf/ExtensionExtStructuralMetadataClassProperty.h new file mode 100644 index 0000000000000000000000000000000000000000..24586618035530f6bbbd4553b635dab11ccfe69e --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltf/ExtensionExtStructuralMetadataClassProperty.h @@ -0,0 +1,192 @@ +// This file was generated by generate-classes. +// DO NOT EDIT THIS FILE! +#pragma once + +#include "CesiumGltf/Library.h" + +#include <CesiumUtility/ExtensibleObject.h> +#include <CesiumUtility/JsonValue.h> + +#include <cstdint> +#include <optional> +#include <string> + +namespace CesiumGltf { +/** + * @brief A class property. + */ +struct CESIUMGLTF_API ExtensionExtStructuralMetadataClassProperty final + : public CesiumUtility::ExtensibleObject { + static inline constexpr const char* TypeName = + "ExtensionExtStructuralMetadataClassProperty"; + + /** + * @brief Known values for The element type. + */ + struct Type { + inline static const std::string SCALAR = "SCALAR"; + + inline static const std::string VEC2 = "VEC2"; + + inline static const std::string VEC3 = "VEC3"; + + inline static const std::string VEC4 = "VEC4"; + + inline static const std::string MAT2 = "MAT2"; + + inline static const std::string MAT3 = "MAT3"; + + inline static const std::string MAT4 = "MAT4"; + + inline static const std::string STRING = "STRING"; + + inline static const std::string BOOLEAN = "BOOLEAN"; + + 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 { + inline static const std::string INT8 = "INT8"; + + inline static const std::string UINT8 = "UINT8"; + + inline static const std::string INT16 = "INT16"; + + inline static const std::string UINT16 = "UINT16"; + + inline static const std::string INT32 = "INT32"; + + inline static const std::string UINT32 = "UINT32"; + + inline static const std::string INT64 = "INT64"; + + inline static const std::string UINT64 = "UINT64"; + + inline static const std::string FLOAT32 = "FLOAT32"; + + inline static const std::string FLOAT64 = "FLOAT64"; + }; + + /** + * @brief The name of the property, e.g. for display purposes. + */ + std::optional<std::string> name; + + /** + * @brief The description of the property. + */ + std::optional<std::string> 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<std::string> componentType; + + /** + * @brief Enum ID as declared in the `enums` dictionary. Required when `type` + * is `ENUM`. + */ + std::optional<std::string> 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<int64_t> 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<CesiumUtility::JsonValue> 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<CesiumUtility::JsonValue> 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<CesiumUtility::JsonValue> 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<CesiumUtility::JsonValue> 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<CesiumUtility::JsonValue> 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<CesiumUtility::JsonValue> 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<std::string> semantic; +}; +} // namespace CesiumGltf diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltf/ExtensionExtStructuralMetadataEnum.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltf/ExtensionExtStructuralMetadataEnum.h new file mode 100644 index 0000000000000000000000000000000000000000..a9c95a7dfe89027a94ac8dd85f18b9d99744933a --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltf/ExtensionExtStructuralMetadataEnum.h @@ -0,0 +1,68 @@ +// This file was generated by generate-classes. +// DO NOT EDIT THIS FILE! +#pragma once + +#include "CesiumGltf/ExtensionExtStructuralMetadataEnumValue.h" +#include "CesiumGltf/Library.h" + +#include <CesiumUtility/ExtensibleObject.h> + +#include <optional> +#include <string> +#include <vector> + +namespace CesiumGltf { +/** + * @brief An object defining the values of an enum. + */ +struct CESIUMGLTF_API ExtensionExtStructuralMetadataEnum final + : public CesiumUtility::ExtensibleObject { + static inline constexpr const char* TypeName = + "ExtensionExtStructuralMetadataEnum"; + + /** + * @brief Known values for The type of the integer enum value. + */ + struct ValueType { + inline static const std::string INT8 = "INT8"; + + inline static const std::string UINT8 = "UINT8"; + + inline static const std::string INT16 = "INT16"; + + inline static const std::string UINT16 = "UINT16"; + + inline static const std::string INT32 = "INT32"; + + inline static const std::string UINT32 = "UINT32"; + + inline static const std::string INT64 = "INT64"; + + inline static const std::string UINT64 = "UINT64"; + }; + + /** + * @brief The name of the enum, e.g. for display purposes. + */ + std::optional<std::string> name; + + /** + * @brief The description of the enum. + */ + std::optional<std::string> 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<CesiumGltf::ExtensionExtStructuralMetadataEnumValue> values; +}; +} // namespace CesiumGltf diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltf/ExtensionExtStructuralMetadataEnumValue.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltf/ExtensionExtStructuralMetadataEnumValue.h new file mode 100644 index 0000000000000000000000000000000000000000..57bc283392ee05bd1cf5fdbbfb88b8bc167488f8 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltf/ExtensionExtStructuralMetadataEnumValue.h @@ -0,0 +1,37 @@ +// This file was generated by generate-classes. +// DO NOT EDIT THIS FILE! +#pragma once + +#include "CesiumGltf/Library.h" + +#include <CesiumUtility/ExtensibleObject.h> + +#include <cstdint> +#include <optional> +#include <string> + +namespace CesiumGltf { +/** + * @brief An enum value. + */ +struct CESIUMGLTF_API ExtensionExtStructuralMetadataEnumValue final + : public CesiumUtility::ExtensibleObject { + static inline constexpr const char* TypeName = + "ExtensionExtStructuralMetadataEnumValue"; + + /** + * @brief The name of the enum value. + */ + std::string name; + + /** + * @brief The description of the enum value. + */ + std::optional<std::string> description; + + /** + * @brief The integer enum value. + */ + int64_t value = int64_t(); +}; +} // namespace CesiumGltf diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltf/ExtensionExtStructuralMetadataPropertyAttribute.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltf/ExtensionExtStructuralMetadataPropertyAttribute.h new file mode 100644 index 0000000000000000000000000000000000000000..9222d9571b5fcb9a1ed62637b23d9059f2dbbc4a --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltf/ExtensionExtStructuralMetadataPropertyAttribute.h @@ -0,0 +1,46 @@ +// This file was generated by generate-classes. +// DO NOT EDIT THIS FILE! +#pragma once + +#include "CesiumGltf/ExtensionExtStructuralMetadataPropertyAttributeProperty.h" +#include "CesiumGltf/Library.h" + +#include <CesiumUtility/ExtensibleObject.h> + +#include <optional> +#include <string> +#include <unordered_map> + +namespace CesiumGltf { +/** + * @brief Properties conforming to a class, organized as property values stored + * in attributes. + */ +struct CESIUMGLTF_API ExtensionExtStructuralMetadataPropertyAttribute final + : public CesiumUtility::ExtensibleObject { + static inline constexpr const char* TypeName = + "ExtensionExtStructuralMetadataPropertyAttribute"; + + /** + * @brief The name of the property attribute, e.g. for display purposes. + */ + std::optional<std::string> 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< + std::string, + CesiumGltf::ExtensionExtStructuralMetadataPropertyAttributeProperty> + properties; +}; +} // namespace CesiumGltf diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltf/ExtensionExtStructuralMetadataPropertyAttributeProperty.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltf/ExtensionExtStructuralMetadataPropertyAttributeProperty.h new file mode 100644 index 0000000000000000000000000000000000000000..25405e9f3b7fac7e1914b9c79b8fff08568433d2 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltf/ExtensionExtStructuralMetadataPropertyAttributeProperty.h @@ -0,0 +1,57 @@ +// This file was generated by generate-classes. +// DO NOT EDIT THIS FILE! +#pragma once + +#include "CesiumGltf/Library.h" + +#include <CesiumUtility/ExtensibleObject.h> +#include <CesiumUtility/JsonValue.h> + +#include <optional> +#include <string> + +namespace CesiumGltf { +/** + * @brief An attribute containing property values. + */ +struct CESIUMGLTF_API ExtensionExtStructuralMetadataPropertyAttributeProperty + final : public CesiumUtility::ExtensibleObject { + static inline constexpr const char* TypeName = + "ExtensionExtStructuralMetadataPropertyAttributeProperty"; + + /** + * @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<CesiumUtility::JsonValue> 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<CesiumUtility::JsonValue> 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<CesiumUtility::JsonValue> 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<CesiumUtility::JsonValue> min; +}; +} // namespace CesiumGltf diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltf/ExtensionExtStructuralMetadataPropertyTable.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltf/ExtensionExtStructuralMetadataPropertyTable.h new file mode 100644 index 0000000000000000000000000000000000000000..004f3a206bcc9fbe86b2961cf3d9dcd52927d4f9 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltf/ExtensionExtStructuralMetadataPropertyTable.h @@ -0,0 +1,52 @@ +// This file was generated by generate-classes. +// DO NOT EDIT THIS FILE! +#pragma once + +#include "CesiumGltf/ExtensionExtStructuralMetadataPropertyTableProperty.h" +#include "CesiumGltf/Library.h" + +#include <CesiumUtility/ExtensibleObject.h> + +#include <cstdint> +#include <optional> +#include <string> +#include <unordered_map> + +namespace CesiumGltf { +/** + * @brief Properties conforming to a class, organized as property values stored + * in binary columnar arrays. + */ +struct CESIUMGLTF_API ExtensionExtStructuralMetadataPropertyTable final + : public CesiumUtility::ExtensibleObject { + static inline constexpr const char* TypeName = + "ExtensionExtStructuralMetadataPropertyTable"; + + /** + * @brief The name of the property table, e.g. for display purposes. + */ + std::optional<std::string> 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< + std::string, + CesiumGltf::ExtensionExtStructuralMetadataPropertyTableProperty> + properties; +}; +} // namespace CesiumGltf diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltf/ExtensionExtStructuralMetadataPropertyTableProperty.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltf/ExtensionExtStructuralMetadataPropertyTableProperty.h new file mode 100644 index 0000000000000000000000000000000000000000..049fae78bd10de836aafe05d0aa5f5af2ece4389 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltf/ExtensionExtStructuralMetadataPropertyTableProperty.h @@ -0,0 +1,136 @@ +// This file was generated by generate-classes. +// DO NOT EDIT THIS FILE! +#pragma once + +#include "CesiumGltf/Library.h" + +#include <CesiumUtility/ExtensibleObject.h> +#include <CesiumUtility/JsonValue.h> + +#include <cstdint> +#include <optional> + +namespace CesiumGltf { +/** + * @brief An array of binary property values. + */ +struct CESIUMGLTF_API ExtensionExtStructuralMetadataPropertyTableProperty final + : public CesiumUtility::ExtensibleObject { + static inline constexpr const char* TypeName = + "ExtensionExtStructuralMetadataPropertyTableProperty"; + + /** + * @brief Known values for The type of values in `arrayOffsets`. + */ + struct ArrayOffsetType { + inline static const std::string UINT8 = "UINT8"; + + inline static const std::string UINT16 = "UINT16"; + + inline static const std::string UINT32 = "UINT32"; + + inline static const std::string UINT64 = "UINT64"; + }; + + /** + * @brief Known values for The type of values in `stringOffsets`. + */ + struct StringOffsetType { + inline static const std::string UINT8 = "UINT8"; + + inline static const std::string UINT16 = "UINT16"; + + inline static const std::string UINT32 = "UINT32"; + + 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<CesiumUtility::JsonValue> 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<CesiumUtility::JsonValue> 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<CesiumUtility::JsonValue> 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<CesiumUtility::JsonValue> min; +}; +} // namespace CesiumGltf diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltf/ExtensionExtStructuralMetadataPropertyTexture.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltf/ExtensionExtStructuralMetadataPropertyTexture.h new file mode 100644 index 0000000000000000000000000000000000000000..2b1ab5c3263044f8c845a3cbf812f56ca7ae6d7e --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltf/ExtensionExtStructuralMetadataPropertyTexture.h @@ -0,0 +1,46 @@ +// This file was generated by generate-classes. +// DO NOT EDIT THIS FILE! +#pragma once + +#include "CesiumGltf/ExtensionExtStructuralMetadataPropertyTextureProperty.h" +#include "CesiumGltf/Library.h" + +#include <CesiumUtility/ExtensibleObject.h> + +#include <optional> +#include <string> +#include <unordered_map> + +namespace CesiumGltf { +/** + * @brief Properties conforming to a class, organized as property values stored + * in textures. + */ +struct CESIUMGLTF_API ExtensionExtStructuralMetadataPropertyTexture final + : public CesiumUtility::ExtensibleObject { + static inline constexpr const char* TypeName = + "ExtensionExtStructuralMetadataPropertyTexture"; + + /** + * @brief The name of the property texture, e.g. for display purposes. + */ + std::optional<std::string> 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< + std::string, + CesiumGltf::ExtensionExtStructuralMetadataPropertyTextureProperty> + properties; +}; +} // namespace CesiumGltf diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltf/ExtensionExtStructuralMetadataPropertyTextureProperty.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltf/ExtensionExtStructuralMetadataPropertyTextureProperty.h new file mode 100644 index 0000000000000000000000000000000000000000..faa50b1898197b228a194735307a5f0ab6f800d2 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltf/ExtensionExtStructuralMetadataPropertyTextureProperty.h @@ -0,0 +1,61 @@ +// This file was generated by generate-classes. +// DO NOT EDIT THIS FILE! +#pragma once + +#include "CesiumGltf/Library.h" +#include "CesiumGltf/TextureInfo.h" + +#include <CesiumUtility/JsonValue.h> + +#include <cstdint> +#include <optional> +#include <vector> + +namespace CesiumGltf { +/** + * @brief A texture containing property values. + */ +struct CESIUMGLTF_API ExtensionExtStructuralMetadataPropertyTextureProperty + final : public TextureInfo { + static inline constexpr const char* TypeName = + "ExtensionExtStructuralMetadataPropertyTextureProperty"; + + /** + * @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<int64_t> 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<CesiumUtility::JsonValue> 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<CesiumUtility::JsonValue> 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<CesiumUtility::JsonValue> 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<CesiumUtility::JsonValue> min; +}; +} // namespace CesiumGltf diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltf/ExtensionExtStructuralMetadataSchema.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltf/ExtensionExtStructuralMetadataSchema.h new file mode 100644 index 0000000000000000000000000000000000000000..8b92f94af62b8bfe4e19d694290f329de4573ac3 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltf/ExtensionExtStructuralMetadataSchema.h @@ -0,0 +1,64 @@ +// This file was generated by generate-classes. +// DO NOT EDIT THIS FILE! +#pragma once + +#include "CesiumGltf/ExtensionExtStructuralMetadataClass.h" +#include "CesiumGltf/ExtensionExtStructuralMetadataEnum.h" +#include "CesiumGltf/Library.h" + +#include <CesiumUtility/ExtensibleObject.h> + +#include <optional> +#include <string> +#include <unordered_map> + +namespace CesiumGltf { +/** + * @brief An object defining classes and enums. + */ +struct CESIUMGLTF_API ExtensionExtStructuralMetadataSchema final + : public CesiumUtility::ExtensibleObject { + static inline constexpr const char* TypeName = + "ExtensionExtStructuralMetadataSchema"; + + /** + * @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<std::string> name; + + /** + * @brief The description of the schema. + */ + std::optional<std::string> description; + + /** + * @brief Application-specific version of the schema. + */ + std::optional<std::string> 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< + std::string, + CesiumGltf::ExtensionExtStructuralMetadataClass> + 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<std::string, CesiumGltf::ExtensionExtStructuralMetadataEnum> + enums; +}; +} // 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 0000000000000000000000000000000000000000..a2d67aa4454ddd7ef99f2d342e928dc8bdbc264a --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltf/ExtensionKhrDracoMeshCompression.h @@ -0,0 +1,34 @@ +// This file was generated by generate-classes. +// DO NOT EDIT THIS FILE! +#pragma once + +#include "CesiumGltf/Library.h" + +#include <CesiumUtility/ExtensibleObject.h> + +#include <cstdint> +#include <unordered_map> + +namespace CesiumGltf { +/** + * @brief KHR_draco_mesh_compression extension + */ +struct CESIUMGLTF_API ExtensionKhrDracoMeshCompression final + : public CesiumUtility::ExtensibleObject { + static inline constexpr const char* TypeName = + "ExtensionKhrDracoMeshCompression"; + static inline 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<std::string, int32_t> attributes; +}; +} // 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 0000000000000000000000000000000000000000..5b512e01d2b0d544575357f2a4cc73b3478ee8ea --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltf/ExtensionKhrMaterialsUnlit.h @@ -0,0 +1,18 @@ +// This file was generated by generate-classes. +// DO NOT EDIT THIS FILE! +#pragma once + +#include "CesiumGltf/Library.h" + +#include <CesiumUtility/ExtensibleObject.h> + +namespace CesiumGltf { +/** + * @brief glTF extension that defines the unlit material model. + */ +struct CESIUMGLTF_API ExtensionKhrMaterialsUnlit final + : public CesiumUtility::ExtensibleObject { + static inline constexpr const char* TypeName = "ExtensionKhrMaterialsUnlit"; + static inline constexpr const char* ExtensionName = "KHR_materials_unlit"; +}; +} // 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 0000000000000000000000000000000000000000..21d67df69f04c0f24eed02c7c7cc1bc02fe2f1f0 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltf/ExtensionKhrTextureBasisu.h @@ -0,0 +1,27 @@ +// This file was generated by generate-classes. +// DO NOT EDIT THIS FILE! +#pragma once + +#include "CesiumGltf/Library.h" + +#include <CesiumUtility/ExtensibleObject.h> + +#include <cstdint> + +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 { + static inline constexpr const char* TypeName = "ExtensionKhrTextureBasisu"; + static inline 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; +}; +} // 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 0000000000000000000000000000000000000000..059a839898f50d62871820b0c0eaf6765506699d --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltf/ExtensionKhrTextureTransform.h @@ -0,0 +1,46 @@ +// This file was generated by generate-classes. +// DO NOT EDIT THIS FILE! +#pragma once + +#include "CesiumGltf/Library.h" + +#include <CesiumUtility/ExtensibleObject.h> + +#include <cstdint> +#include <optional> +#include <vector> + +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 { + static inline constexpr const char* TypeName = "ExtensionKhrTextureTransform"; + static inline constexpr const char* ExtensionName = "KHR_texture_transform"; + + /** + * @brief The offset of the UV coordinate origin as a factor of the texture + * dimensions. + */ + std::vector<double> 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<double> scale = {1, 1}; + + /** + * @brief Overrides the textureInfo texCoord value if supplied, and if this + * extension is supported. + */ + std::optional<int64_t> texCoord; +}; +} // namespace CesiumGltf diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltf/ExtensionMeshPrimitiveExtFeatureMetadata.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltf/ExtensionMeshPrimitiveExtFeatureMetadata.h new file mode 100644 index 0000000000000000000000000000000000000000..5cf35aacbb46a749a17c21ac0fcbe2bd6c0c90cd --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltf/ExtensionMeshPrimitiveExtFeatureMetadata.h @@ -0,0 +1,43 @@ +// This file was generated by generate-classes. +// DO NOT EDIT THIS FILE! +#pragma once + +#include "CesiumGltf/FeatureIDAttribute.h" +#include "CesiumGltf/FeatureIDTexture.h" +#include "CesiumGltf/Library.h" + +#include <CesiumUtility/ExtensibleObject.h> + +#include <string> +#include <vector> + +namespace CesiumGltf { +/** + * @brief `EXT_feature_metadata extension` for a primitive in a glTF model, to + * associate it with the root `EXT_feature_metadata` object. + */ +struct CESIUMGLTF_API ExtensionMeshPrimitiveExtFeatureMetadata final + : public CesiumUtility::ExtensibleObject { + static inline constexpr const char* TypeName = + "ExtensionMeshPrimitiveExtFeatureMetadata"; + static inline constexpr const char* ExtensionName = "EXT_feature_metadata"; + + /** + * @brief An array of objects mapping per-vertex feature IDs to a feature + * table. + */ + std::vector<CesiumGltf::FeatureIDAttribute> featureIdAttributes; + + /** + * @brief An array of objects mapping per-texel feature IDs to a feature + * table. + */ + std::vector<CesiumGltf::FeatureIDTexture> featureIdTextures; + + /** + * @brief An array of IDs of feature textures from the root + * `EXT_feature_metadata` object. + */ + std::vector<std::string> featureTextures; +}; +} // 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 0000000000000000000000000000000000000000..f137dc25d6a60963fe39a83228d1193bff40ee09 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltf/ExtensionMeshPrimitiveExtStructuralMetadata.h @@ -0,0 +1,34 @@ +// This file was generated by generate-classes. +// DO NOT EDIT THIS FILE! +#pragma once + +#include "CesiumGltf/Library.h" + +#include <CesiumUtility/ExtensibleObject.h> + +#include <cstdint> +#include <vector> + +namespace CesiumGltf { +/** + * @brief Structural metadata about a glTF primitive. + */ +struct CESIUMGLTF_API ExtensionMeshPrimitiveExtStructuralMetadata final + : public CesiumUtility::ExtensibleObject { + static inline constexpr const char* TypeName = + "ExtensionMeshPrimitiveExtStructuralMetadata"; + static inline constexpr const char* ExtensionName = "EXT_structural_metadata"; + + /** + * @brief An array of indexes of property textures in the root + * `EXT_structural_metadata` object. + */ + std::vector<int64_t> propertyTextures; + + /** + * @brief An array of indexes of property attributes in the root + * `EXT_structural_metadata` object. + */ + std::vector<int64_t> propertyAttributes; +}; +} // namespace CesiumGltf diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltf/ExtensionModelExtFeatureMetadata.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltf/ExtensionModelExtFeatureMetadata.h new file mode 100644 index 0000000000000000000000000000000000000000..7fb51dc7c4005b936c445481fa03964857b6de6d --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltf/ExtensionModelExtFeatureMetadata.h @@ -0,0 +1,54 @@ +// This file was generated by generate-classes. +// DO NOT EDIT THIS FILE! +#pragma once + +#include "CesiumGltf/FeatureTable.h" +#include "CesiumGltf/FeatureTexture.h" +#include "CesiumGltf/Library.h" +#include "CesiumGltf/Schema.h" +#include "CesiumGltf/Statistics.h" + +#include <CesiumUtility/ExtensibleObject.h> + +#include <optional> +#include <string> +#include <unordered_map> + +namespace CesiumGltf { +/** + * @brief glTF extension that assigns metadata to features in a model. + */ +struct CESIUMGLTF_API ExtensionModelExtFeatureMetadata final + : public CesiumUtility::ExtensibleObject { + static inline constexpr const char* TypeName = + "ExtensionModelExtFeatureMetadata"; + static inline constexpr const char* ExtensionName = "EXT_feature_metadata"; + + /** + * @brief An object defining classes and enums. + */ + std::optional<CesiumGltf::Schema> schema; + + /** + * @brief The URI (or IRI) of the external schema file. + */ + std::optional<std::string> schemaUri; + + /** + * @brief An object containing statistics about features. + */ + std::optional<CesiumGltf::Statistics> statistics; + + /** + * @brief A dictionary, where each key is a feature table ID and each value is + * an object defining the feature table. + */ + std::unordered_map<std::string, CesiumGltf::FeatureTable> featureTables; + + /** + * @brief A dictionary, where each key is a feature texture ID and each value + * is an object defining the feature texture. + */ + std::unordered_map<std::string, CesiumGltf::FeatureTexture> featureTextures; +}; +} // 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 0000000000000000000000000000000000000000..270019b92ae1a1dd1bbd846a41fd369d963d32d3 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltf/ExtensionModelExtStructuralMetadata.h @@ -0,0 +1,59 @@ +// This file was generated by generate-classes. +// DO NOT EDIT THIS FILE! +#pragma once + +#include "CesiumGltf/ExtensionExtStructuralMetadataPropertyAttribute.h" +#include "CesiumGltf/ExtensionExtStructuralMetadataPropertyTable.h" +#include "CesiumGltf/ExtensionExtStructuralMetadataPropertyTexture.h" +#include "CesiumGltf/ExtensionExtStructuralMetadataSchema.h" +#include "CesiumGltf/Library.h" + +#include <CesiumUtility/ExtensibleObject.h> + +#include <optional> +#include <string> +#include <vector> + +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 { + static inline constexpr const char* TypeName = + "ExtensionModelExtStructuralMetadata"; + static inline constexpr const char* ExtensionName = "EXT_structural_metadata"; + + /** + * @brief An object defining classes and enums. + */ + std::optional<CesiumGltf::ExtensionExtStructuralMetadataSchema> schema; + + /** + * @brief The URI (or IRI) of the external schema file. + */ + std::optional<std::string> schemaUri; + + /** + * @brief An array of property table definitions, which may be referenced by + * index. + */ + std::vector<CesiumGltf::ExtensionExtStructuralMetadataPropertyTable> + propertyTables; + + /** + * @brief An array of property texture definitions, which may be referenced by + * index. + */ + std::vector<CesiumGltf::ExtensionExtStructuralMetadataPropertyTexture> + propertyTextures; + + /** + * @brief An array of property attribute definitions, which may be referenced + * by index. + */ + std::vector<CesiumGltf::ExtensionExtStructuralMetadataPropertyAttribute> + propertyAttributes; +}; +} // 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 0000000000000000000000000000000000000000..1d86be27667571a5c7db53ea6e997143e072c7c3 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltf/ExtensionModelMaxarMeshVariants.h @@ -0,0 +1,35 @@ +// This file was generated by generate-classes. +// DO NOT EDIT THIS FILE! +#pragma once + +#include "CesiumGltf/ExtensionModelMaxarMeshVariantsValue.h" +#include "CesiumGltf/Library.h" + +#include <CesiumUtility/ExtensibleObject.h> + +#include <cstdint> +#include <vector> + +namespace CesiumGltf { +/** + * @brief glTF extension that defines mesh variants for nodes + */ +struct CESIUMGLTF_API ExtensionModelMaxarMeshVariants final + : public CesiumUtility::ExtensibleObject { + static inline constexpr const char* TypeName = + "ExtensionModelMaxarMeshVariants"; + static inline 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<CesiumGltf::ExtensionModelMaxarMeshVariantsValue> variants; +}; +} // 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 0000000000000000000000000000000000000000..c0f3489a16fc917b1771d046f1ab7acfe80f7205 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltf/ExtensionModelMaxarMeshVariantsValue.h @@ -0,0 +1,24 @@ +// This file was generated by generate-classes. +// DO NOT EDIT THIS FILE! +#pragma once + +#include "CesiumGltf/Library.h" +#include "CesiumGltf/NamedObject.h" + +#include <string> + +namespace CesiumGltf { +/** + * @brief An object defining a valid mesh variant + */ +struct CESIUMGLTF_API ExtensionModelMaxarMeshVariantsValue final + : public CesiumGltf::NamedObject { + static inline constexpr const char* TypeName = + "ExtensionModelMaxarMeshVariantsValue"; + + /** + * @brief The name of the mesh variant + */ + std::string name; +}; +} // 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 0000000000000000000000000000000000000000..eb4822b610dee4e292c3c8fa9753d18b75434d53 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltf/ExtensionNodeMaxarMeshVariants.h @@ -0,0 +1,27 @@ +// This file was generated by generate-classes. +// DO NOT EDIT THIS FILE! +#pragma once + +#include "CesiumGltf/ExtensionNodeMaxarMeshVariantsMappingsValue.h" +#include "CesiumGltf/Library.h" + +#include <CesiumUtility/ExtensibleObject.h> + +#include <vector> + +namespace CesiumGltf { +/** + * @brief MAXAR_mesh_variants node extension + */ +struct CESIUMGLTF_API ExtensionNodeMaxarMeshVariants final + : public CesiumUtility::ExtensibleObject { + static inline constexpr const char* TypeName = + "ExtensionNodeMaxarMeshVariants"; + static inline constexpr const char* ExtensionName = "MAXAR_mesh_variants"; + + /** + * @brief A list of mesh to variant mappings + */ + std::vector<CesiumGltf::ExtensionNodeMaxarMeshVariantsMappingsValue> mappings; +}; +} // 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 0000000000000000000000000000000000000000..afd9a71467b004f117f71b29215ca7a12877a986 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltf/ExtensionNodeMaxarMeshVariantsMappingsValue.h @@ -0,0 +1,38 @@ +// This file was generated by generate-classes. +// DO NOT EDIT THIS FILE! +#pragma once + +#include "CesiumGltf/Library.h" + +#include <CesiumUtility/ExtensibleObject.h> + +#include <cstdint> +#include <optional> +#include <string> +#include <vector> + +namespace CesiumGltf { +/** + * @brief ExtensionNodeMaxarMeshVariants Mappings Value + */ +struct CESIUMGLTF_API ExtensionNodeMaxarMeshVariantsMappingsValue final + : public CesiumUtility::ExtensibleObject { + static inline constexpr const char* TypeName = + "ExtensionNodeMaxarMeshVariantsMappingsValue"; + + /** + * @brief An array of variant index values. + */ + std::vector<int32_t> 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<std::string> name; +}; +} // 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 0000000000000000000000000000000000000000..c9ee691e54e87e8e38b0485e21567576055542ce --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltf/ExtensionTextureWebp.h @@ -0,0 +1,25 @@ +// This file was generated by generate-classes. +// DO NOT EDIT THIS FILE! +#pragma once + +#include "CesiumGltf/Library.h" + +#include <CesiumUtility/ExtensibleObject.h> + +#include <cstdint> + +namespace CesiumGltf { +/** + * @brief glTF extension to specify textures using the WebP image format. + */ +struct CESIUMGLTF_API ExtensionTextureWebp final + : public CesiumUtility::ExtensibleObject { + static inline constexpr const char* TypeName = "ExtensionTextureWebp"; + static inline constexpr const char* ExtensionName = "EXT_texture_webp"; + + /** + * @brief The index of the images node which points to a WebP image. + */ + int32_t source = -1; +}; +} // namespace CesiumGltf diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltf/FeatureIDAttribute.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltf/FeatureIDAttribute.h new file mode 100644 index 0000000000000000000000000000000000000000..458be201986fee70d470cb34bab8c58738f068bd --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltf/FeatureIDAttribute.h @@ -0,0 +1,34 @@ +// This file was generated by generate-classes. +// DO NOT EDIT THIS FILE! +#pragma once + +#include "CesiumGltf/FeatureIDs.h" +#include "CesiumGltf/Library.h" + +#include <CesiumUtility/ExtensibleObject.h> + +#include <string> + +namespace CesiumGltf { +/** + * @brief An object mapping feature IDs to a feature table. + */ +struct CESIUMGLTF_API FeatureIDAttribute final + : public CesiumUtility::ExtensibleObject { + static inline constexpr const char* TypeName = "FeatureIDAttribute"; + + /** + * @brief The ID of the feature table in the model's root + * `EXT_feature_metadata.featureTables` dictionary. + */ + std::string featureTable; + + /** + * @brief An object describing feature IDs to be used as indices to property + * arrays in the feature table. Feature IDs must be whole numbers in the range + * `[0, count - 1]` (inclusive), where `count` is the total number of features + * in the feature table. + */ + CesiumGltf::FeatureIDs featureIds; +}; +} // 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 0000000000000000000000000000000000000000..27bc4a51f2aa00b7875d5d27d40adb90ac4ced7e --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltf/FeatureIDTexture.h @@ -0,0 +1,36 @@ +// This file was generated by generate-classes. +// DO NOT EDIT THIS FILE! +#pragma once + +#include "CesiumGltf/Library.h" +#include "CesiumGltf/TextureAccessor.h" + +#include <CesiumUtility/ExtensibleObject.h> + +#include <string> + +namespace CesiumGltf { +/** + * @brief An object describing a texture used for storing per-texel feature IDs. + */ +struct CESIUMGLTF_API FeatureIDTexture final + : public CesiumUtility::ExtensibleObject { + static inline constexpr const char* TypeName = "FeatureIDTexture"; + + /** + * @brief The ID of the feature table in the model's root + * `EXT_feature_metadata.featureTables` dictionary. + */ + std::string featureTable; + + /** + * @brief A description of the texture and channel to use for feature IDs. The + * `channels` property must have a single channel. Furthermore, feature IDs + * must be whole numbers in the range `[0, count - 1]` (inclusive), where + * `count` is the total number of features in the feature table. Texel values + * must be read as integers. Texture filtering should be disabled when + * fetching feature IDs. + */ + CesiumGltf::TextureAccessor featureIds; +}; +} // 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 0000000000000000000000000000000000000000..c3a29c02f1e390745e4b9ba7a8a8387d11fb0f0b --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltf/FeatureIDTextureView.h @@ -0,0 +1,141 @@ +#pragma once + +#include "CesiumGltf/FeatureIDTexture.h" +#include "CesiumGltf/Texture.h" +#include "CesiumGltf/TextureAccessor.h" +#include "Image.h" +#include "ImageCesium.h" +#include "Model.h" + +#include <algorithm> +#include <cassert> +#include <cmath> +#include <cstddef> +#include <cstdint> +#include <string> + +namespace CesiumGltf { + +/** + * @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. + */ + InvalidUninitialized, + + /** + * @brief This feature id texture has a texture index that doesn't exist in + * the glTF. + */ + InvalidTextureIndex, + + /** + * @brief This feature id texture has an image index that doesn't exist in + * the glTF. + */ + InvalidImageIndex, + + /** + * @brief This feature id texture has an unknown image channel. + */ + InvalidChannel, + + /** + * @brief This feature id texture has an empty image. + */ + InvalidEmptyImage +}; + +/** + * @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: + /** + * @brief Constructs an uninitialized and invalid view. + */ + FeatureIDTextureView() noexcept; + + /** + * @brief Construct a view of the data specified by a + * {@link FeatureIDTexture}. + * + * @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. + */ + FeatureIDTextureView( + const Model& model, + const FeatureIDTexture& featureIDTexture) noexcept; + + /** + * @brief Get the Feature ID for the given texture coordinates. + * + * Will return -1 when the status is not Valid. + * + * @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 { return _status; } + + /** + * @brief Get the actual feature ID texture. + * + * This will be nullptr if the feature id texture view runs into problems + * during construction. + */ + const ImageCesium* getImage() const { return _pImage; } + + /** + * @brief Get the channel index that this feature ID texture uses. + */ + int32_t getChannel() const { return _channel; } + + /** + * @brief Get the name of the feature table associated with this feature ID + * texture. + */ + const std::string& getFeatureTableName() const { + return this->_featureTableName; + } + + /** + * @brief Get the texture coordinate attribute index for this feature id + * texture. + */ + int64_t getTextureCoordinateAttributeId() const { + return this->_textureCoordinateAttributeId; + } + +private: + const ImageCesium* _pImage; + int32_t _channel; + int64_t _textureCoordinateAttributeId; + std::string _featureTableName; + FeatureIDTextureViewStatus _status; +}; + +} // namespace CesiumGltf \ No newline at end of file diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltf/FeatureIDs.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltf/FeatureIDs.h new file mode 100644 index 0000000000000000000000000000000000000000..402625edc46ee736b0780db841da441e117beb6c --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltf/FeatureIDs.h @@ -0,0 +1,42 @@ +// This file was generated by generate-classes. +// DO NOT EDIT THIS FILE! +#pragma once + +#include "CesiumGltf/Library.h" + +#include <CesiumUtility/ExtensibleObject.h> + +#include <cstdint> +#include <optional> +#include <string> + +namespace CesiumGltf { +/** + * @brief Feature IDs to be used as indices to property arrays in the feature + * table. + */ +struct CESIUMGLTF_API FeatureIDs final + : public CesiumUtility::ExtensibleObject { + static inline constexpr const char* TypeName = "FeatureIDs"; + + /** + * @brief The name of the attribute containing feature IDs. + */ + std::optional<std::string> attribute; + + /** + * @brief Sets a constant feature ID when the attribute property is omitted. + */ + int64_t constant = 0; + + /** + * @brief The rate at which feature IDs increment. If `divisor` is 0 then + * `constant` is used. If `divisor` is non-zero the feature ID increments once + * per `divisor` sets of elements, starting at `constant`. For example, if + * `constant` is 0 and `divisor` is 1 the feature IDs are [0, 1, 2, ...]; if + * `constant` is 2 and `divisor` is 3 the feature IDs are [2, 2, 2, 3, 3, 3, + * 4, 4, 4, ...] + */ + int64_t divisor = 0; +}; +} // namespace CesiumGltf diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltf/FeatureTable.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltf/FeatureTable.h new file mode 100644 index 0000000000000000000000000000000000000000..410f8b11a31b449c724dc8b10d06a028363c40fc --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltf/FeatureTable.h @@ -0,0 +1,44 @@ +// This file was generated by generate-classes. +// DO NOT EDIT THIS FILE! +#pragma once + +#include "CesiumGltf/FeatureTableProperty.h" +#include "CesiumGltf/Library.h" + +#include <CesiumUtility/ExtensibleObject.h> + +#include <cstdint> +#include <optional> +#include <string> +#include <unordered_map> + +namespace CesiumGltf { +/** + * @brief A feature table defined by a class and property values stored in + * arrays. + */ +struct CESIUMGLTF_API FeatureTable final + : public CesiumUtility::ExtensibleObject { + static inline constexpr const char* TypeName = "FeatureTable"; + + /** + * @brief The class that property values conform to. The value must be a class + * ID declared in the `classes` dictionary. + */ + std::optional<std::string> classProperty; + + /** + * @brief The number of features, as well as 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. Optional properties may be excluded from this + * dictionary. + */ + std::unordered_map<std::string, CesiumGltf::FeatureTableProperty> properties; +}; +} // namespace CesiumGltf diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltf/FeatureTableProperty.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltf/FeatureTableProperty.h new file mode 100644 index 0000000000000000000000000000000000000000..7ca4ffeaaa2ef6bf1c4b66f61fb7075ececf30de --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltf/FeatureTableProperty.h @@ -0,0 +1,89 @@ +// This file was generated by generate-classes. +// DO NOT EDIT THIS FILE! +#pragma once + +#include "CesiumGltf/Library.h" + +#include <CesiumUtility/ExtensibleObject.h> + +#include <cstdint> + +namespace CesiumGltf { +/** + * @brief An array of binary property values. + */ +struct CESIUMGLTF_API FeatureTableProperty final + : public CesiumUtility::ExtensibleObject { + static inline constexpr const char* TypeName = "FeatureTableProperty"; + + /** + * @brief Known values for The type of values in `arrayOffsetBufferView` and + * `stringOffsetBufferView`. + */ + struct OffsetType { + inline static const std::string UINT8 = "UINT8"; + + inline static const std::string UINT16 = "UINT16"; + + inline static const std::string UINT32 = "UINT32"; + + 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 bitfield. When `type` is + * `STRING` values are stored as byte sequences and decoded as UTF-8 strings. + * When `type` is a numeric type values are stored as the provided `type`. + * When `type` is `ENUM` values are stored as the enum's `valueType`. Each + * enum value in the buffer must match one of the allowed values in the enum + * definition. When `type` is `ARRAY` elements are packed tightly together and + * the data type is based on the `componentType` following the same rules as + * above. `arrayOffsetBufferView` is required for variable-size arrays and + * `stringOffsetBufferView` is required for strings (for variable-length + * arrays of strings, both are required). The buffer view `byteOffset` must be + * aligned to a multiple of 8 bytes. If the buffer view's `buffer` is the + * GLB-stored `BIN` chunk, the byte offset is measured relative to the + * beginning of the GLB. Otherwise, it is measured relative to the beginning + * of the buffer. + */ + int32_t bufferView = -1; + + /** + * @brief The type of values in `arrayOffsetBufferView` and + * `stringOffsetBufferView`. + * + * Known values are defined in {@link OffsetType}. + * + */ + std::string offsetType = OffsetType::UINT32; + + /** + * @brief The index of the buffer view containing offsets for variable-length + * arrays. The number of offsets is equal to the feature 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 current offset and the subsequent + * offset. If `componentType` is `STRING` the offsets index into the string + * offsets array (stored in `stringOffsetBufferView`), otherwise they index + * into the property array (stored in `bufferView`). The data type of these + * offsets is determined by `offsetType`. The buffer view `byteOffset` must be + * aligned to a multiple of 8 bytes in the same manner as the main + * `bufferView` + */ + int32_t arrayOffsetBufferView = -1; + + /** + * @brief The index of the buffer view containing offsets for strings. The + * number of offsets is equal to the number of string components plus one. The + * offsets represent the byte offsets of each string in the main `bufferView`, + * with the last offset representing the byte offset after the last string. + * The string byte length is computed using the difference between the current + * offset and the subsequent offset. The data type of these offsets is + * determined by `offsetType`. The buffer view `byteOffset` must be aligned to + * a multiple of 8 bytes in the same manner as the main `bufferView`. + */ + int32_t stringOffsetBufferView = -1; +}; +} // namespace CesiumGltf diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltf/FeatureTexture.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltf/FeatureTexture.h new file mode 100644 index 0000000000000000000000000000000000000000..fe9666e1826766e8874a0aac8037455334714f5c --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltf/FeatureTexture.h @@ -0,0 +1,36 @@ +// This file was generated by generate-classes. +// DO NOT EDIT THIS FILE! +#pragma once + +#include "CesiumGltf/Library.h" +#include "CesiumGltf/TextureAccessor.h" + +#include <CesiumUtility/ExtensibleObject.h> + +#include <string> +#include <unordered_map> + +namespace CesiumGltf { +/** + * @brief Features whose property values are stored directly in texture + * channels. This is not to be confused with feature ID textures which store + * feature IDs for use with a feature table. + */ +struct CESIUMGLTF_API FeatureTexture final + : public CesiumUtility::ExtensibleObject { + static inline constexpr const char* TypeName = "FeatureTexture"; + + /** + * @brief The class this feature texture conforms 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 describes the texture + * channels containing property values. + */ + std::unordered_map<std::string, CesiumGltf::TextureAccessor> properties; +}; +} // namespace CesiumGltf diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltf/FeatureTexturePropertyView.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltf/FeatureTexturePropertyView.h new file mode 100644 index 0000000000000000000000000000000000000000..bbe87a546cbed12e802dc24c825b25afa5286901 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltf/FeatureTexturePropertyView.h @@ -0,0 +1,253 @@ +#pragma once + +#include "CesiumGltf/ClassProperty.h" +#include "CesiumGltf/ExtensionModelExtFeatureMetadata.h" +#include "CesiumGltf/FeatureTexture.h" +#include "CesiumGltf/Sampler.h" +#include "CesiumGltf/Texture.h" +#include "CesiumGltf/TextureAccessor.h" +#include "CesiumGltf/TextureInfo.h" +#include "Image.h" +#include "ImageCesium.h" +#include "Model.h" + +#include <cassert> +#include <cstdint> +#include <variant> + +namespace CesiumGltf { + +/** + * @brief Indicates the status of a feature texture property view. + * + * The {@link FeatureTexturePropertyView} constructor always completes + * successfully. However it may not always reflect the actual content of the + * corresponding feature texture property. This enumeration provides the reason. + */ +enum class FeatureTexturePropertyViewStatus { + /** + * @brief This view is valid and ready to use. + */ + Valid, + + /** + * @brief This view has not been initialized. + */ + InvalidUninitialized, + + /** + * @brief This feature texture property has a texture index that does not + * exist in the glTF. + */ + InvalidTextureIndex, + + /** + * @brief This feature texture property has a texture sampler index that does + * not exist in the glTF. + */ + InvalidTextureSamplerIndex, + + /** + * @brief This feature texture property has an image index that does not + * exist in the glTF. + */ + InvalidImageIndex, + + /** + * @brief This feature texture property points to an empty image. + */ + InvalidEmptyImage, + + /** + * @brief This feature texture property has an invalid channels string. + */ + InvalidChannelsString +}; + +/** + * @brief The supported component types that can exist in feature id textures. + */ +enum class FeatureTexturePropertyComponentType { + Uint8 + // TODO: add more types. Currently this is the only one outputted by stb, + // so change stb call to output more of the original types. +}; + +/** + * @brief Specifies which channel each component exists in or -1 if the channel + * isn't present. This can be used to un-swizzle pixel data. + */ +struct FeatureTexturePropertyChannelOffsets { + int32_t r = -1; + int32_t g = -1; + int32_t b = -1; + int32_t a = -1; +}; + +/** + * @brief The feature texture property value for a pixel. This will contain + * four channels of the specified type. + * + * Only the first n components will be valid, where n is the number of channels + * in this feature texture property. + * + * @tparam T The component type, must correspond to a valid + * {@link FeatureTexturePropertyComponentType}. + */ +template <typename T> struct FeatureTexturePropertyValue { T components[4]; }; + +/** + * @brief A view of the data specified by a property from a + * {@link FeatureTexture}. + * + * Provides utilities to sample the feature texture property using texture + * coordinates. + */ +class FeatureTexturePropertyView { +public: + /** + * @brief Construct an uninitialized, invalid view. + */ + FeatureTexturePropertyView() noexcept; + + /** + * @brief Construct a view of the data specified by a feature texture + * property. + * + * @param model The glTF in which to look for the data specified by the + * feature texture property. + * @param classProperty The property description. + * @param textureAccessor The texture accessor for this property. + */ + FeatureTexturePropertyView( + const Model& model, + const ClassProperty& classProperty, + const TextureAccessor& textureAccessor) noexcept; + + /** + * @brief Get the property for the given texture coordinates. + * + * Will return -1s when the status is not Valid or when the templated + * component type doesn't match the image's channel byte-size. + * + * @tparam T The component type to use when interpreting the channels of the + * property's pixel value. + * @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 property at the nearest pixel to the texture coordinates. + */ + template <typename T> + FeatureTexturePropertyValue<T> + getProperty(double u, double v) const noexcept { + if (this->_status != FeatureTexturePropertyViewStatus::Valid || + sizeof(T) != this->_pImage->bytesPerChannel) { + FeatureTexturePropertyValue<T> property; + property.components[0] = -1; + property.components[1] = -1; + property.components[2] = -1; + property.components[3] = -1; + return property; + } + + // TODO: actually use the sampler?? + int64_t x = std::clamp( + std::llround(u * this->_pImage->width), + 0LL, + (long long)this->_pImage->width); + int64_t y = std::clamp( + std::llround(v * this->_pImage->height), + 0LL, + (long long)this->_pImage->height); + + int64_t pixelOffset = this->_pImage->bytesPerChannel * + this->_pImage->channels * + (y * this->_pImage->width + x); + const T* pRedChannel = reinterpret_cast<const T*>( + this->_pImage->pixelData.data() + pixelOffset); + + FeatureTexturePropertyValue<T> property; + property.components[0] = *(pRedChannel + this->_channelOffsets.r); + property.components[1] = *(pRedChannel + this->_channelOffsets.g); + property.components[2] = *(pRedChannel + this->_channelOffsets.b); + property.components[3] = *(pRedChannel + this->_channelOffsets.a); + + return property; + } + + /** + * @brief Get the status of this view. + * + * If invalid, it will not be safe to sample feature ids from this view. + */ + FeatureTexturePropertyViewStatus status() const noexcept { + return this->_status; + } + + /** + * @brief Get the component type for this property. + */ + FeatureTexturePropertyComponentType getPropertyType() const noexcept { + return this->_type; + } + + /** + * @brief Get the component count for this property. + * + * This is also how many channels a pixel value for this property will use. + */ + int64_t getComponentCount() const noexcept { return this->_componentCount; } + + /** + * @brief Get the texture coordinate attribute index for this property. + */ + int64_t getTextureCoordinateAttributeId() const noexcept { + return this->_textureCoordinateAttributeId; + } + + /** + * @brief Whether the component type for this property should be normalized. + */ + bool isNormalized() const noexcept { return this->_normalized; } + + /** + * @brief Get the image containing this property's data. + * + * This will be nullptr if the feature texture property view runs into + * problems during construction. + */ + const ImageCesium* getImage() const noexcept { return this->_pImage; } + + /** + * @brief Get the swizzle string for this texture's channels. Used to + * determine which channel represents red, green, blue, and alpha + * respectively. + */ + const std::string& getSwizzle() const noexcept { + const static std::string empty_str = ""; + return this->_pSwizzle ? *this->_pSwizzle : empty_str; + } + + /** + * @brief Get the {@link FeatureTexturePropertyChannelOffsets} that specifies + * how to un-swizzle this property's pixel values. + */ + const FeatureTexturePropertyChannelOffsets& + getChannelOffsets() const noexcept { + return this->_channelOffsets; + } + +private: + const Sampler* _pSampler; + const ImageCesium* _pImage; + const ClassProperty* _pClassProperty; + const std::string* _pSwizzle; + int64_t _textureCoordinateAttributeId; + FeatureTexturePropertyViewStatus _status; + FeatureTexturePropertyChannelOffsets _channelOffsets; + FeatureTexturePropertyComponentType _type; + int64_t _componentCount; + bool _normalized; +}; +} // namespace CesiumGltf \ No newline at end of file diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltf/FeatureTextureView.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltf/FeatureTextureView.h new file mode 100644 index 0000000000000000000000000000000000000000..8b6410579cec932fde6f2cc58d7f2e41cf259c29 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltf/FeatureTextureView.h @@ -0,0 +1,110 @@ +#pragma once + +#include "CesiumGltf/Class.h" +#include "CesiumGltf/ClassProperty.h" +#include "CesiumGltf/ExtensionModelExtFeatureMetadata.h" +#include "CesiumGltf/FeatureTexture.h" +#include "CesiumGltf/FeatureTexturePropertyView.h" +#include "CesiumGltf/Texture.h" +#include "CesiumGltf/TextureAccessor.h" +#include "Image.h" +#include "ImageCesium.h" +#include "Model.h" + +namespace CesiumGltf { + +/** + * @brief Indicates the status of a feature texture view. + * + * The {@link FeatureTextureView} constructor always completes successfully. + * However it may not always reflect the actual content of the + * {@link FeatureTexture}. This enumeration provides the reason. + */ +enum class FeatureTextureViewStatus { + /** + * @brief This feature texture view is valid and ready to use. + */ + Valid, + + /** + * @brief This feature texture view is not initialized. + */ + InvalidUninitialized, + + /** + * @brief The glTF is missing the EXT_feature_metadata extension. + */ + InvalidMissingMetadataExtension, + + /** + * @brief The glTF EXT_feature_metadata extension doesn't contain a schema. + */ + InvalidMissingSchema, + + /** + * @brief The feature texture's specified class could not be found in the + * extension. + * + */ + InvalidClassNotFound, + + /** + * @brief A property name specified in the feature texture could not be found + * in the class. + */ + InvalidClassPropertyNotFound, + + /** + * @brief A property view for one of this feature texture's properties failed + * to initialize successfully. Look for the invalid property view's status to + * find why it failed. + */ + InvalidPropertyViewStatus +}; + +/** + * @brief A view on the {@link FeatureTexture}. + * + * Provides access to views on the feature texture properties. + */ +class FeatureTextureView { +public: + /** + * @brief Construct an uninitialized, invalid feature texture view. + */ + FeatureTextureView() noexcept; + + /** + * @brief Construct a view for the feature texture. + * + * @param model The glTF in which to look for the feature texture's data. + * @param featureTexture The feature texture to create a view for. + */ + FeatureTextureView( + const Model& model, + const FeatureTexture& featureTexture) noexcept; + + /** + * @brief Gets the status of this feature texture view. + * + * Indicates whether the view accurately reflects the feature texture's data, + * or whether an error occurred. + */ + FeatureTextureViewStatus status() const noexcept { return this->_status; } + + /** + * @brief Get the views for this feature texture's properties. + */ + const std::unordered_map<std::string, FeatureTexturePropertyView>& + getProperties() const noexcept { + return this->_propertyViews; + } + +private: + const Model* _pModel; + const FeatureTexture* _pFeatureTexture; + const Class* _pClass; + std::unordered_map<std::string, FeatureTexturePropertyView> _propertyViews; + FeatureTextureViewStatus _status; +}; +} // namespace CesiumGltf \ No newline at end of file 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 0000000000000000000000000000000000000000..8ddfa19beff70aa7056c3f9a065748280f73b231 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltf/Image.h @@ -0,0 +1,16 @@ +#pragma once + +#include "CesiumGltf/ImageCesium.h" +#include "CesiumGltf/ImageSpec.h" +#include "CesiumGltf/Library.h" + +namespace CesiumGltf { +/** @copydoc ImageSpec */ +struct CESIUMGLTF_API Image final : public ImageSpec { + /** + * @brief Holds properties that are specific to the glTF loader rather than + * part of the glTF spec. + */ + ImageCesium cesium; +}; +} // namespace CesiumGltf diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltf/ImageCesium.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltf/ImageCesium.h new file mode 100644 index 0000000000000000000000000000000000000000..7a798a9dd8947bcc402314d256508467a384e512 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltf/ImageCesium.h @@ -0,0 +1,99 @@ +#pragma once + +#include "CesiumGltf/Ktx2TranscodeTargets.h" +#include "CesiumGltf/Library.h" + +#include <cstddef> +#include <cstdint> +#include <optional> +#include <vector> + +namespace CesiumGltf { + +/** + * @brief The byte range within a buffer where this mip exists. + */ +struct CESIUMGLTF_API ImageCesiumMipPosition { + /** + * @brief The byte index where this mip begins. + */ + size_t byteOffset; + + /** + * @brief The size in bytes of this mip. + */ + size_t byteSize; +}; + +/** + * @brief Holds {@link Image} properties that are specific to the glTF loader + * rather than part of the glTF spec. + */ +struct CESIUMGLTF_API ImageCesium final { + /** + * @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<ImageCesiumMipPosition> 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 mipOffsets 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<std::byte> pixelData; +}; +} // 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 0000000000000000000000000000000000000000..b8ec52d2c1f1d4f1639bb543b680893b1eef18a1 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltf/ImageSpec.h @@ -0,0 +1,61 @@ +// This file was generated by generate-classes. +// DO NOT EDIT THIS FILE! +#pragma once + +#include "CesiumGltf/Library.h" +#include "CesiumGltf/NamedObject.h" + +#include <cstdint> +#include <optional> +#include <string> + +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 { + static inline 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 { + inline static const std::string image_jpeg = "image/jpeg"; + + 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<std::string> 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<std::string> 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; + +private: + /** + * @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/Ktx2TranscodeTargets.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltf/Ktx2TranscodeTargets.h new file mode 100644 index 0000000000000000000000000000000000000000..4d0c7057cac474b5200806cb7a842564c5516c8b --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltf/Ktx2TranscodeTargets.h @@ -0,0 +1,129 @@ +#pragma once + +#include "CesiumGltf/Library.h" + +namespace CesiumGltf { + +/** + * @brief Supported gpu compressed pixel formats. + */ +enum class CESIUMGLTF_API GpuCompressedPixelFormat { + NONE, + ETC1_RGB, + ETC2_RGBA, + BC1_RGB, + BC3_RGBA, + BC4_R, + BC5_RG, + BC7_RGBA, + PVRTC1_4_RGB, + PVRTC1_4_RGBA, + ASTC_4x4_RGBA, + PVRTC2_4_RGB, + PVRTC2_4_RGBA, + ETC2_EAC_R11, + 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 { + bool ETC1_RGB{}; + bool ETC2_RGBA{}; + bool BC1_RGB{}; + bool BC3_RGBA{}; + bool BC4_R{}; + bool BC5_RG{}; + bool BC7_RGBA{}; + bool PVRTC1_4_RGB{}; + bool PVRTC1_4_RGBA{}; + bool ASTC_4x4_RGBA{}; + bool PVRTC2_4_RGB{}; + bool PVRTC2_4_RGBA{}; + bool ETC2_EAC_R11{}; + 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 0000000000000000000000000000000000000000..517fa6fad256ad75d1b02d15edd6341b4849f0ac --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltf/Library.h @@ -0,0 +1,16 @@ +#pragma once + +/** + * @brief Classes for working with [glTF](https://www.khronos.org/gltf/) models. + */ +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 0000000000000000000000000000000000000000..5fa3c20353cb0d0b78a2e3d39e6f9dcf77e922c7 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltf/Material.h @@ -0,0 +1,116 @@ +// This file was generated by generate-classes. +// DO NOT EDIT THIS FILE! +#pragma once + +#include "CesiumGltf/Library.h" +#include "CesiumGltf/MaterialNormalTextureInfo.h" +#include "CesiumGltf/MaterialOcclusionTextureInfo.h" +#include "CesiumGltf/MaterialPBRMetallicRoughness.h" +#include "CesiumGltf/NamedObject.h" +#include "CesiumGltf/TextureInfo.h" + +#include <optional> +#include <vector> + +namespace CesiumGltf { +/** + * @brief The material appearance of a primitive. + */ +struct CESIUMGLTF_API Material final : public CesiumGltf::NamedObject { + static inline constexpr const char* TypeName = "Material"; + + /** + * @brief Known values for The alpha rendering mode of the material. + */ + struct AlphaMode { + inline static const std::string OPAQUE = "OPAQUE"; + + inline static const std::string MASK = "MASK"; + + 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<CesiumGltf::MaterialPBRMetallicRoughness> 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<CesiumGltf::MaterialNormalTextureInfo> 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<CesiumGltf::MaterialOcclusionTextureInfo> 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<CesiumGltf::TextureInfo> 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<double> 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; +}; +} // 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 0000000000000000000000000000000000000000..1bcf74477644d30862868dfbb8b3f5f96c528897 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltf/MaterialNormalTextureInfo.h @@ -0,0 +1,26 @@ +// This file was generated by generate-classes. +// DO NOT EDIT THIS FILE! +#pragma once + +#include "CesiumGltf/Library.h" +#include "CesiumGltf/TextureInfo.h" + +namespace CesiumGltf { +/** + * @brief Material Normal Texture Info + */ +struct CESIUMGLTF_API MaterialNormalTextureInfo final : public TextureInfo { + static inline 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((<sampled normal texture value> * 2.0 - 1.0) * + * vec3(<normal scale>, <normal scale>, 1.0))`. + */ + double scale = 1; +}; +} // 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 0000000000000000000000000000000000000000..0800082d000f2960d9594d05e7b0bee193e4458a --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltf/MaterialOcclusionTextureInfo.h @@ -0,0 +1,25 @@ +// This file was generated by generate-classes. +// DO NOT EDIT THIS FILE! +#pragma once + +#include "CesiumGltf/Library.h" +#include "CesiumGltf/TextureInfo.h" + +namespace CesiumGltf { +/** + * @brief Material Occlusion Texture Info + */ +struct CESIUMGLTF_API MaterialOcclusionTextureInfo final : public TextureInfo { + static inline 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 * (<sampled occlusion + * texture value> - 1.0)`. + */ + double strength = 1; +}; +} // 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 0000000000000000000000000000000000000000..b516f0ef5a589ff704e79d3b06e4a012c4b923ab --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltf/MaterialPBRMetallicRoughness.h @@ -0,0 +1,71 @@ +// This file was generated by generate-classes. +// DO NOT EDIT THIS FILE! +#pragma once + +#include "CesiumGltf/Library.h" +#include "CesiumGltf/TextureInfo.h" + +#include <CesiumUtility/ExtensibleObject.h> + +#include <optional> +#include <vector> + +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 { + static inline 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<double> 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<CesiumGltf::TextureInfo> 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<CesiumGltf::TextureInfo> metallicRoughnessTexture; +}; +} // 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 0000000000000000000000000000000000000000..77dd2977549485a247c8e6288079400c372df376 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltf/Mesh.h @@ -0,0 +1,30 @@ +// This file was generated by generate-classes. +// DO NOT EDIT THIS FILE! +#pragma once + +#include "CesiumGltf/Library.h" +#include "CesiumGltf/MeshPrimitive.h" +#include "CesiumGltf/NamedObject.h" + +#include <vector> + +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 { + static inline constexpr const char* TypeName = "Mesh"; + + /** + * @brief An array of primitives, each defining geometry to be rendered. + */ + std::vector<CesiumGltf::MeshPrimitive> 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<double> weights; +}; +} // 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 0000000000000000000000000000000000000000..f8a72af6056b166fa169bd327e23ce355a9cc883 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltf/MeshPrimitive.h @@ -0,0 +1,74 @@ +// This file was generated by generate-classes. +// DO NOT EDIT THIS FILE! +#pragma once + +#include "CesiumGltf/Library.h" + +#include <CesiumUtility/ExtensibleObject.h> + +#include <cstdint> +#include <unordered_map> +#include <vector> + +namespace CesiumGltf { +/** + * @brief Geometry to be rendered with the given material. + */ +struct CESIUMGLTF_API MeshPrimitive final + : public CesiumUtility::ExtensibleObject { + static inline constexpr const char* TypeName = "MeshPrimitive"; + + /** + * @brief Known values for The topology type of primitives to render. + */ + struct Mode { + static constexpr int32_t POINTS = 0; + + static constexpr int32_t LINES = 1; + + static constexpr int32_t LINE_LOOP = 2; + + static constexpr int32_t LINE_STRIP = 3; + + static constexpr int32_t TRIANGLES = 4; + + static constexpr int32_t TRIANGLE_STRIP = 5; + + 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<std::string, int32_t> 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<std::unordered_map<std::string, int32_t>> targets; +}; +} // namespace CesiumGltf diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltf/MetadataArrayView.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltf/MetadataArrayView.h new file mode 100644 index 0000000000000000000000000000000000000000..fe6b94b0c2154a39ceb433f769c031ced9f02dac --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltf/MetadataArrayView.h @@ -0,0 +1,129 @@ +#pragma once + +#include "CesiumGltf/PropertyType.h" + +#include <CesiumUtility/SpanHelper.h> + +#include <gsl/span> + +#include <cassert> +#include <cstddef> + +namespace CesiumGltf { +template <typename ElementType> class MetadataArrayView { +public: + MetadataArrayView() : _valueBuffer{} {} + + MetadataArrayView(const gsl::span<const std::byte>& buffer) noexcept + : _valueBuffer{ + CesiumUtility::reintepretCastSpan<const ElementType>(buffer)} {} + + const ElementType& operator[](int64_t index) const noexcept { + return _valueBuffer[index]; + } + + int64_t size() const noexcept { + return static_cast<int64_t>(_valueBuffer.size()); + } + +private: + gsl::span<const ElementType> _valueBuffer; +}; + +template <> class MetadataArrayView<bool> { +public: + MetadataArrayView() : _valueBuffer{}, _bitOffset{0}, _instanceCount{0} {} + + MetadataArrayView( + const gsl::span<const std::byte>& buffer, + int64_t bitOffset, + int64_t instanceCount) noexcept + : _valueBuffer{buffer}, + _bitOffset{bitOffset}, + _instanceCount{instanceCount} {} + + 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<int>(_valueBuffer[byteIndex] >> bitIndex) & 1; + return bitValue == 1; + } + + int64_t size() const noexcept { return _instanceCount; } + +private: + gsl::span<const std::byte> _valueBuffer; + int64_t _bitOffset; + int64_t _instanceCount; +}; + +template <> class MetadataArrayView<std::string_view> { +public: + MetadataArrayView() + : _valueBuffer{}, _offsetBuffer{}, _offsetType{}, _size{0} {} + + MetadataArrayView( + const gsl::span<const std::byte>& buffer, + const gsl::span<const std::byte>& offsetBuffer, + PropertyType offsetType, + int64_t size) noexcept + : _valueBuffer{buffer}, + _offsetBuffer{offsetBuffer}, + _offsetType{offsetType}, + _size{size} {} + + std::string_view operator[](int64_t index) const noexcept { + const size_t currentOffset = + getOffsetFromOffsetBuffer(index, _offsetBuffer, _offsetType); + const size_t nextOffset = + getOffsetFromOffsetBuffer(index + 1, _offsetBuffer, _offsetType); + return std::string_view( + reinterpret_cast<const char*>(_valueBuffer.data() + currentOffset), + (nextOffset - currentOffset)); + } + + int64_t size() const noexcept { return _size; } + +private: + static size_t getOffsetFromOffsetBuffer( + size_t instance, + const gsl::span<const std::byte>& offsetBuffer, + PropertyType offsetType) noexcept { + switch (offsetType) { + case PropertyType::Uint8: { + assert(instance < offsetBuffer.size() / sizeof(uint8_t)); + const uint8_t offset = *reinterpret_cast<const uint8_t*>( + offsetBuffer.data() + instance * sizeof(uint8_t)); + return static_cast<size_t>(offset); + } + case PropertyType::Uint16: { + assert(instance < offsetBuffer.size() / sizeof(uint16_t)); + const uint16_t offset = *reinterpret_cast<const uint16_t*>( + offsetBuffer.data() + instance * sizeof(uint16_t)); + return static_cast<size_t>(offset); + } + case PropertyType::Uint32: { + assert(instance < offsetBuffer.size() / sizeof(uint32_t)); + const uint32_t offset = *reinterpret_cast<const uint32_t*>( + offsetBuffer.data() + instance * sizeof(uint32_t)); + return static_cast<size_t>(offset); + } + case PropertyType::Uint64: { + assert(instance < offsetBuffer.size() / sizeof(uint64_t)); + const uint64_t offset = *reinterpret_cast<const uint64_t*>( + offsetBuffer.data() + instance * sizeof(uint64_t)); + return static_cast<size_t>(offset); + } + default: + assert(false && "Offset type has unknown type"); + return 0; + } + } + gsl::span<const std::byte> _valueBuffer; + gsl::span<const std::byte> _offsetBuffer; + PropertyType _offsetType; + int64_t _size; +}; +} // namespace CesiumGltf diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltf/MetadataFeatureTableView.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltf/MetadataFeatureTableView.h new file mode 100644 index 0000000000000000000000000000000000000000..cae3deb92cc387a6a381300be699ffcf22834db8 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltf/MetadataFeatureTableView.h @@ -0,0 +1,536 @@ +#pragma once + +#include "CesiumGltf/ExtensionModelExtFeatureMetadata.h" +#include "CesiumGltf/MetadataPropertyView.h" +#include "CesiumGltf/Model.h" +#include "CesiumGltf/PropertyType.h" + +#include <glm/common.hpp> + +#include <optional> + +namespace CesiumGltf { +/** + * @brief Utility to retrieve the data of FeatureTable + * + * This should be used to get {@link MetadataPropertyView} of a property since + * it will validate the EXT_Feature_Metadata format to make sure {@link MetadataPropertyView} + * not access out of bound + */ +class MetadataFeatureTableView { +public: + /** + * @brief Create an instance of MetadataFeatureTableView + * @param model The Gltf Model that stores featureTable data + * @param featureTable The FeatureTable that will be used to retrieve the data + * from + */ + MetadataFeatureTableView( + const Model* pModel, + const FeatureTable* pFeatureTable); + + /** + * @brief Find the {@link ClassProperty} which stores the type information of a property based on the property name + * @param propertyName The name of the property to retrieve type info + * @return ClassProperty of a property. Return nullptr if no property is found + */ + const ClassProperty* getClassProperty(const std::string& propertyName) const; + + /** + * @brief Get MetadataPropertyView to view the data of a property stored in + * the FeatureTable. + * + * This method will validate the EXT_Feature_Metadata format to ensure + * MetadataPropertyView retrieve the correct data. T must be uin8_t, int8_t, + * uint16_t, int16_t, uint32_t, int32_t, uint64_t, int64_t, float, double, + * bool, std::string_view, and MetadataArrayView<T> with T must be one of the + * types mentioned above + * + * @param propertyName The name of the property to retrieve data from + * @return ClassProperty of a property. Return nullptr if no property is found + */ + template <typename T> + MetadataPropertyView<T> + getPropertyView(const std::string& propertyName) const { + if (_pFeatureTable->count < 0) { + return createInvalidPropertyView<T>( + MetadataPropertyViewStatus::InvalidPropertyNotExist); + } + + const ClassProperty* pClassProperty = getClassProperty(propertyName); + if (!pClassProperty) { + return createInvalidPropertyView<T>( + MetadataPropertyViewStatus::InvalidPropertyNotExist); + } + + return getPropertyViewImpl<T>(propertyName, *pClassProperty); + } + + /** + * @brief Get MetadataPropertyView through a callback that accepts property + * name and std::optional<MetadataPropertyView<T>> to view the data of a + * property stored in the FeatureTable. + * + * This method will validate the EXT_Feature_Metadata format to ensure + * MetadataPropertyView retrieve the correct data. T must be uin8_t, int8_t, + * uint16_t, int16_t, uint32_t, int32_t, uint64_t, int64_t, float, double, + * bool, std::string_view, and MetadataArrayView<T> with T must be one of the + * types mentioned above. If the property is invalid, std::nullopt will be + * passed to the callback. Otherwise, a valid property view will be passed to + * the callback + * + * @param propertyName The name of the property to retrieve data from + * @tparam callback A callback function that accepts property name and + * std::optional<MetadataPropertyView<T>> + */ + template <typename Callback> + void + getPropertyView(const std::string& propertyName, Callback&& callback) const { + const ClassProperty* pClassProperty = getClassProperty(propertyName); + if (!pClassProperty) { + return; + } + + PropertyType type = convertStringToPropertyType(pClassProperty->type); + PropertyType componentType = PropertyType::None; + if (pClassProperty->componentType.has_value()) { + componentType = + convertStringToPropertyType(pClassProperty->componentType.value()); + } + + if (type != PropertyType::Array) { + getScalarPropertyViewImpl( + propertyName, + *pClassProperty, + type, + std::forward<Callback>(callback)); + } else { + getArrayPropertyViewImpl( + propertyName, + *pClassProperty, + componentType, + std::forward<Callback>(callback)); + } + } + + /** + * @brief Get MetadataPropertyView for each property in the FeatureTable + * through a callback that accepts property name and + * std::optional<MetadataPropertyView<T>> to view the data stored in the + * FeatureTableProperty. + * + * This method will validate the EXT_Feature_Metadata format to ensure + * MetadataPropertyView retrieve the correct data. T must be uin8_t, int8_t, + * uint16_t, int16_t, uint32_t, int32_t, uint64_t, int64_t, float, double, + * bool, std::string_view, and MetadataArrayView<T> with T must be one of the + * types mentioned above. If the property is invalid, std::nullopt will be + * passed to the callback. Otherwise, a valid property view will be passed to + * the callback + * + * @param propertyName The name of the property to retrieve data from + * @tparam callback A callback function that accepts property name and + * std::optional<MetadataPropertyView<T>> + */ + template <typename Callback> void forEachProperty(Callback&& callback) const { + for (const auto& property : this->_pClass->properties) { + getPropertyView(property.first, std::forward<Callback>(callback)); + } + } + +private: + template <typename Callback> + void getArrayPropertyViewImpl( + const std::string& propertyName, + const ClassProperty& classProperty, + PropertyType type, + Callback&& callback) const { + switch (type) { + case PropertyType::Int8: + callback( + propertyName, + getPropertyViewImpl<MetadataArrayView<int8_t>>( + propertyName, + classProperty)); + break; + case PropertyType::Uint8: + callback( + propertyName, + getPropertyViewImpl<MetadataArrayView<uint8_t>>( + propertyName, + classProperty)); + break; + case PropertyType::Int16: + callback( + propertyName, + getPropertyViewImpl<MetadataArrayView<int16_t>>( + propertyName, + classProperty)); + break; + case PropertyType::Uint16: + callback( + propertyName, + getPropertyViewImpl<MetadataArrayView<uint16_t>>( + propertyName, + classProperty)); + break; + case PropertyType::Int32: + callback( + propertyName, + getPropertyViewImpl<MetadataArrayView<int32_t>>( + propertyName, + classProperty)); + break; + case PropertyType::Uint32: + callback( + propertyName, + getPropertyViewImpl<MetadataArrayView<uint32_t>>( + propertyName, + classProperty)); + break; + case PropertyType::Int64: + callback( + propertyName, + getPropertyViewImpl<MetadataArrayView<int64_t>>( + propertyName, + classProperty)); + break; + case PropertyType::Uint64: + callback( + propertyName, + getPropertyViewImpl<MetadataArrayView<uint64_t>>( + propertyName, + classProperty)); + break; + case PropertyType::Float32: + callback( + propertyName, + getPropertyViewImpl<MetadataArrayView<float>>( + propertyName, + classProperty)); + break; + case PropertyType::Float64: + callback( + propertyName, + getPropertyViewImpl<MetadataArrayView<double>>( + propertyName, + classProperty)); + break; + case PropertyType::Boolean: + callback( + propertyName, + getPropertyViewImpl<MetadataArrayView<bool>>( + propertyName, + classProperty)); + break; + case PropertyType::String: + callback( + propertyName, + getPropertyViewImpl<MetadataArrayView<std::string_view>>( + propertyName, + classProperty)); + break; + default: + break; + } + } + + template <typename Callback> + void getScalarPropertyViewImpl( + const std::string& propertyName, + const ClassProperty& classProperty, + PropertyType type, + Callback&& callback) const { + switch (type) { + case PropertyType::Int8: + callback( + propertyName, + getPropertyViewImpl<int8_t>(propertyName, classProperty)); + break; + case PropertyType::Uint8: + callback( + propertyName, + getPropertyViewImpl<uint8_t>(propertyName, classProperty)); + break; + case PropertyType::Int16: + callback( + propertyName, + getPropertyViewImpl<int16_t>(propertyName, classProperty)); + break; + case PropertyType::Uint16: + callback( + propertyName, + getPropertyViewImpl<uint16_t>(propertyName, classProperty)); + break; + case PropertyType::Int32: + callback( + propertyName, + getPropertyViewImpl<int32_t>(propertyName, classProperty)); + break; + case PropertyType::Uint32: + callback( + propertyName, + getPropertyViewImpl<uint32_t>(propertyName, classProperty)); + break; + case PropertyType::Int64: + callback( + propertyName, + getPropertyViewImpl<int64_t>(propertyName, classProperty)); + break; + case PropertyType::Uint64: + callback( + propertyName, + getPropertyViewImpl<uint64_t>(propertyName, classProperty)); + break; + case PropertyType::Float32: + callback( + propertyName, + getPropertyViewImpl<float>(propertyName, classProperty)); + break; + case PropertyType::Float64: + callback( + propertyName, + getPropertyViewImpl<double>(propertyName, classProperty)); + break; + case PropertyType::Boolean: + callback( + propertyName, + getPropertyViewImpl<bool>(propertyName, classProperty)); + break; + case PropertyType::String: + callback( + propertyName, + getPropertyViewImpl<std::string_view>(propertyName, classProperty)); + break; + default: + break; + } + } + + template <typename T> + MetadataPropertyView<T> getPropertyViewImpl( + const std::string& propertyName, + const ClassProperty& classProperty) const { + auto featureTablePropertyIter = + _pFeatureTable->properties.find(propertyName); + if (featureTablePropertyIter == _pFeatureTable->properties.end()) { + return createInvalidPropertyView<T>( + MetadataPropertyViewStatus::InvalidPropertyNotExist); + } + + const FeatureTableProperty& featureTableProperty = + featureTablePropertyIter->second; + + if constexpr (IsMetadataNumeric<T>::value || IsMetadataBoolean<T>::value) { + return getPrimitivePropertyValues<T>(classProperty, featureTableProperty); + } + + if constexpr (IsMetadataString<T>::value) { + return getStringPropertyValues(classProperty, featureTableProperty); + } + + if constexpr ( + IsMetadataNumericArray<T>::value || IsMetadataBooleanArray<T>::value) { + return getPrimitiveArrayPropertyValues< + typename MetadataArrayType<T>::type>( + classProperty, + featureTableProperty); + } + + if constexpr (IsMetadataStringArray<T>::value) { + return getStringArrayPropertyValues(classProperty, featureTableProperty); + } + } + + template <typename T> + MetadataPropertyView<T> getPrimitivePropertyValues( + const ClassProperty& classProperty, + const FeatureTableProperty& featureTableProperty) const { + const PropertyType type = convertStringToPropertyType(classProperty.type); + if (TypeToPropertyType<T>::value != type) { + return createInvalidPropertyView<T>( + MetadataPropertyViewStatus::InvalidTypeMismatch); + } + + gsl::span<const std::byte> valueBuffer; + const auto status = + getBufferSafe(featureTableProperty.bufferView, valueBuffer); + if (status != MetadataPropertyViewStatus::Valid) { + return createInvalidPropertyView<T>(status); + } + + if (valueBuffer.size() % sizeof(T) != 0) { + return createInvalidPropertyView<T>( + MetadataPropertyViewStatus:: + InvalidBufferViewSizeNotDivisibleByTypeSize); + } + + size_t maxRequiredBytes = 0; + if (IsMetadataBoolean<T>::value) { + maxRequiredBytes = static_cast<size_t>( + glm::ceil(static_cast<double>(_pFeatureTable->count) / 8.0)); + } else { + maxRequiredBytes = _pFeatureTable->count * sizeof(T); + } + + if (valueBuffer.size() < maxRequiredBytes) { + return createInvalidPropertyView<T>( + MetadataPropertyViewStatus::InvalidBufferViewSizeNotFitInstanceCount); + } + + return MetadataPropertyView<T>( + MetadataPropertyViewStatus::Valid, + valueBuffer, + gsl::span<const std::byte>(), + gsl::span<const std::byte>(), + PropertyType::None, + 0, + _pFeatureTable->count, + classProperty.normalized); + } + + MetadataPropertyView<std::string_view> getStringPropertyValues( + const ClassProperty& classProperty, + const FeatureTableProperty& featureTableProperty) const; + + template <typename T> + MetadataPropertyView<MetadataArrayView<T>> getPrimitiveArrayPropertyValues( + const ClassProperty& classProperty, + const FeatureTableProperty& featureTableProperty) const { + if (classProperty.type != ClassProperty::Type::ARRAY) { + return createInvalidPropertyView<MetadataArrayView<T>>( + MetadataPropertyViewStatus::InvalidTypeMismatch); + } + + if (!classProperty.componentType.has_value()) { + return createInvalidPropertyView<MetadataArrayView<T>>( + MetadataPropertyViewStatus::InvalidTypeMismatch); + } + + const PropertyType componentType = + convertStringToPropertyType(classProperty.componentType.value()); + if (TypeToPropertyType<T>::value != componentType) { + return createInvalidPropertyView<MetadataArrayView<T>>( + MetadataPropertyViewStatus::InvalidTypeMismatch); + } + + gsl::span<const std::byte> valueBuffer; + auto status = getBufferSafe(featureTableProperty.bufferView, valueBuffer); + if (status != MetadataPropertyViewStatus::Valid) { + return createInvalidPropertyView<MetadataArrayView<T>>(status); + } + + if (valueBuffer.size() % sizeof(T) != 0) { + return createInvalidPropertyView<MetadataArrayView<T>>( + MetadataPropertyViewStatus:: + InvalidBufferViewSizeNotDivisibleByTypeSize); + } + + const int64_t componentCount = classProperty.componentCount.value_or(0); + if (componentCount > 0 && featureTableProperty.arrayOffsetBufferView >= 0) { + return createInvalidPropertyView<MetadataArrayView<T>>( + MetadataPropertyViewStatus:: + InvalidArrayComponentCountAndOffsetBufferCoexist); + } + + if (componentCount <= 0 && featureTableProperty.arrayOffsetBufferView < 0) { + return createInvalidPropertyView<MetadataArrayView<T>>( + MetadataPropertyViewStatus:: + InvalidArrayComponentCountOrOffsetBufferNotExist); + } + + // fixed array + if (componentCount > 0) { + size_t maxRequiredBytes = 0; + if constexpr (IsMetadataBoolean<T>::value) { + maxRequiredBytes = static_cast<size_t>(glm::ceil( + static_cast<double>(_pFeatureTable->count * componentCount) / 8.0)); + } else { + maxRequiredBytes = static_cast<size_t>( + _pFeatureTable->count * componentCount * sizeof(T)); + } + + if (valueBuffer.size() < maxRequiredBytes) { + return createInvalidPropertyView<MetadataArrayView<T>>( + MetadataPropertyViewStatus:: + InvalidBufferViewSizeNotFitInstanceCount); + } + + return MetadataPropertyView<MetadataArrayView<T>>( + MetadataPropertyViewStatus::Valid, + valueBuffer, + gsl::span<const std::byte>(), + gsl::span<const std::byte>(), + PropertyType::None, + static_cast<size_t>(componentCount), + static_cast<size_t>(_pFeatureTable->count), + classProperty.normalized); + } + + // dynamic array + const PropertyType offsetType = + convertOffsetStringToPropertyType(featureTableProperty.offsetType); + if (offsetType == PropertyType::None) { + return createInvalidPropertyView<MetadataArrayView<T>>( + MetadataPropertyViewStatus::InvalidOffsetType); + } + + constexpr bool checkBitsSize = IsMetadataBoolean<T>::value; + gsl::span<const std::byte> offsetBuffer; + status = getOffsetBufferSafe( + featureTableProperty.arrayOffsetBufferView, + offsetType, + valueBuffer.size(), + static_cast<size_t>(_pFeatureTable->count), + checkBitsSize, + offsetBuffer); + if (status != MetadataPropertyViewStatus::Valid) { + return createInvalidPropertyView<MetadataArrayView<T>>(status); + } + + return MetadataPropertyView<MetadataArrayView<T>>( + MetadataPropertyViewStatus::Valid, + valueBuffer, + offsetBuffer, + gsl::span<const std::byte>(), + offsetType, + 0, + static_cast<size_t>(_pFeatureTable->count), + classProperty.normalized); + } + + MetadataPropertyView<MetadataArrayView<std::string_view>> + getStringArrayPropertyValues( + const ClassProperty& classProperty, + const FeatureTableProperty& featureTableProperty) const; + + MetadataPropertyViewStatus getBufferSafe( + int32_t bufferViewIdx, + gsl::span<const std::byte>& buffer) const noexcept; + + MetadataPropertyViewStatus getOffsetBufferSafe( + int32_t bufferViewIdx, + PropertyType offsetType, + size_t valueBufferSize, + size_t instanceCount, + bool checkBitsSize, + gsl::span<const std::byte>& offsetBuffer) const noexcept; + + template <typename T> + static MetadataPropertyView<T> + createInvalidPropertyView(MetadataPropertyViewStatus invalidStatus) noexcept { + return MetadataPropertyView<T>( + invalidStatus, + gsl::span<const std::byte>(), + gsl::span<const std::byte>(), + gsl::span<const std::byte>(), + PropertyType::None, + 0, + 0, + false); + } + + const Model* _pModel; + const FeatureTable* _pFeatureTable; + const Class* _pClass; +}; +} // namespace CesiumGltf diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltf/MetadataPropertyView.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltf/MetadataPropertyView.h new file mode 100644 index 0000000000000000000000000000000000000000..6b535d27db94d1e61314c6cbfacbc9c3612d2d69 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltf/MetadataPropertyView.h @@ -0,0 +1,411 @@ +#pragma once + +#include "CesiumGltf/MetadataArrayView.h" +#include "CesiumGltf/PropertyType.h" +#include "CesiumGltf/PropertyTypeTraits.h" + +#include <gsl/span> + +#include <cassert> +#include <cstddef> +#include <cstdint> +#include <string_view> +#include <type_traits> + +namespace CesiumGltf { +/** + * @brief Indicates the status of a property view. + * + * The {@link MetadataPropertyView} constructor always completes successfully. However, + * it may not always reflect the actual content of the {@link FeatureTableProperty}, but + * instead indicate that its {@link MetadataPropertyView::size} is 0. This enumeration + * provides the reason. + */ +enum class MetadataPropertyViewStatus { + /** + * @brief This property view is valid and ready to use. + */ + Valid, + + /** + * @brief This property view does not exist in the FeatureTable. + */ + InvalidPropertyNotExist, + + /** + * @brief This property view does not have a correct type with what is + * specified in {@link ClassProperty::type}. + */ + InvalidTypeMismatch, + + /** + * @brief This property view does not have a valid value buffer view index. + */ + InvalidValueBufferViewIndex, + + /** + * @brief This array property view does not have a valid array offset buffer + * view index. + */ + InvalidArrayOffsetBufferViewIndex, + + /** + * @brief This string property view does not have a valid string offset buffer + * view index. + */ + InvalidStringOffsetBufferViewIndex, + + /** + * @brief This property view has a valid value buffer view index, but buffer + * view specifies an invalid buffer index + */ + InvalidValueBufferIndex, + + /** + * @brief This property view has a valid array string buffer view index, but + * buffer view specifies an invalid buffer index + */ + InvalidArrayOffsetBufferIndex, + + /** + * @brief This property view has a valid string offset buffer view index, but + * buffer view specifies an invalid buffer index + */ + InvalidStringOffsetBufferIndex, + + /** + * @brief This property view has buffer view's offset not aligned by 8 bytes + */ + InvalidBufferViewNotAligned8Bytes, + + /** + * @brief This property view has an out-of-bound buffer view + */ + InvalidBufferViewOutOfBound, + + /** + * @brief This property view has an invalid buffer view's length which is not + * a multiple of the size of its type or offset type + */ + InvalidBufferViewSizeNotDivisibleByTypeSize, + + /** + * @brief This property view has an invalid buffer view's length which cannot + * fit all the instances of the feature table + */ + InvalidBufferViewSizeNotFitInstanceCount, + + /** + * @brief This array property view has both component count and offset buffer + * view + */ + InvalidArrayComponentCountAndOffsetBufferCoexist, + + /** + * @brief This array property view doesn't have either component count or + * offset buffer view + */ + InvalidArrayComponentCountOrOffsetBufferNotExist, + + /** + * @brief This property view have an unknown offset type + */ + InvalidOffsetType, + + /** + * @brief This property view has offset values not sorted ascendingly + */ + InvalidOffsetValuesNotSortedAscending, + + /** + * @brief This property view has an offset point to an out of bound value + */ + InvalidOffsetValuePointsToOutOfBoundBuffer +}; + +/** + * @brief A view on the data of the FeatureTableProperty + * + * It provides utility to retrieve the actual data stored in the + * {@link FeatureTableProperty::bufferView} like an array of elements. + * Data of each instance can be accessed through the {@link get(int64_t instance)} method + * + * @param ElementType must be uin8_t, int8_t, uint16_t, int16_t, + * uint32_t, int32_t, uint64_t, int64_t, float, double, bool, std::string_view, + * and MetadataArrayView<T> with T must be one of the types mentioned above + */ +template <typename ElementType> class MetadataPropertyView { +public: + /** + * @brief Constructs a new instance viewing a non-existent property. + */ + MetadataPropertyView() + : _status{MetadataPropertyViewStatus::InvalidPropertyNotExist}, + _valueBuffer{}, + _arrayOffsetBuffer{}, + _stringOffsetBuffer{}, + _offsetType{}, + _offsetSize{}, + _componentCount{}, + _instanceCount{}, + _normalized{} {} + + /** + * @brief Construct a new instance pointing to the data specified by + * FeatureTableProperty + * @param valueBuffer The raw buffer specified by {@link FeatureTableProperty::bufferView} + * @param arrayOffsetBuffer The raw buffer specified by {@link FeatureTableProperty::arrayOffsetBufferView} + * @param stringOffsetBuffer The raw buffer specified by {@link FeatureTableProperty::stringOffsetBufferView} + * @param offsetType The offset type of the arrayOffsetBuffer and stringOffsetBuffer that is specified by {@link FeatureTableProperty::offsetType} + * @param componentCount The number of elements for fixed array value which is specified by {@link FeatureTableProperty::componentCount} + * @param instanceCount The number of instances specified by {@link FeatureTable::count} + * @param normalized Whether this property has a normalized integer type. + */ + MetadataPropertyView( + MetadataPropertyViewStatus status, + gsl::span<const std::byte> valueBuffer, + gsl::span<const std::byte> arrayOffsetBuffer, + gsl::span<const std::byte> stringOffsetBuffer, + PropertyType offsetType, + int64_t componentCount, + int64_t instanceCount, + bool normalized) noexcept + : _status{status}, + _valueBuffer{valueBuffer}, + _arrayOffsetBuffer{arrayOffsetBuffer}, + _stringOffsetBuffer{stringOffsetBuffer}, + _offsetType{offsetType}, + _offsetSize{getOffsetSize(offsetType)}, + _componentCount{componentCount}, + _instanceCount{instanceCount}, + _normalized{normalized} {} + + /** + * @brief Gets the status of this property view. + * + * Indicates whether the view accurately reflects the property's data, or + * whether an error occurred. + */ + MetadataPropertyViewStatus status() const noexcept { return _status; } + + /** + * @brief Get the value of an instance of the FeatureTable. + * @param instance The instance index + * @return The value of the instance + */ + ElementType get(int64_t instance) const noexcept { + assert( + _status == MetadataPropertyViewStatus::Valid && + "Check the status() first to make sure view is valid"); + assert( + size() > 0 && + "Check the size() of the view to make sure it's not empty"); + assert(instance >= 0 && "instance index must be positive"); + + if constexpr (IsMetadataNumeric<ElementType>::value) { + return getNumeric(instance); + } + + if constexpr (IsMetadataBoolean<ElementType>::value) { + return getBoolean(instance); + } + + if constexpr (IsMetadataString<ElementType>::value) { + return getString(instance); + } + + if constexpr (IsMetadataNumericArray<ElementType>::value) { + return getNumericArray<typename MetadataArrayType<ElementType>::type>( + instance); + } + + if constexpr (IsMetadataBooleanArray<ElementType>::value) { + return getBooleanArray(instance); + } + + if constexpr (IsMetadataStringArray<ElementType>::value) { + return getStringArray(instance); + } + } + + /** + * @brief Get the number of instances in the FeatureTable + * @return The number of instances in the FeatureTable + */ + int64_t size() const noexcept { return _instanceCount; } + + /** + * @brief Get the component count of this property. Only applicable when the + * property is an array type. + * + * @return The component count of this property. + */ + int64_t getComponentCount() const noexcept { return _componentCount; } + + /** + * @brief Whether this property has a normalized integer type. + * + * @return Whether this property has a normalized integer type. + */ + bool isNormalized() const noexcept { return _normalized; } + +private: + ElementType getNumeric(int64_t instance) const noexcept { + return reinterpret_cast<const ElementType*>(_valueBuffer.data())[instance]; + } + + bool getBoolean(int64_t instance) const noexcept { + const int64_t byteIndex = instance / 8; + const int64_t bitIndex = instance % 8; + const int bitValue = + static_cast<int>(_valueBuffer[byteIndex] >> bitIndex) & 1; + return bitValue == 1; + } + + std::string_view getString(int64_t instance) const noexcept { + const size_t currentOffset = + getOffsetFromOffsetBuffer(instance, _stringOffsetBuffer, _offsetType); + const size_t nextOffset = getOffsetFromOffsetBuffer( + instance + 1, + _stringOffsetBuffer, + _offsetType); + return std::string_view( + reinterpret_cast<const char*>(_valueBuffer.data() + currentOffset), + (nextOffset - currentOffset)); + } + + template <typename T> + MetadataArrayView<T> getNumericArray(int64_t instance) const noexcept { + if (_componentCount > 0) { + const gsl::span<const std::byte> vals( + _valueBuffer.data() + instance * _componentCount * sizeof(T), + _componentCount * sizeof(T)); + return MetadataArrayView<T>{vals}; + } + + const size_t currentOffset = + getOffsetFromOffsetBuffer(instance, _arrayOffsetBuffer, _offsetType); + const size_t nextOffset = getOffsetFromOffsetBuffer( + instance + 1, + _arrayOffsetBuffer, + _offsetType); + const gsl::span<const std::byte> vals( + _valueBuffer.data() + currentOffset, + (nextOffset - currentOffset)); + return MetadataArrayView<T>{vals}; + } + + MetadataArrayView<std::string_view> + getStringArray(int64_t instance) const noexcept { + if (_componentCount > 0) { + const gsl::span<const std::byte> offsetVals( + _stringOffsetBuffer.data() + instance * _componentCount * _offsetSize, + (_componentCount + 1) * _offsetSize); + return MetadataArrayView<std::string_view>( + _valueBuffer, + offsetVals, + _offsetType, + _componentCount); + } + + const size_t currentOffset = + getOffsetFromOffsetBuffer(instance, _arrayOffsetBuffer, _offsetType); + const size_t nextOffset = getOffsetFromOffsetBuffer( + instance + 1, + _arrayOffsetBuffer, + _offsetType); + const gsl::span<const std::byte> offsetVals( + _stringOffsetBuffer.data() + currentOffset, + (nextOffset - currentOffset + _offsetSize)); + return MetadataArrayView<std::string_view>( + _valueBuffer, + offsetVals, + _offsetType, + (nextOffset - currentOffset) / _offsetSize); + } + + MetadataArrayView<bool> getBooleanArray(int64_t instance) const noexcept { + if (_componentCount > 0) { + const size_t offsetBits = _componentCount * instance; + const size_t nextOffsetBits = _componentCount * (instance + 1); + const gsl::span<const std::byte> buffer( + _valueBuffer.data() + offsetBits / 8, + (nextOffsetBits / 8 - offsetBits / 8 + 1)); + return MetadataArrayView<bool>(buffer, offsetBits % 8, _componentCount); + } + + const size_t currentOffset = + getOffsetFromOffsetBuffer(instance, _arrayOffsetBuffer, _offsetType); + const size_t nextOffset = getOffsetFromOffsetBuffer( + instance + 1, + _arrayOffsetBuffer, + _offsetType); + + const size_t totalBits = nextOffset - currentOffset; + const gsl::span<const std::byte> buffer( + _valueBuffer.data() + currentOffset / 8, + (nextOffset / 8 - currentOffset / 8 + 1)); + return MetadataArrayView<bool>(buffer, currentOffset % 8, totalBits); + } + + static int64_t getOffsetSize(PropertyType offsetType) noexcept { + switch (offsetType) { + case CesiumGltf::PropertyType::Uint8: + return sizeof(uint8_t); + case CesiumGltf::PropertyType::Uint16: + return sizeof(uint16_t); + case CesiumGltf::PropertyType::Uint32: + return sizeof(uint32_t); + case CesiumGltf::PropertyType::Uint64: + return sizeof(uint64_t); + default: + return 0; + } + } + + static size_t getOffsetFromOffsetBuffer( + size_t instance, + const gsl::span<const std::byte>& offsetBuffer, + PropertyType offsetType) noexcept { + switch (offsetType) { + case PropertyType::Uint8: { + assert(instance < offsetBuffer.size() / sizeof(uint8_t)); + const uint8_t offset = *reinterpret_cast<const uint8_t*>( + offsetBuffer.data() + instance * sizeof(uint8_t)); + return static_cast<size_t>(offset); + } + case PropertyType::Uint16: { + assert(instance < offsetBuffer.size() / sizeof(uint16_t)); + const uint16_t offset = *reinterpret_cast<const uint16_t*>( + offsetBuffer.data() + instance * sizeof(uint16_t)); + return static_cast<size_t>(offset); + } + case PropertyType::Uint32: { + assert(instance < offsetBuffer.size() / sizeof(uint32_t)); + const uint32_t offset = *reinterpret_cast<const uint32_t*>( + offsetBuffer.data() + instance * sizeof(uint32_t)); + return static_cast<size_t>(offset); + } + case PropertyType::Uint64: { + assert(instance < offsetBuffer.size() / sizeof(uint64_t)); + const uint64_t offset = *reinterpret_cast<const uint64_t*>( + offsetBuffer.data() + instance * sizeof(uint64_t)); + return static_cast<size_t>(offset); + } + default: + assert(false && "Offset type has unknown type"); + return 0; + } + } + + MetadataPropertyViewStatus _status; + gsl::span<const std::byte> _valueBuffer; + gsl::span<const std::byte> _arrayOffsetBuffer; + gsl::span<const std::byte> _stringOffsetBuffer; + PropertyType _offsetType; + int64_t _offsetSize; + int64_t _componentCount; + int64_t _instanceCount; + bool _normalized; +}; +} // namespace CesiumGltf 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 0000000000000000000000000000000000000000..d88694f149077f7ce7fc327f961ea830114f1ea3 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltf/Model.h @@ -0,0 +1,141 @@ +#pragma once + +#include "CesiumGltf/Library.h" +#include "CesiumGltf/ModelSpec.h" + +#include <glm/mat4x4.hpp> + +#include <functional> + +namespace CesiumGltf { + +/** @copydoc ModelSpec */ +struct CESIUMGLTF_API Model : public ModelSpec { + /** + * @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 ExtensibleObject::extras}, if any, + * are _not_ updated. + * + * @param rhs The model to merge into this one. + */ + void merge(Model&& rhs); + + /** + * @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( + int sceneID, + std::function<ForEachPrimitiveInSceneCallback>&& 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 Gltf::forEachPrimitiveInScene() */ + void forEachPrimitiveInScene( + int sceneID, + std::function<ForEachPrimitiveInSceneConstCallback>&& 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 <typename T> + static const T& getSafe(const std::vector<T>& items, int32_t index) { + static T defaultObject; + if (index < 0 || static_cast<size_t>(index) >= items.size()) { + return defaultObject; + } else { + return items[static_cast<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 <typename T> + static const T* + getSafe(const std::vector<T>* pItems, int32_t index) noexcept { + if (index < 0 || static_cast<size_t>(index) >= pItems->size()) { + return nullptr; + } else { + return &(*pItems)[static_cast<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 <typename T> + static T* getSafe(std::vector<T>* pItems, int32_t index) noexcept { + if (index < 0 || static_cast<size_t>(index) >= pItems->size()) { + return nullptr; + } else { + return &(*pItems)[static_cast<size_t>(index)]; + } + } +}; +} // 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 0000000000000000000000000000000000000000..b2cbf16b39e861066e957fb3d5abcdbf24d48c09 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltf/ModelSpec.h @@ -0,0 +1,147 @@ +// This file was generated by generate-classes. +// DO NOT EDIT THIS FILE! +#pragma once + +#include "CesiumGltf/Accessor.h" +#include "CesiumGltf/Animation.h" +#include "CesiumGltf/Asset.h" +#include "CesiumGltf/Buffer.h" +#include "CesiumGltf/BufferView.h" +#include "CesiumGltf/Camera.h" +#include "CesiumGltf/Image.h" +#include "CesiumGltf/Library.h" +#include "CesiumGltf/Material.h" +#include "CesiumGltf/Mesh.h" +#include "CesiumGltf/Node.h" +#include "CesiumGltf/Sampler.h" +#include "CesiumGltf/Scene.h" +#include "CesiumGltf/Skin.h" +#include "CesiumGltf/Texture.h" + +#include <CesiumUtility/ExtensibleObject.h> + +#include <cstdint> +#include <string> +#include <vector> + +namespace CesiumGltf { +/** + * @brief The root object for a glTF asset. + */ +struct CESIUMGLTF_API ModelSpec : public CesiumUtility::ExtensibleObject { + static inline constexpr const char* TypeName = "Model"; + + /** + * @brief Names of glTF extensions used in this asset. + */ + std::vector<std::string> extensionsUsed; + + /** + * @brief Names of glTF extensions required to properly load this asset. + */ + std::vector<std::string> extensionsRequired; + + /** + * @brief An array of accessors. + * + * An accessor is a typed view into a bufferView. + */ + std::vector<CesiumGltf::Accessor> accessors; + + /** + * @brief An array of keyframe animations. + */ + std::vector<CesiumGltf::Animation> 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<CesiumGltf::Buffer> buffers; + + /** + * @brief An array of bufferViews. + * + * A bufferView is a view into a buffer generally representing a subset of the + * buffer. + */ + std::vector<CesiumGltf::BufferView> bufferViews; + + /** + * @brief An array of cameras. + * + * A camera defines a projection matrix. + */ + std::vector<CesiumGltf::Camera> cameras; + + /** + * @brief An array of images. + * + * An image defines data used to create a texture. + */ + std::vector<CesiumGltf::Image> images; + + /** + * @brief An array of materials. + * + * A material defines the appearance of a primitive. + */ + std::vector<CesiumGltf::Material> materials; + + /** + * @brief An array of meshes. + * + * A mesh is a set of primitives to be rendered. + */ + std::vector<CesiumGltf::Mesh> meshes; + + /** + * @brief An array of nodes. + */ + std::vector<CesiumGltf::Node> nodes; + + /** + * @brief An array of samplers. + * + * A sampler contains properties for texture filtering and wrapping modes. + */ + std::vector<CesiumGltf::Sampler> 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<CesiumGltf::Scene> scenes; + + /** + * @brief An array of skins. + * + * A skin is defined by joints and matrices. + */ + std::vector<CesiumGltf::Skin> skins; + + /** + * @brief An array of textures. + */ + std::vector<CesiumGltf::Texture> textures; + +private: + /** + * @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 0000000000000000000000000000000000000000..3f0a9997b6b7c606a76c95e3ec0a3686678e166b --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltf/NamedObject.h @@ -0,0 +1,24 @@ +#pragma once + +#include "CesiumGltf/Library.h" + +#include <CesiumUtility/ExtensibleObject.h> + +#include <string> + +namespace CesiumGltf { +/** + * @brief The base class for objects in a glTF that have a name. + * + * A named object is also an {@link 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; +}; +} // 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 0000000000000000000000000000000000000000..ebae12e31389d4271b18efb219d5c59f3fad60ae --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltf/Node.h @@ -0,0 +1,80 @@ +// This file was generated by generate-classes. +// DO NOT EDIT THIS FILE! +#pragma once + +#include "CesiumGltf/Library.h" +#include "CesiumGltf/NamedObject.h" + +#include <cstdint> +#include <vector> + +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 { + static inline 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<int32_t> 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<double> 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<double> 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<double> scale = {1, 1, 1}; + + /** + * @brief The node's translation along the x, y, and z axes. + */ + std::vector<double> 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<double> weights; +}; +} // namespace CesiumGltf diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltf/PropertyStatistics.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltf/PropertyStatistics.h new file mode 100644 index 0000000000000000000000000000000000000000..97eae4d4a3cda4e8d9063764f02b18552a840270 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltf/PropertyStatistics.h @@ -0,0 +1,92 @@ +// This file was generated by generate-classes. +// DO NOT EDIT THIS FILE! +#pragma once + +#include "CesiumGltf/Library.h" + +#include <CesiumUtility/ExtensibleObject.h> +#include <CesiumUtility/JsonValue.h> + +#include <optional> +#include <unordered_map> + +namespace CesiumGltf { +/** + * @brief Statistics about property values. + */ +struct CESIUMGLTF_API PropertyStatistics final + : public CesiumUtility::ExtensibleObject { + static inline constexpr const char* TypeName = "PropertyStatistics"; + + /** + * @brief The minimum property value. Only applicable for numeric types and + * fixed-length arrays of numeric types. For numeric types this is a single + * number. For fixed-length arrays this is an array with `componentCount` + * number of elements. The `normalized` property has no effect on these + * values. + */ + std::optional<CesiumUtility::JsonValue> min; + + /** + * @brief The maximum property value. Only applicable for numeric types and + * fixed-length arrays of numeric types. For numeric types this is a single + * number. For fixed-length arrays this is an array with `componentCount` + * number of elements. The `normalized` property has no effect on these + * values. + */ + std::optional<CesiumUtility::JsonValue> max; + + /** + * @brief The arithmetic mean of the property values. Only applicable for + * numeric types and fixed-length arrays of numeric types. For numeric types + * this is a single number. For fixed-length arrays this is an array with + * `componentCount` number of elements. The `normalized` property has no + * effect on these values. + */ + std::optional<CesiumUtility::JsonValue> mean; + + /** + * @brief The median of the property values. Only applicable for numeric types + * and fixed-length arrays of numeric types. For numeric types this is a + * single number. For fixed-length arrays this is an array with + * `componentCount` number of elements. The `normalized` property has no + * effect on these values. + */ + std::optional<CesiumUtility::JsonValue> median; + + /** + * @brief The standard deviation of the property values. Only applicable for + * numeric types and fixed-length arrays of numeric types. For numeric types + * this is a single number. For fixed-length arrays this is an array with + * `componentCount` number of elements. The `normalized` property has no + * effect on these values. + */ + std::optional<CesiumUtility::JsonValue> standardDeviation; + + /** + * @brief The variance of the property values. Only applicable for numeric + * types and fixed-length arrays of numeric types. For numeric types this is a + * single number. For fixed-length arrays this is an array with + * `componentCount` number of elements. The `normalized` property has no + * effect on these values. + */ + std::optional<CesiumUtility::JsonValue> variance; + + /** + * @brief The sum of the property values. Only applicable for numeric types + * and fixed-length arrays of numeric types. For numeric types this is a + * single number. For fixed-length arrays this is an array with + * `componentCount` number of elements. The `normalized` property has no + * effect on these values. + */ + std::optional<CesiumUtility::JsonValue> 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` or `componentType` is `ENUM`. For fixed-length arrays, this is an + * array with `componentCount` number of elements. + */ + std::unordered_map<std::string, CesiumUtility::JsonValue> occurrences; +}; +} // 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 0000000000000000000000000000000000000000..bb2ece60a28e03e6c07bac7a6719bc29fbd4dd21 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltf/PropertyType.h @@ -0,0 +1,31 @@ +#pragma once + +#include <cstdint> +#include <string> +#include <string_view> + +namespace CesiumGltf { +enum class PropertyType { + None, + Int8, + Uint8, + Int16, + Uint16, + Int32, + Uint32, + Int64, + Uint64, + Float32, + Float64, + Boolean, + Enum, + String, + Array, +}; + +std::string convertPropertyTypeToString(CesiumGltf::PropertyType type); + +PropertyType convertStringToPropertyType(const std::string& str); + +PropertyType convertOffsetStringToPropertyType(const std::string& str); +} // 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 0000000000000000000000000000000000000000..144365665082ebd58bb29c8731b3d5ce3ee52415 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltf/PropertyTypeTraits.h @@ -0,0 +1,180 @@ +#pragma once + +#include "CesiumGltf/MetadataArrayView.h" +#include "CesiumGltf/PropertyType.h" + +#include <cstdint> +#include <type_traits> + +namespace CesiumGltf { +/** + * @brief Check if a C++ type can be represented as a numeric property type + */ +template <typename... T> struct IsMetadataNumeric; +template <typename T> struct IsMetadataNumeric<T> : std::false_type {}; +template <> struct IsMetadataNumeric<uint8_t> : std::true_type {}; +template <> struct IsMetadataNumeric<int8_t> : std::true_type {}; +template <> struct IsMetadataNumeric<uint16_t> : std::true_type {}; +template <> struct IsMetadataNumeric<int16_t> : std::true_type {}; +template <> struct IsMetadataNumeric<uint32_t> : std::true_type {}; +template <> struct IsMetadataNumeric<int32_t> : std::true_type {}; +template <> struct IsMetadataNumeric<uint64_t> : std::true_type {}; +template <> struct IsMetadataNumeric<int64_t> : std::true_type {}; +template <> struct IsMetadataNumeric<float> : std::true_type {}; +template <> struct IsMetadataNumeric<double> : std::true_type {}; + +/** + * @brief Check if a C++ type can be represented as an integer property type + */ +template <typename... T> struct IsMetadataInteger; +template <typename T> struct IsMetadataInteger<T> : std::false_type {}; +template <> struct IsMetadataInteger<uint8_t> : std::true_type {}; +template <> struct IsMetadataInteger<int8_t> : std::true_type {}; +template <> struct IsMetadataInteger<uint16_t> : std::true_type {}; +template <> struct IsMetadataInteger<int16_t> : std::true_type {}; +template <> struct IsMetadataInteger<uint32_t> : std::true_type {}; +template <> struct IsMetadataInteger<int32_t> : std::true_type {}; +template <> struct IsMetadataInteger<uint64_t> : std::true_type {}; +template <> struct IsMetadataInteger<int64_t> : std::true_type {}; + +/** + * @brief Check if a C++ type can be represented as a floating-point property + * type + */ +template <typename... T> struct IsMetadataFloating; +template <typename T> struct IsMetadataFloating<T> : std::false_type {}; +template <> struct IsMetadataFloating<float> : std::true_type {}; +template <> struct IsMetadataFloating<double> : std::true_type {}; + +/** + * @brief Check if a C++ type can be represented as a boolean property type + */ +template <typename... T> struct IsMetadataBoolean; +template <typename T> struct IsMetadataBoolean<T> : std::false_type {}; +template <> struct IsMetadataBoolean<bool> : std::true_type {}; + +/** + * @brief Check if a C++ type can be represented as a string property type + */ +template <typename... T> struct IsMetadataString; +template <typename T> struct IsMetadataString<T> : std::false_type {}; +template <> struct IsMetadataString<std::string_view> : std::true_type {}; + +/** + * @brief Check if a C++ type can be represented as an array. + */ +template <typename... T> struct IsMetadataArray; +template <typename T> struct IsMetadataArray<T> : std::false_type {}; +template <typename T> +struct IsMetadataArray<MetadataArrayView<T>> : std::true_type {}; + +/** + * @brief Check if a C++ type can be represented as an array of number property + * type + */ +template <typename... T> struct IsMetadataNumericArray; +template <typename T> struct IsMetadataNumericArray<T> : std::false_type {}; +template <typename T> struct IsMetadataNumericArray<MetadataArrayView<T>> { + static constexpr bool value = IsMetadataNumeric<T>::value; +}; + +/** + * @brief Check if a C++ type can be represented as an array of boolean property + * type + */ +template <typename... T> struct IsMetadataBooleanArray; +template <typename T> struct IsMetadataBooleanArray<T> : std::false_type {}; +template <> +struct IsMetadataBooleanArray<MetadataArrayView<bool>> : std::true_type {}; + +/** + * @brief Check if a C++ type can be represented as an array of string property + * type + */ +template <typename... T> struct IsMetadataStringArray; +template <typename T> struct IsMetadataStringArray<T> : std::false_type {}; +template <> +struct IsMetadataStringArray<MetadataArrayView<std::string_view>> + : std::true_type {}; + +/** + * @brief Retrieve the component type of a metadata array + */ +template <typename T> struct MetadataArrayType; +template <typename T> +struct MetadataArrayType<CesiumGltf::MetadataArrayView<T>> { + using type = T; +}; + +/** + * @brief Convert a C++ type to PropertyType + */ +template <typename T> struct TypeToPropertyType; + +template <> struct TypeToPropertyType<uint8_t> { + static constexpr PropertyType component = PropertyType::None; + static constexpr PropertyType value = PropertyType::Uint8; +}; + +template <> struct TypeToPropertyType<int8_t> { + static constexpr PropertyType component = PropertyType::None; + static constexpr PropertyType value = PropertyType::Int8; +}; + +template <> struct TypeToPropertyType<uint16_t> { + static constexpr PropertyType component = PropertyType::None; + static constexpr PropertyType value = PropertyType::Uint16; +}; + +template <> struct TypeToPropertyType<int16_t> { + static constexpr PropertyType component = PropertyType::None; + static constexpr PropertyType value = PropertyType::Int16; +}; + +template <> struct TypeToPropertyType<uint32_t> { + static constexpr PropertyType component = PropertyType::None; + static constexpr PropertyType value = PropertyType::Uint32; +}; + +template <> struct TypeToPropertyType<int32_t> { + static constexpr PropertyType component = PropertyType::None; + static constexpr PropertyType value = PropertyType::Int32; +}; + +template <> struct TypeToPropertyType<uint64_t> { + static constexpr PropertyType component = PropertyType::None; + static constexpr PropertyType value = PropertyType::Uint64; +}; + +template <> struct TypeToPropertyType<int64_t> { + static constexpr PropertyType component = PropertyType::None; + static constexpr PropertyType value = PropertyType::Int64; +}; + +template <> struct TypeToPropertyType<float> { + static constexpr PropertyType component = PropertyType::None; + static constexpr PropertyType value = PropertyType::Float32; +}; + +template <> struct TypeToPropertyType<double> { + static constexpr PropertyType component = PropertyType::None; + static constexpr PropertyType value = PropertyType::Float64; +}; + +template <> struct TypeToPropertyType<bool> { + static constexpr PropertyType component = PropertyType::None; + static constexpr PropertyType value = PropertyType::Boolean; +}; + +template <> struct TypeToPropertyType<std::string_view> { + static constexpr PropertyType component = PropertyType::None; + static constexpr PropertyType value = PropertyType::String; +}; + +template <typename T> +struct TypeToPropertyType<CesiumGltf::MetadataArrayView<T>> { + static constexpr PropertyType component = TypeToPropertyType<T>::value; + static constexpr PropertyType value = PropertyType::Array; +}; + +} // 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 0000000000000000000000000000000000000000..70b98883e84712771cbf1aabb09998af08c54e90 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltf/Sampler.h @@ -0,0 +1,99 @@ +// This file was generated by generate-classes. +// DO NOT EDIT THIS FILE! +#pragma once + +#include "CesiumGltf/Library.h" +#include "CesiumGltf/NamedObject.h" + +#include <optional> + +namespace CesiumGltf { +/** + * @brief Texture sampler properties for filtering and wrapping modes. + */ +struct CESIUMGLTF_API Sampler final : public CesiumGltf::NamedObject { + static inline constexpr const char* TypeName = "Sampler"; + + /** + * @brief Known values for Magnification filter. + */ + struct MagFilter { + static constexpr int32_t NEAREST = 9728; + + static constexpr int32_t LINEAR = 9729; + }; + + /** + * @brief Known values for Minification filter. + */ + struct MinFilter { + static constexpr int32_t NEAREST = 9728; + + static constexpr int32_t LINEAR = 9729; + + static constexpr int32_t NEAREST_MIPMAP_NEAREST = 9984; + + static constexpr int32_t LINEAR_MIPMAP_NEAREST = 9985; + + static constexpr int32_t NEAREST_MIPMAP_LINEAR = 9986; + + static constexpr int32_t LINEAR_MIPMAP_LINEAR = 9987; + }; + + /** + * @brief Known values for S (U) wrapping mode. + */ + struct WrapS { + static constexpr int32_t CLAMP_TO_EDGE = 33071; + + static constexpr int32_t MIRRORED_REPEAT = 33648; + + static constexpr int32_t REPEAT = 10497; + }; + + /** + * @brief Known values for T (V) wrapping mode. + */ + struct WrapT { + static constexpr int32_t CLAMP_TO_EDGE = 33071; + + static constexpr int32_t MIRRORED_REPEAT = 33648; + + static constexpr int32_t REPEAT = 10497; + }; + + /** + * @brief Magnification filter. + * + * Known values are defined in {@link MagFilter}. + * + */ + std::optional<int32_t> magFilter; + + /** + * @brief Minification filter. + * + * Known values are defined in {@link MinFilter}. + * + */ + std::optional<int32_t> 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; +}; +} // 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 0000000000000000000000000000000000000000..48fce87cdb130d468eb516b9fae40b7b7bfee89e --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltf/Scene.h @@ -0,0 +1,23 @@ +// This file was generated by generate-classes. +// DO NOT EDIT THIS FILE! +#pragma once + +#include "CesiumGltf/Library.h" +#include "CesiumGltf/NamedObject.h" + +#include <cstdint> +#include <vector> + +namespace CesiumGltf { +/** + * @brief The root nodes of a scene. + */ +struct CESIUMGLTF_API Scene final : public CesiumGltf::NamedObject { + static inline constexpr const char* TypeName = "Scene"; + + /** + * @brief The indices of each root node. + */ + std::vector<int32_t> nodes; +}; +} // 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 0000000000000000000000000000000000000000..838b1e567c66a406cbbe85d00ffb0209bb278bb6 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltf/Schema.h @@ -0,0 +1,49 @@ +// This file was generated by generate-classes. +// DO NOT EDIT THIS FILE! +#pragma once + +#include "CesiumGltf/Class.h" +#include "CesiumGltf/Enum.h" +#include "CesiumGltf/Library.h" + +#include <CesiumUtility/ExtensibleObject.h> + +#include <optional> +#include <string> +#include <unordered_map> + +namespace CesiumGltf { +/** + * @brief An object defining classes and enums. + */ +struct CESIUMGLTF_API Schema final : public CesiumUtility::ExtensibleObject { + static inline constexpr const char* TypeName = "Schema"; + + /** + * @brief The name of the schema. + */ + std::optional<std::string> name; + + /** + * @brief The description of the schema. + */ + std::optional<std::string> description; + + /** + * @brief Application-specific version of the schema. + */ + std::optional<std::string> version; + + /** + * @brief A dictionary, where each key is a class ID and each value is an + * object defining the class. + */ + std::unordered_map<std::string, CesiumGltf::Class> classes; + + /** + * @brief A dictionary, where each key is an enum ID and each value is an + * object defining the values for the enum. + */ + std::unordered_map<std::string, CesiumGltf::Enum> enums; +}; +} // 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 0000000000000000000000000000000000000000..1900693d42d389224f33cf8c2efb584a84defd95 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltf/Skin.h @@ -0,0 +1,41 @@ +// This file was generated by generate-classes. +// DO NOT EDIT THIS FILE! +#pragma once + +#include "CesiumGltf/Library.h" +#include "CesiumGltf/NamedObject.h" + +#include <cstdint> +#include <vector> + +namespace CesiumGltf { +/** + * @brief Joints and matrices defining a skin. + */ +struct CESIUMGLTF_API Skin final : public CesiumGltf::NamedObject { + static inline 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<int32_t> joints; +}; +} // namespace CesiumGltf diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltf/Statistics.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltf/Statistics.h new file mode 100644 index 0000000000000000000000000000000000000000..98f2ebc77dc6fba7aefcbb8cdab9dc838dabcaea --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltf/Statistics.h @@ -0,0 +1,27 @@ +// This file was generated by generate-classes. +// DO NOT EDIT THIS FILE! +#pragma once + +#include "CesiumGltf/ClassStatistics.h" +#include "CesiumGltf/Library.h" + +#include <CesiumUtility/ExtensibleObject.h> + +#include <unordered_map> + +namespace CesiumGltf { +/** + * @brief Statistics about features. + */ +struct CESIUMGLTF_API Statistics final + : public CesiumUtility::ExtensibleObject { + static inline constexpr const char* TypeName = "Statistics"; + + /** + * @brief A dictionary, where each key is a class ID declared in the `classes` + * dictionary and each value is an object containing statistics about features + * that conform to the class. + */ + std::unordered_map<std::string, CesiumGltf::ClassStatistics> classes; +}; +} // 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 0000000000000000000000000000000000000000..0e914e0e18e50ba410a7b89abe6fcf353a5af710 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltf/Texture.h @@ -0,0 +1,30 @@ +// This file was generated by generate-classes. +// DO NOT EDIT THIS FILE! +#pragma once + +#include "CesiumGltf/Library.h" +#include "CesiumGltf/NamedObject.h" + +#include <cstdint> + +namespace CesiumGltf { +/** + * @brief A texture and its sampler. + */ +struct CESIUMGLTF_API Texture final : public CesiumGltf::NamedObject { + static inline 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; +}; +} // namespace CesiumGltf diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltf/TextureAccessor.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltf/TextureAccessor.h new file mode 100644 index 0000000000000000000000000000000000000000..97b52e28afb91a2811cef5aee6fd19a1bfcf8456 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltf/TextureAccessor.h @@ -0,0 +1,32 @@ +// This file was generated by generate-classes. +// DO NOT EDIT THIS FILE! +#pragma once + +#include "CesiumGltf/Library.h" +#include "CesiumGltf/TextureInfo.h" + +#include <CesiumUtility/ExtensibleObject.h> + +#include <string> + +namespace CesiumGltf { +/** + * @brief A description of how to access property values from the color channels + * of a texture. + */ +struct CESIUMGLTF_API TextureAccessor final + : public CesiumUtility::ExtensibleObject { + static inline constexpr const char* TypeName = "TextureAccessor"; + + /** + * @brief Texture channels containing property values. Channels are labeled by + * `rgba` and are swizzled with a string of 1-4 characters. + */ + std::string channels; + + /** + * @brief The glTF texture and texture coordinates to use. + */ + CesiumGltf::TextureInfo texture; +}; +} // 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 0000000000000000000000000000000000000000..f9f26c91efa1a684e54c0233d011c4972aa8b898 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltf/TextureInfo.h @@ -0,0 +1,35 @@ +// This file was generated by generate-classes. +// DO NOT EDIT THIS FILE! +#pragma once + +#include "CesiumGltf/Library.h" + +#include <CesiumUtility/ExtensibleObject.h> + +#include <cstdint> + +namespace CesiumGltf { +/** + * @brief Reference to a texture. + */ +struct CESIUMGLTF_API TextureInfo : public CesiumUtility::ExtensibleObject { + static inline 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_<set index>` 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; +}; +} // namespace CesiumGltf 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 0000000000000000000000000000000000000000..5795779e6ed3f0c39b245bba25d506e139b21f7e --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltfReader/GltfReader.h @@ -0,0 +1,196 @@ +#pragma once + +#include "CesiumGltfReader/Library.h" + +#include <CesiumAsync/AsyncSystem.h> +#include <CesiumAsync/Future.h> +#include <CesiumAsync/HttpHeaders.h> +#include <CesiumAsync/IAssetAccessor.h> +#include <CesiumGltf/ImageCesium.h> +#include <CesiumGltf/Ktx2TranscodeTargets.h> +#include <CesiumGltf/Model.h> +#include <CesiumJsonReader/ExtensionReaderContext.h> +#include <CesiumJsonReader/IExtensionJsonHandler.h> + +#include <gsl/span> + +#include <functional> +#include <memory> +#include <optional> +#include <string> +#include <vector> + +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<CesiumGltf::Model> model; + + /** + * @brief Errors, if any, that occurred during the load process. + */ + std::vector<std::string> errors; + + /** + * @brief Warnings, if any, that occurred during the load process. + */ + std::vector<std::string> warnings; +}; + +/** + * @brief The result of reading an image with + * {@link GltfReader::readImage}. + */ +struct CESIUMGLTFREADER_API ImageReaderResult { + + /** + * @brief The {@link ImageCesium} that was read. + * + * This will be `std::nullopt` if the image could not be read. + */ + std::optional<CesiumGltf::ImageCesium> image; + + /** + * @brief Error messages that occurred while trying to read the image. + */ + std::vector<std::string> errors; + + /** + * @brief Warning messages that occurred while reading the image. + */ + std::vector<std::string> 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 Model::buffers} should be + * automatically decoded as part of the load process. + * + * The {@link 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 geometry compressed using the `KHR_draco_mesh_compression` + * extension should be automatically decoded as part of the load process. + */ + bool decodeDraco = true; + + /** + * @brief For each possible input transmission format, this struct names + * the ideal target gpu-compressed pixel format to transcode to. + */ + CesiumGltf::Ktx2TranscodeTargets ktx2TranscodeTargets; +}; + +/** + * @brief Reads glTF models and images. + */ +class CESIUMGLTFREADER_API GltfReader { +public: + /** + * @brief Constructs a new instance. + */ + GltfReader(); + + /** + * @brief Gets the context used to control how extensions are loaded from glTF + * files. + */ + CesiumJsonReader::ExtensionReaderContext& getExtensions(); + + /** + * @brief Gets the context used to control how extensions are loaded from glTF + * files. + */ + const CesiumJsonReader::ExtensionReaderContext& 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 gsl::span<const std::byte>& data, + const GltfReaderOptions& options = GltfReaderOptions()) const; + + /** + * @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<GltfReaderResult> resolveExternalData( + CesiumAsync::AsyncSystem asyncSystem, + const std::string& baseUrl, + const CesiumAsync::HttpHeaders& headers, + std::shared_ptr<CesiumAsync::IAssetAccessor> pAssetAccessor, + const GltfReaderOptions& options, + GltfReaderResult&& result); + + /** + * @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 ktx2TranscodeTargetFormat 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 gsl::span<const std::byte>& 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<std::string> + generateMipMaps(CesiumGltf::ImageCesium& image); + +private: + CesiumJsonReader::ExtensionReaderContext _context; +}; + +} // namespace CesiumGltfReader diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltfReader/ImageManipulation.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltfReader/ImageManipulation.h new file mode 100644 index 0000000000000000000000000000000000000000..26fa73b7b864255d6a9e88ead930d28f8f8c4d17 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltfReader/ImageManipulation.h @@ -0,0 +1,100 @@ +#pragma once + +#include "CesiumGltfReader/Library.h" + +#include <cstddef> +#include <cstdint> + +// Forward declarations +namespace CesiumGltf { +struct ImageCesium; +} + +namespace CesiumGltfReader { + +/** + * @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; +}; + +class CESIUMGLTFREADER_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::ImageCesium& target, + const PixelRectangle& targetPixels, + const CesiumGltf::ImageCesium& source, + const PixelRectangle& sourcePixels); +}; + +} // 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 0000000000000000000000000000000000000000..d4f85b2aea240b722452f63d6e2d05f5d915814d --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltfReader/Library.h @@ -0,0 +1,16 @@ +#pragma once + +/** + * @brief Classes for reading [glTF](https://www.khronos.org/gltf/) models. + */ +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/CesiumGltfWriter/GltfWriter.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltfWriter/GltfWriter.h new file mode 100644 index 0000000000000000000000000000000000000000..9cedeee58340a0244aaa0b5cab255ed3cac7c918 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltfWriter/GltfWriter.h @@ -0,0 +1,112 @@ +#pragma once + +#include "CesiumGltfWriter/Library.h" + +#include <CesiumJsonWriter/ExtensionWriterContext.h> + +#include <gsl/span> + +// 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<std::byte> of the glTF or glb. + */ + std::vector<std::byte> gltfBytes; + + /** + * @brief Errors, if any, that occurred during the write process. + */ + std::vector<std::string> errors; + + /** + * @brief Warnings, if any, that occurred during the write process. + */ + std::vector<std::string> 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 or EXT_feature_metadata 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::ImageCesium} 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::ImageCesium}. + * + * @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 gsl::span<const std::byte>& 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 0000000000000000000000000000000000000000..65c6401277857c01c32b6bb0186e9f2e2ef11d84 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumGltfWriter/Library.h @@ -0,0 +1,16 @@ +#pragma once + +/** + * @brief Classes for writing [glTF](https://www.khronos.org/gltf/) models. + */ +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/CesiumIonClient/Assets.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumIonClient/Assets.h new file mode 100644 index 0000000000000000000000000000000000000000..dc736fa4c0de2a945a29723bf72d15a2b2c6eac3 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumIonClient/Assets.h @@ -0,0 +1,89 @@ +#pragma once + +#include <cstdint> +#include <string> +#include <vector> + +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; +}; + +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<Asset> 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 0000000000000000000000000000000000000000..ba04177b219aa92a129ef2dfc03a3b5c3c41e74f --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumIonClient/Connection.h @@ -0,0 +1,288 @@ +#pragma once + +#include "Assets.h" +#include "Profile.h" +#include "Response.h" +#include "Token.h" +#include "TokenList.h" + +#include <CesiumAsync/AsyncSystem.h> +#include <CesiumAsync/IAssetAccessor.h> +#include <CesiumAsync/Library.h> + +#include <cstdint> + +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<int32_t> limit; + + /** + * @brief The page number, where the first page of results is page 1 (not 0). + */ + std::optional<int32_t> 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<std::string> search; + + /** + * @brief The property by which to sort results. Valid values are + * `"NAME"` and `"LAST_USED"`. + */ + std::optional<std::string> sortBy; + + /** + * @brief The property by which to sort results. Valid values are + * `"NAME"` and `"LAST_USED"`. + */ + std::optional<SortOrder> 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 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<Connection> authorize( + const CesiumAsync::AsyncSystem& asyncSystem, + const std::shared_ptr<CesiumAsync::IAssetAccessor>& pAssetAccessor, + const std::string& friendlyApplicationName, + int64_t clientID, + const std::string& redirectPath, + const std::vector<std::string>& scopes, + std::function<void(const std::string&)>&& openUrlCallback, + const std::string& ionApiUrl = "https://api.cesium.com/", + const std::string& ionAuthorizeUrl = "https://cesium.com/ion/oauth"); + + /** + * @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 apiUrl The base URL of the Cesium ion API. + */ + Connection( + const CesiumAsync::AsyncSystem& asyncSystem, + const std::shared_ptr<CesiumAsync::IAssetAccessor>& pAssetAccessor, + const std::string& accessToken, + 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<CesiumAsync::IAssetAccessor>& + 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<Response<Profile>> me() const; + + /** + * @brief Gets the list of available assets. + * + * @return A future that resolves to the asset information. + */ + CesiumAsync::Future<Response<Assets>> 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<Response<TokenList>> + 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<Response<Asset>> 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<Response<Token>> 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<Response<TokenList>> + nextPage(const Response<TokenList>& 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<Response<TokenList>> + previousPage(const Response<TokenList>& 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<Response<Token>> createToken( + const std::string& name, + const std::vector<std::string>& scopes, + const std::optional<std::vector<int64_t>>& assetIds = std::nullopt, + const std::optional<std::vector<std::string>>& 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<Response<NoValue>> modifyToken( + const std::string& tokenID, + const std::string& newName, + const std::optional<std::vector<int64_t>>& newAssetIDs, + const std::vector<std::string>& newScopes, + const std::optional<std::vector<std::string>>& 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<std::string> getIdFromToken(const std::string& token); + +private: + static CesiumAsync::Future<Connection> completeTokenExchange( + const CesiumAsync::AsyncSystem& asyncSystem, + const std::shared_ptr<CesiumAsync::IAssetAccessor>& pAssetAccessor, + int64_t clientID, + const std::string& ionApiUrl, + const std::string& code, + const std::string& redirectUrl, + const std::string& codeVerifier); + + CesiumAsync::Future<Response<TokenList>> tokens(const std::string& url) const; + + CesiumAsync::AsyncSystem _asyncSystem; + std::shared_ptr<CesiumAsync::IAssetAccessor> _pAssetAccessor; + std::string _accessToken; + std::string _apiUrl; +}; +} // namespace CesiumIonClient 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 0000000000000000000000000000000000000000..20c744a8d85185cf41bcbd0e5aa97b27361c4f27 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumIonClient/Profile.h @@ -0,0 +1,74 @@ +#pragma once + +#include <cstdint> +#include <string> +#include <vector> + +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<std::string> 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 0000000000000000000000000000000000000000..9668c7571d2ec4db43167d7d1947d78c3affa6a4 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumIonClient/Response.h @@ -0,0 +1,94 @@ +#pragma once + +#include <cstdint> +#include <memory> +#include <optional> +#include <string> + +namespace CesiumAsync { +class IAssetRequest; +} + +namespace CesiumIonClient { + +/** + * @brief A response from Cesium ion. + * + * @tparam T The type of the response object. + */ +template <typename T> struct Response final { + Response(); + + Response( + const std::shared_ptr<CesiumAsync::IAssetRequest>& pRequest, + T&& value); + + Response( + T&& value, + uint16_t httpStatusCode, + const std::string& errorCode, + const std::string& 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<T> 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<std::string> 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<std::string> 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 0000000000000000000000000000000000000000..488136132724e50e0913978d5161582e35e0c12d --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumIonClient/Token.h @@ -0,0 +1,68 @@ +#pragma once + +#include <cstdint> +#include <optional> +#include <string> +#include <vector> + +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<std::vector<int64_t>> 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<std::vector<std::string>> allowedUrls{}; + + /** + * @brief The scopes granted by this token. + */ + std::vector<std::string> 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 0000000000000000000000000000000000000000..32da35148937a3b652a8caddf6d9fe30525ba638 --- /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<Token> 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 0000000000000000000000000000000000000000..d2902cc0b1b589cd52dbe1095c32fc4309fc9e91 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumJsonReader/ArrayJsonHandler.h @@ -0,0 +1,448 @@ +#pragma once + +#include "DoubleJsonHandler.h" +#include "IntegerJsonHandler.h" +#include "JsonHandler.h" +#include "Library.h" +#include "StringJsonHandler.h" + +#include <cassert> +#include <functional> +#include <memory> +#include <vector> + +namespace CesiumJsonReader { +template <typename T, typename THandler> +class CESIUMJSONREADER_API ArrayJsonHandler : public JsonHandler { +public: + template <typename... Ts> + ArrayJsonHandler(Ts&&... args) noexcept + : JsonHandler(), + _handlerFactory( + std::bind(handlerFactory<Ts...>, std::forward<Ts>(args)...)), + _objectHandler() {} + + void reset(IJsonHandler* pParent, std::vector<T>* 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(); + } + + 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<std::string>&& context = + std::vector<std::string>()) 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 <typename... Ts> static THandler* handlerFactory(Ts&&... args) { + return new THandler(std::forward<Ts>(args)...); + } + + std::vector<T>* _pArray = nullptr; + bool _arrayIsOpen = false; + + std::function<THandler*()> _handlerFactory; + std::unique_ptr<THandler> _objectHandler; +}; + +template <> +class CESIUMJSONREADER_API ArrayJsonHandler<double, DoubleJsonHandler> + : public JsonHandler { +public: + ArrayJsonHandler() noexcept : JsonHandler() {} + + void reset(IJsonHandler* pParent, std::vector<double>* 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); + } + + assert(this->_pArray); + this->_pArray->emplace_back(static_cast<double>(i)); + return this; + } + + virtual IJsonHandler* readUint32(uint32_t i) override { + if (!this->_arrayIsOpen) { + return this->invalid("An integer")->readUint32(i); + } + + assert(this->_pArray); + this->_pArray->emplace_back(static_cast<double>(i)); + return this; + } + + virtual IJsonHandler* readInt64(int64_t i) override { + if (!this->_arrayIsOpen) { + return this->invalid("An integer")->readInt64(i); + } + + assert(this->_pArray); + this->_pArray->emplace_back(static_cast<double>(i)); + return this; + } + + virtual IJsonHandler* readUint64(uint64_t i) override { + if (!this->_arrayIsOpen) { + return this->invalid("An integer")->readUint64(i); + } + + assert(this->_pArray); + this->_pArray->emplace_back(static_cast<double>(i)); + return this; + } + + virtual IJsonHandler* readDouble(double d) override { + if (!this->_arrayIsOpen) { + return this->invalid("An integer")->readDouble(d); + } + + 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<std::string>&& context = + std::vector<std::string>()) 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<double>* _pArray = nullptr; + bool _arrayIsOpen = false; +}; + +template <typename T> +class CESIUMJSONREADER_API ArrayJsonHandler<T, IntegerJsonHandler<T>> + : public JsonHandler { +public: + ArrayJsonHandler() noexcept : JsonHandler() {} + + void reset(IJsonHandler* pParent, std::vector<T>* 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 null")->readBool(b); + } + + virtual IJsonHandler* readInt32(int32_t i) override { + if (!this->_arrayIsOpen) { + return this->invalid("An integer")->readInt32(i); + } + + assert(this->_pArray); + this->_pArray->emplace_back(static_cast<T>(i)); + return this; + } + + virtual IJsonHandler* readUint32(uint32_t i) override { + if (!this->_arrayIsOpen) { + return this->invalid("An integer")->readUint32(i); + } + + assert(this->_pArray); + this->_pArray->emplace_back(static_cast<T>(i)); + return this; + } + + virtual IJsonHandler* readInt64(int64_t i) override { + if (!this->_arrayIsOpen) { + return this->invalid("An integer")->readInt64(i); + } + + assert(this->_pArray); + this->_pArray->emplace_back(static_cast<T>(i)); + return this; + } + + virtual IJsonHandler* readUint64(uint64_t i) override { + if (!this->_arrayIsOpen) { + return this->invalid("An integer")->readUint64(i); + } + + assert(this->_pArray); + this->_pArray->emplace_back(static_cast<T>(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<std::string>&& context = + std::vector<std::string>()) 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<T>* _pArray = nullptr; + bool _arrayIsOpen = false; +}; + +template <> +class CESIUMJSONREADER_API ArrayJsonHandler<std::string, StringJsonHandler> + : public JsonHandler { +public: + ArrayJsonHandler() noexcept : JsonHandler() {} + + void reset(IJsonHandler* pParent, std::vector<std::string>* 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); + } + + assert(this->_pArray); + this->_pArray->emplace_back(str); + return this; + } + + virtual void reportWarning( + const std::string& warning, + std::vector<std::string>&& context = + std::vector<std::string>()) 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<std::string>* _pArray = nullptr; + bool _arrayIsOpen = false; +}; +} // 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 0000000000000000000000000000000000000000..1aa34585668cd4a3a13c7383e56cf9385251a7db --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumJsonReader/BoolJsonHandler.h @@ -0,0 +1,17 @@ +#pragma once + +#include "JsonHandler.h" +#include "Library.h" + +namespace CesiumJsonReader { +class CESIUMJSONREADER_API BoolJsonHandler : public JsonHandler { +public: + BoolJsonHandler() noexcept; + void reset(IJsonHandler* pParent, bool* pBool); + + 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 0000000000000000000000000000000000000000..fff6c1261311b9172816801d836c73023e92214e --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumJsonReader/DictionaryJsonHandler.h @@ -0,0 +1,49 @@ +#pragma once + +#include "IntegerJsonHandler.h" +#include "Library.h" +#include "ObjectJsonHandler.h" + +#include <map> +#include <unordered_map> + +namespace CesiumJsonReader { +template <typename T, typename THandler> +class CESIUMJSONREADER_API DictionaryJsonHandler : public ObjectJsonHandler { +public: + template <typename... Ts> + DictionaryJsonHandler(Ts&&... args) noexcept + : ObjectJsonHandler(), _item(std::forward<Ts>(args)...) {} + + void reset( + IJsonHandler* pParent, + std::unordered_map<std::string, T>* pDictionary) { + ObjectJsonHandler::reset(pParent); + this->_pDictionary1 = pDictionary; + } + + void reset(IJsonHandler* pParent, std::map<std::string, T>* pDictionary) { + ObjectJsonHandler::reset(pParent); + this->_pDictionary2 = pDictionary; + } + + virtual IJsonHandler* readObjectKey(const std::string_view& str) override { + 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<std::string, T>* _pDictionary1 = nullptr; + std::map<std::string, T>* _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 0000000000000000000000000000000000000000..cd4669489fb8ccc9083c959555ac747e091a15e1 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumJsonReader/DoubleJsonHandler.h @@ -0,0 +1,23 @@ +#pragma once + +#include "JsonHandler.h" +#include "Library.h" + +#include <cassert> + +namespace CesiumJsonReader { +class CESIUMJSONREADER_API DoubleJsonHandler : public JsonHandler { +public: + DoubleJsonHandler() noexcept; + void reset(IJsonHandler* pParent, double* pDouble); + + virtual IJsonHandler* readInt32(int32_t i) override; + virtual IJsonHandler* readUint32(uint32_t i) override; + virtual IJsonHandler* readInt64(int64_t i) override; + virtual IJsonHandler* readUint64(uint64_t i) override; + 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 0000000000000000000000000000000000000000..d4b4cf2956efb63d5d66c7d88e508562de3a4238 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumJsonReader/ExtensibleObjectJsonHandler.h @@ -0,0 +1,33 @@ +#pragma once + +#include "DictionaryJsonHandler.h" +#include "ExtensionReaderContext.h" +#include "ExtensionsJsonHandler.h" +#include "JsonObjectJsonHandler.h" +#include "ObjectJsonHandler.h" + +#include <CesiumUtility/ExtensibleObject.h> +#include <CesiumUtility/JsonValue.h> + +namespace CesiumJsonReader { + +class ExtensibleObjectJsonHandler : public CesiumJsonReader::ObjectJsonHandler { +public: + explicit ExtensibleObjectJsonHandler( + const ExtensionReaderContext& context) noexcept; + +protected: + void reset(IJsonHandler* pParent, CesiumUtility::ExtensibleObject* pObject); + IJsonHandler* readObjectKeyExtensibleObject( + const std::string& objectType, + const std::string_view& str, + CesiumUtility::ExtensibleObject& o); + +private: + CesiumJsonReader::DictionaryJsonHandler< + CesiumUtility::JsonValue, + CesiumJsonReader::JsonObjectJsonHandler> + _extras; + ExtensionsJsonHandler _extensions; +}; +} // namespace CesiumJsonReader diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumJsonReader/ExtensionReaderContext.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumJsonReader/ExtensionReaderContext.h new file mode 100644 index 0000000000000000000000000000000000000000..7453a519df5490390ed3a8e5add9f10e9dc8b419 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumJsonReader/ExtensionReaderContext.h @@ -0,0 +1,124 @@ +#pragma once + +#include "IExtensionJsonHandler.h" +#include "Library.h" + +#include <functional> +#include <map> +#include <memory> +#include <optional> +#include <string> +#include <vector> + +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 +}; + +class CESIUMJSONREADER_API ExtensionReaderContext { +public: + /** + * @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 <typename TExtended, typename TExtensionHandler> + void registerExtension(const std::string& extensionName) { + auto it = + this->_extensions.emplace(extensionName, ObjectTypeToHandler()).first; + it->second.insert_or_assign( + TExtended::TypeName, + ExtensionReaderFactory([](const ExtensionReaderContext& context) { + return std::make_unique<TExtensionHandler>(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 <typename TExtended, typename TExtensionHandler> + void registerExtension() { + auto it = + this->_extensions + .emplace(TExtensionHandler::ExtensionName, ObjectTypeToHandler()) + .first; + it->second.insert_or_assign( + TExtended::TypeName, + ExtensionHandlerFactory([](const ExtensionReaderContext& context) { + return std::make_unique<TExtensionHandler>(context); + })); + } + + /** + * @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); + + std::unique_ptr<IExtensionJsonHandler> createExtensionHandler( + const std::string_view& extensionName, + const std::string& extendedObjectType) const; + +private: + using ExtensionHandlerFactory = + std::function<std::unique_ptr<IExtensionJsonHandler>( + const ExtensionReaderContext&)>; + using ObjectTypeToHandler = std::map<std::string, ExtensionHandlerFactory>; + using ExtensionNameMap = std::map<std::string, ObjectTypeToHandler>; + + ExtensionNameMap _extensions; + std::unordered_map<std::string, ExtensionState> _extensionStates; +}; + +} // 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 0000000000000000000000000000000000000000..e8616b205b8d606ff3c3e1d8ddc5101cc1f2d83b --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumJsonReader/ExtensionsJsonHandler.h @@ -0,0 +1,35 @@ +#pragma once + +#include "ExtensionReaderContext.h" +#include "IExtensionJsonHandler.h" +#include "ObjectJsonHandler.h" + +#include <CesiumUtility/ExtensibleObject.h> + +#include <memory> + +namespace CesiumJsonReader { + +class ExtensionsJsonHandler : public CesiumJsonReader::ObjectJsonHandler { +public: + explicit ExtensionsJsonHandler(const ExtensionReaderContext& context) noexcept + : ObjectJsonHandler(), + _context(context), + _pObject(nullptr), + _currentExtensionHandler() {} + + void reset( + IJsonHandler* pParent, + CesiumUtility::ExtensibleObject* pObject, + const std::string& objectType); + + virtual IJsonHandler* readObjectKey(const std::string_view& str) override; + +private: + const ExtensionReaderContext& _context; + CesiumUtility::ExtensibleObject* _pObject = nullptr; + std::string _objectType; + std::unique_ptr<IExtensionJsonHandler> _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 0000000000000000000000000000000000000000..c640ff1c6cbbdc56c03dbf994fd5352151dc282c --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumJsonReader/IExtensionJsonHandler.h @@ -0,0 +1,20 @@ +#pragma once + +#include "IJsonHandler.h" + +#include <CesiumUtility/ExtensibleObject.h> + +#include <any> +#include <string_view> + +namespace CesiumJsonReader { + +class IExtensionJsonHandler : public IJsonHandler { +public: + virtual void reset( + IJsonHandler* pParentHandler, + CesiumUtility::ExtensibleObject& o, + const std::string_view& extensionName) = 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 0000000000000000000000000000000000000000..e36f6b7fee14456b3ef19f1153a23f4dec36acb9 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumJsonReader/IJsonHandler.h @@ -0,0 +1,31 @@ +#pragma once + +#include "Library.h" + +#include <cstdint> +#include <string_view> +#include <vector> + +namespace CesiumJsonReader { +class CESIUMJSONREADER_API IJsonHandler { +public: + virtual ~IJsonHandler(){}; + virtual IJsonHandler* readNull() = 0; + virtual IJsonHandler* readBool(bool b) = 0; + virtual IJsonHandler* readInt32(int32_t i) = 0; + virtual IJsonHandler* readUint32(uint32_t i) = 0; + virtual IJsonHandler* readInt64(int64_t i) = 0; + virtual IJsonHandler* readUint64(uint64_t i) = 0; + virtual IJsonHandler* readDouble(double d) = 0; + virtual IJsonHandler* readString(const std::string_view& str) = 0; + virtual IJsonHandler* readObjectStart() = 0; + virtual IJsonHandler* readObjectKey(const std::string_view& str) = 0; + virtual IJsonHandler* readObjectEnd() = 0; + virtual IJsonHandler* readArrayStart() = 0; + virtual IJsonHandler* readArrayEnd() = 0; + + virtual void reportWarning( + const std::string& warning, + std::vector<std::string>&& context = std::vector<std::string>()) = 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 0000000000000000000000000000000000000000..2adc9f917156cc06fecd6909d302a9c4fb00b682 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumJsonReader/IgnoreValueJsonHandler.h @@ -0,0 +1,37 @@ +#pragma once + +#include "IJsonHandler.h" +#include "Library.h" + +#include <cstdint> + +namespace CesiumJsonReader { +class CESIUMJSONREADER_API IgnoreValueJsonHandler : public IJsonHandler { +public: + void reset(IJsonHandler* pParent) noexcept; + + virtual IJsonHandler* readNull() override; + virtual IJsonHandler* readBool(bool b) override; + virtual IJsonHandler* readInt32(int32_t i) override; + virtual IJsonHandler* readUint32(uint32_t i) override; + virtual IJsonHandler* readInt64(int64_t i) override; + virtual IJsonHandler* readUint64(uint64_t i) override; + virtual IJsonHandler* readDouble(double d) override; + virtual IJsonHandler* readString(const std::string_view& str) override; + virtual IJsonHandler* readObjectStart() override; + virtual IJsonHandler* readObjectKey(const std::string_view& str) override; + virtual IJsonHandler* readObjectEnd() override; + virtual IJsonHandler* readArrayStart() override; + virtual IJsonHandler* readArrayEnd() override; + + virtual void reportWarning( + const std::string& warning, + std::vector<std::string>&& context = std::vector<std::string>()) override; + + 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 0000000000000000000000000000000000000000..439b00c619c9e0dd658b81dcdd0a5235ef962a34 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumJsonReader/IntegerJsonHandler.h @@ -0,0 +1,63 @@ +#pragma once + +#include "JsonHandler.h" +#include "Library.h" + +#include <cassert> +#include <cmath> + +namespace CesiumJsonReader { +template <typename T> +class CESIUMJSONREADER_API IntegerJsonHandler : public JsonHandler { +public: + IntegerJsonHandler() noexcept : JsonHandler() {} + + void reset(IJsonHandler* pParent, T* pInteger) { + JsonHandler::reset(pParent); + this->_pInteger = pInteger; + } + + T* getObject() { return this->_pInteger; } + + virtual IJsonHandler* readInt32(int32_t i) override { + assert(this->_pInteger); + *this->_pInteger = static_cast<T>(i); + return this->parent(); + } + virtual IJsonHandler* readUint32(uint32_t i) override { + assert(this->_pInteger); + *this->_pInteger = static_cast<T>(i); + return this->parent(); + } + virtual IJsonHandler* readInt64(int64_t i) override { + assert(this->_pInteger); + *this->_pInteger = static_cast<T>(i); + return this->parent(); + } + virtual IJsonHandler* readUint64(uint64_t i) override { + assert(this->_pInteger); + *this->_pInteger = static_cast<T>(i); + return this->parent(); + } + virtual IJsonHandler* readDouble(double d) override { + assert(this->_pInteger); + double intPart; + double fractPart = std::modf(d, &intPart); + if (fractPart != 0) { + return JsonHandler::readDouble(d); + } + *this->_pInteger = static_cast<T>(intPart); + return this->parent(); + } + + virtual void reportWarning( + const std::string& warning, + std::vector<std::string>&& 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 0000000000000000000000000000000000000000..e05c5025800807906b7527c171080223cc51d13f --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumJsonReader/JsonHandler.h @@ -0,0 +1,53 @@ +#pragma once + +#include "IJsonHandler.h" +#include "IgnoreValueJsonHandler.h" +#include "Library.h" + +#include <cstdint> +#include <string> + +namespace CesiumJsonReader { +class CESIUMJSONREADER_API JsonHandler : public IJsonHandler { +public: + JsonHandler() noexcept; + virtual IJsonHandler* readNull() override; + virtual IJsonHandler* readBool(bool b) override; + virtual IJsonHandler* readInt32(int32_t i) override; + virtual IJsonHandler* readUint32(uint32_t i) override; + virtual IJsonHandler* readInt64(int64_t i) override; + virtual IJsonHandler* readUint64(uint64_t i) override; + virtual IJsonHandler* readDouble(double d) override; + virtual IJsonHandler* readString(const std::string_view& str) override; + virtual IJsonHandler* readObjectStart() override; + virtual IJsonHandler* readObjectKey(const std::string_view& str) override; + virtual IJsonHandler* readObjectEnd() override; + virtual IJsonHandler* readArrayStart() override; + virtual IJsonHandler* readArrayEnd() override; + + virtual void reportWarning( + const std::string& warning, + std::vector<std::string>&& context = std::vector<std::string>()) override; + +protected: + void reset(IJsonHandler* pParent); + + 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 0000000000000000000000000000000000000000..824e5b39b60d4fa2e359c9e43565ac65985850e0 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumJsonReader/JsonObjectJsonHandler.h @@ -0,0 +1,37 @@ +#pragma once + +#include "JsonHandler.h" +#include "Library.h" + +#include <CesiumUtility/JsonValue.h> + +namespace CesiumJsonReader { + +class CESIUMJSONREADER_API JsonObjectJsonHandler : public JsonHandler { +public: + JsonObjectJsonHandler() noexcept; + + void reset(IJsonHandler* pParent, CesiumUtility::JsonValue* pValue); + + virtual IJsonHandler* readNull() override; + virtual IJsonHandler* readBool(bool b) override; + virtual IJsonHandler* readInt32(int32_t i) override; + virtual IJsonHandler* readUint32(uint32_t i) override; + virtual IJsonHandler* readInt64(int64_t i) override; + virtual IJsonHandler* readUint64(uint64_t i) override; + virtual IJsonHandler* readDouble(double d) override; + virtual IJsonHandler* readString(const std::string_view& str) override; + virtual IJsonHandler* readObjectStart() override; + virtual IJsonHandler* readObjectKey(const std::string_view& str) override; + virtual IJsonHandler* readObjectEnd() override; + virtual IJsonHandler* readArrayStart() override; + virtual IJsonHandler* readArrayEnd() override; + +private: + IJsonHandler* doneElement(); + + std::vector<CesiumUtility::JsonValue*> _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 0000000000000000000000000000000000000000..3680acaa0166d19ddf6a8c651687bde1f3dd1cca --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumJsonReader/JsonReader.h @@ -0,0 +1,97 @@ +#pragma once + +#include "JsonHandler.h" +#include "Library.h" + +#include <gsl/span> + +#include <cstddef> +#include <optional> +#include <string> +#include <vector> + +namespace rapidjson { +struct MemoryStream; +} + +namespace CesiumJsonReader { + +/** + * @brief The result of {@link Reader::readJson}. + */ +template <typename T> struct ReadJsonResult { + /** + * @brief The value read from the JSON, or `std::nullopt` on error. + */ + std::optional<T> value; + + /** + * @brief Errors that occurred while reading. + */ + std::vector<std::string> errors; + + /** + * @brief Warnings that occurred while reading. + */ + std::vector<std::string> warnings; +}; + +/** + * @brief Reads JSON. + */ +class CESIUMJSONREADER_API JsonReader { +public: + /** + * @brief Reads JSON from a byte buffer. + * + * @param data The buffer from which to read JSON. + * @param handler The handler to receive the top-level JSON object. + * @return The result of reading the JSON. + */ + template <typename T> + static ReadJsonResult<typename T::ValueType> + readJson(const gsl::span<const std::byte>& data, T& handler) { + ReadJsonResult<typename T::ValueType> 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; + } + +private: + class FinalJsonHandler : public JsonHandler { + public: + FinalJsonHandler(std::vector<std::string>& warnings); + virtual void reportWarning( + const std::string& warning, + std::vector<std::string>&& context) override; + void setInputStream(rapidjson::MemoryStream* pInputStream) noexcept; + + private: + std::vector<std::string>& _warnings; + rapidjson::MemoryStream* _pInputStream; + }; + + static void internalRead( + const gsl::span<const std::byte>& data, + IJsonHandler& handler, + FinalJsonHandler& finalHandler, + std::vector<std::string>& errors, + std::vector<std::string>& warnings); +}; + +} // 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 0000000000000000000000000000000000000000..1a44da88ecbcf0e0e48575c9ca02b58c73af0f02 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumJsonReader/Library.h @@ -0,0 +1,16 @@ +#pragma once + +/** + * @brief Classes for reading JSON. + */ +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 0000000000000000000000000000000000000000..d5d4e89236bf1a98f1b1faa6c31a62cf3015c73a --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumJsonReader/ObjectJsonHandler.h @@ -0,0 +1,56 @@ +#pragma once + +#include "JsonHandler.h" +#include "Library.h" + +#include <optional> + +namespace CesiumJsonReader { +class CESIUMJSONREADER_API ObjectJsonHandler : public JsonHandler { +public: + ObjectJsonHandler() noexcept : JsonHandler() {} + + virtual IJsonHandler* readObjectStart() override /* final */; + virtual IJsonHandler* readObjectEnd() override /* final */; + +protected: + virtual IJsonHandler* StartSubObject() noexcept; + virtual IJsonHandler* EndSubObject() noexcept; + + template <typename TAccessor, typename TProperty> + IJsonHandler* + property(const char* currentKey, TAccessor& accessor, TProperty& value) { + this->_currentKey = currentKey; + + if constexpr (isOptional<TProperty>::value) { + value.emplace(); + accessor.reset(this, &value.value()); + } else { + accessor.reset(this, &value); + } + + return &accessor; + } + + const char* getCurrentKey() const noexcept; + + virtual void reportWarning( + const std::string& warning, + std::vector<std::string>&& context = std::vector<std::string>()) override; + +protected: + void setCurrentKey(const char* key) noexcept; + +private: + template <typename T> struct isOptional { + static constexpr bool value = false; + }; + + template <typename T> struct isOptional<std::optional<T>> { + static constexpr bool value = true; + }; + + int32_t _depth = 0; + const char* _currentKey = nullptr; +}; +} // 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 0000000000000000000000000000000000000000..799950cd3d77dc52f956a10eda37f41d8c84873f --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumJsonReader/StringJsonHandler.h @@ -0,0 +1,19 @@ +#pragma once + +#include "JsonHandler.h" +#include "Library.h" + +#include <string> + +namespace CesiumJsonReader { +class CESIUMJSONREADER_API StringJsonHandler : public JsonHandler { +public: + StringJsonHandler() noexcept; + void reset(IJsonHandler* pParent, std::string* pString); + std::string* getObject() noexcept; + 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 0000000000000000000000000000000000000000..626cdabf5a830c818ac82126502336692095af99 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumJsonWriter/ExtensionWriterContext.h @@ -0,0 +1,126 @@ +#pragma once + +#include "CesiumJsonWriter/JsonWriter.h" +#include "CesiumJsonWriter/Library.h" + +#include <any> +#include <functional> +#include <map> +#include <string> +#include <unordered_map> + +namespace CesiumJsonWriter { + +/** + * @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 +}; + +class CESIUMJSONWRITER_API ExtensionWriterContext { +private: + template <typename TExtension> + 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 + * {@link CesiumJsonReader::JsonHandler}. + * @param extensionName The name of the extension. + */ + template <typename TExtended, typename TExtensionHandler> + 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<const TExtension&>(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 + * {@link CesiumJsonReader::JsonHandler}. + */ + template <typename TExtended, typename TExtensionHandler> + void registerExtension() { + registerExtension<TExtended, TExtensionHandler>( + TExtensionHandler::ExtensionName); + } + + /** + * @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); + + ExtensionHandler<std::any> createExtensionHandler( + const std::string_view& extensionName, + const std::string& extendedObjectType) const; + +private: + using ObjectTypeToHandler = + std::unordered_map<std::string, ExtensionHandler<std::any>>; + using ExtensionNameMap = std::map<std::string, ObjectTypeToHandler>; + + ExtensionNameMap _extensions; + std::unordered_map<std::string, ExtensionState> _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 0000000000000000000000000000000000000000..2866bfd3b2e9600d5b9b0af844964a46a31a1be8 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumJsonWriter/JsonObjectWriter.h @@ -0,0 +1,15 @@ +#pragma once + +// forward declarations +namespace CesiumJsonWriter { +class JsonWriter; +} + +// forward declarations +namespace CesiumUtility { +class JsonValue; +} + +namespace CesiumJsonWriter { +void writeJsonValue(const CesiumUtility::JsonValue& value, JsonWriter& writer); +} 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 0000000000000000000000000000000000000000..fbceb569123e50436598e7a2150a7d2b5a1a8a9e --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumJsonWriter/JsonWriter.h @@ -0,0 +1,75 @@ +#pragma once + +#include <rapidjson/stringbuffer.h> +#include <rapidjson/writer.h> + +#include <cstddef> +#include <cstdint> +#include <functional> +#include <memory> +#include <string_view> +#include <vector> + +namespace CesiumJsonWriter { +class JsonWriter { + rapidjson::StringBuffer _compactBuffer; + std::unique_ptr<rapidjson::Writer<rapidjson::StringBuffer>> compact; + +public: + JsonWriter(); + virtual ~JsonWriter() {} + + // rapidjson methods + virtual bool Null(); + virtual bool Bool(bool b); + virtual bool Int(int i); + virtual bool Uint(unsigned int i); + virtual bool Uint64(std::uint64_t i); + virtual bool Int64(std::int64_t i); + virtual bool Double(double d); + virtual bool RawNumber(const char* str, unsigned int length, bool copy); + virtual bool Key(std::string_view string); + virtual bool String(std::string_view string); + virtual bool StartObject(); + virtual bool EndObject(); + virtual bool StartArray(); + virtual bool EndArray(); + + // Primitive overloads + virtual void Primitive(std::int32_t value); + virtual void Primitive(std::uint32_t value); + virtual void Primitive(std::int64_t value); + virtual void Primitive(std::uint64_t value); + virtual void Primitive(float value); + virtual void Primitive(double value); + virtual void Primitive(std::nullptr_t value); + virtual void Primitive(std::string_view string); + + // Integral + virtual void KeyPrimitive(std::string_view keyName, std::int32_t value); + virtual void KeyPrimitive(std::string_view keyName, std::uint32_t value); + virtual void KeyPrimitive(std::string_view keyName, std::int64_t value); + virtual void KeyPrimitive(std::string_view keyName, std::uint64_t value); + + // String + virtual void KeyPrimitive(std::string_view keyName, std::string_view value); + + // Floating Point + virtual void KeyPrimitive(std::string_view keyName, float value); + virtual void KeyPrimitive(std::string_view keyName, double value); + + // Null + virtual void KeyPrimitive(std::string_view keyName, std::nullptr_t value); + + // Array / Objects + virtual void + KeyArray(std::string_view keyName, std::function<void(void)> insideArray); + + virtual void + KeyObject(std::string_view keyName, std::function<void(void)> insideObject); + + virtual std::string toString(); + virtual std::string_view toStringView(); + virtual std::vector<std::byte> toBytes(); +}; +} // 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 0000000000000000000000000000000000000000..e7b1ba5f8efa3b54e370712a4d697d0b6e129316 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumJsonWriter/Library.h @@ -0,0 +1,16 @@ +#pragma once + +/** + * @brief Classes for writing JSON. + */ +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 0000000000000000000000000000000000000000..44d26b1ab5a9fd02061d728d30b553eb892c3cd6 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumJsonWriter/PrettyJsonWriter.h @@ -0,0 +1,78 @@ +#pragma once + +#include "JsonWriter.h" + +#include <rapidjson/prettywriter.h> +#include <rapidjson/stringbuffer.h> + +#include <cstdint> +#include <functional> +#include <memory> +#include <string_view> +#include <vector> + +namespace CesiumJsonWriter { + +class PrettyJsonWriter : public JsonWriter { + rapidjson::StringBuffer _prettyBuffer; + std::unique_ptr<rapidjson::PrettyWriter<rapidjson::StringBuffer>> pretty; + +public: + PrettyJsonWriter() noexcept; + ~PrettyJsonWriter() {} + + // rapidjson methods + 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; + + // Primitive overloads + 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; + + // Integral + 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; + + // String + void KeyPrimitive(std::string_view keyName, std::string_view value) override; + + // Floating Point + void KeyPrimitive(std::string_view keyName, float value) override; + void KeyPrimitive(std::string_view keyName, double value) override; + + // Null + void KeyPrimitive(std::string_view keyName, std::nullptr_t value) override; + + // Array / Objects + void KeyArray(std::string_view keyName, std::function<void(void)> insideArray) + override; + + void KeyObject( + std::string_view keyName, + std::function<void(void)> insideObject) override; + + std::string toString() override; + std::string_view toStringView() override; + std::vector<std::byte> 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 0000000000000000000000000000000000000000..a1d89578307624170aa02f3385df39726465ff6d --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumJsonWriter/writeJsonExtensions.h @@ -0,0 +1,27 @@ +#pragma once + +#include "CesiumJsonWriter/ExtensionWriterContext.h" +#include "CesiumJsonWriter/JsonWriter.h" + +namespace CesiumJsonWriter { +template <typename TExtended> +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, TExtended::TypeName); + if (!handler) { + continue; + } + jsonWriter.Key(item.first); + handler(item.second, jsonWriter, context); + } + jsonWriter.EndObject(); +} +} // namespace CesiumJsonWriter 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 0000000000000000000000000000000000000000..4785b79477789bd26de76f890fcc69d1d0cb9a63 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumUtility/DoublyLinkedList.h @@ -0,0 +1,247 @@ +#pragma once + +#include <cstddef> + +namespace CesiumUtility { + +/** + * @brief Contains the previous and next pointers for an element in + * a {@link DoublyLinkedList}. + */ +template <class T> 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(DoublyLinkedListPointers& rhs) noexcept + : DoublyLinkedListPointers() {} + + /** + * @brief Assignment operator. + */ + DoublyLinkedListPointers& + operator=(const DoublyLinkedListPointers& /*rhs*/) noexcept { + return *this; + } + +private: + template < + class TElement, + DoublyLinkedListPointers<TElement>(TElement::*Pointers)> + friend class DoublyLinkedList; + + 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 <class T, DoublyLinkedListPointers<T>(T::*Pointers)> +class DoublyLinkedList final { +public: + /** + * @brief Removes the given node from this list. + */ + void remove(T& node) noexcept { + DoublyLinkedListPointers<T>& nodePointers = node.*Pointers; + + if (nodePointers.pPrevious) { + DoublyLinkedListPointers<T>& 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<T>& 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<T>& afterPointers = after.*Pointers; + DoublyLinkedListPointers<T>& nodePointers = node.*Pointers; + + nodePointers.pPrevious = &after; + nodePointers.pNext = afterPointers.pNext; + afterPointers.pNext = &node; + + if (nodePointers.pNext) { + DoublyLinkedListPointers<T>& 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<T>& beforePointers = before.*Pointers; + DoublyLinkedListPointers<T>& nodePointers = node.*Pointers; + + nodePointers.pPrevious = beforePointers.pPrevious; + nodePointers.pNext = &before; + beforePointers.pPrevious = &node; + + if (nodePointers.pPrevious) { + DoublyLinkedListPointers<T>& 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; + } + +private: + size_t _size = 0; + T* _pHead = nullptr; + T* _pTail = nullptr; +}; + +} // 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 0000000000000000000000000000000000000000..803fcbcf05a8d2e8c4b6549a490487c452344878 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumUtility/ExtensibleObject.h @@ -0,0 +1,99 @@ +#pragma once + +#include "JsonValue.h" +#include "Library.h" + +#include <any> +#include <unordered_map> +#include <utility> +#include <vector> + +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 <typename T> 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 <typename T> const T* getExtension() const noexcept { + auto it = this->extensions.find(T::ExtensionName); + if (it == this->extensions.end()) { + return nullptr; + } + + return std::any_cast<T>(&it->second); + } + + /** @copydoc ExtensibleObject::getExtension */ + template <typename T> T* getExtension() noexcept { + return const_cast<T*>(std::as_const(*this).getExtension<T>()); + } + + /** + * @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 <typename T> T& addExtension() { + std::any& extension = + extensions.try_emplace(T::ExtensionName, std::make_any<T>()) + .first->second; + return std::any_cast<T&>(extension); + } + + /** + * @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<std::string, std::any> 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; +}; +} // 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 0000000000000000000000000000000000000000..5a0169d5f140b9b508229757a8bc35b56038f82d --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumUtility/IntrusivePointer.h @@ -0,0 +1,207 @@ +#pragma once +#include <type_traits> +#include <utility> + +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 T> class IntrusivePointer final { +public: + /** + * @brief Default constructor. + */ + IntrusivePointer(T* p = nullptr) noexcept : _p(p) { this->addReference(); } + + /** + * @brief Copy constructor. + */ + IntrusivePointer(const IntrusivePointer<T>& 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 <class U> + IntrusivePointer(const IntrusivePointer<U>& rhs) noexcept : _p(rhs._p) { + this->addReference(); + } + + /** + * @brief Move constructor. + */ + IntrusivePointer(IntrusivePointer<T>&& 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 <class U> + IntrusivePointer(IntrusivePointer<U>&& rhs) noexcept + : _p(std::exchange(rhs._p, nullptr)) { + // Reference count is unchanged + } + + /** + * @brief Default destructor. + */ + ~IntrusivePointer() noexcept { this->releaseReference(); } + + /** + * @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; + } + template <class U> + IntrusivePointer& operator=(const IntrusivePointer<U>& 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<T>& rhs) const noexcept { + return this->_p == rhs._p; + } + template <class U> + bool operator==(const IntrusivePointer<U>& rhs) const noexcept { + return this->_p == rhs._p; + } + + /** + * @brief Returns `true` if two pointers are *not* equal. + */ + bool operator!=(const IntrusivePointer<T>& 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 <typename U> friend class IntrusivePointer; +}; + +template <typename T, typename U> +IntrusivePointer<T> +const_intrusive_cast(const IntrusivePointer<U>& p) noexcept { + return IntrusivePointer<T>(const_cast<T*>(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 0000000000000000000000000000000000000000..dc695bedb4c40c06ebc813a6b7997b0ad603fdd2 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumUtility/JsonHelpers.h @@ -0,0 +1,94 @@ +#pragma once + +#include <glm/mat4x4.hpp> +#include <rapidjson/fwd.h> + +#include <optional> +#include <string> +#include <vector> + +namespace CesiumUtility { + +class JsonHelpers final { +public: + static std::optional<double> + getScalarProperty(const rapidjson::Value& tileJson, const std::string& key); + static std::optional<glm::dmat4x4> 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<std::vector<double>> getDoubles( + const rapidjson::Value& json, + int32_t expectedSize, + const std::string& key); + + static std::string getStringOrDefault( + const rapidjson::Value& json, + const std::string& key, + const std::string& defaultValue); + static std::string getStringOrDefault( + const rapidjson::Value& json, + const std::string& defaultValue); + + static double getDoubleOrDefault( + const rapidjson::Value& json, + const std::string& key, + double defaultValue); + static double + getDoubleOrDefault(const rapidjson::Value& json, double defaultValue); + + static uint32_t getUint32OrDefault( + const rapidjson::Value& json, + const std::string& key, + uint32_t defaultValue); + static uint32_t + getUint32OrDefault(const rapidjson::Value& json, uint32_t defaultValue); + + static int32_t getInt32OrDefault( + const rapidjson::Value& json, + const std::string& key, + int32_t defaultValue); + static int32_t + getInt32OrDefault(const rapidjson::Value& json, int32_t defaultValue); + + static uint64_t getUint64OrDefault( + const rapidjson::Value& json, + const std::string& key, + uint64_t defaultValue); + static uint64_t + getUint64OrDefault(const rapidjson::Value& json, uint64_t defaultValue); + + static int64_t getInt64OrDefault( + const rapidjson::Value& json, + const std::string& key, + int64_t defaultValue); + static int64_t + getInt64OrDefault(const rapidjson::Value& json, int64_t defaultValue); + + static bool getBoolOrDefault( + const rapidjson::Value& json, + const std::string& key, + bool defaultValue); + static bool getBoolOrDefault(const rapidjson::Value& json, bool defaultValue); + + static std::vector<std::string> + getStrings(const rapidjson::Value& json, const std::string& key); + static std::vector<int64_t> + 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 0000000000000000000000000000000000000000..47773ed14c38dda06eccaa9c5768750c06df2652 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumUtility/JsonValue.h @@ -0,0 +1,620 @@ +#pragma once + +#include "Library.h" + +#include <gsl/narrow> + +#include <cmath> +#include <cstdint> +#include <initializer_list> +#include <map> +#include <optional> +#include <stdexcept> +#include <string> +#include <string_view> +#include <type_traits> +#include <variant> +#include <vector> + +namespace CesiumUtility { + +struct JsonValueMissingKey : public std::runtime_error { + JsonValueMissingKey(const std::string& key) + : std::runtime_error(key + " is not present in Object") {} +}; + +struct JsonValueNotRealValue : public std::runtime_error { + JsonValueNotRealValue() + : std::runtime_error("this->value was not double, uint64_t or int64_t") {} +}; + +template <typename T, typename U> +constexpr T losslessNarrowOrDefault(U u, T defaultValue) noexcept { + constexpr const bool is_different_signedness = + (std::is_signed<T>::value != std::is_signed<U>::value); + + const T t = gsl::narrow_cast<T>(u); + + if (static_cast<U>(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<std::string, JsonValue>; + + /** + * @brief The type to represent an `Array` JSON value. + */ + using Array = std::vector<JsonValue>; + + /** + * @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<std::int64_t>(v)) {} + + /** + * @brief Creates a `std::uint64_t` JSON value (Widening conversion from + * std::uint8_t). + */ + JsonValue(std::uint8_t v) noexcept : value(static_cast<std::uint64_t>(v)) {} + + /** + * @brief Creates a `std::int64_t` JSON value (Widening conversion from + * std::int16_t). + */ + JsonValue(std::int16_t v) noexcept : value(static_cast<std::int64_t>(v)) {} + + /** + * @brief Creates a `std::uint64_t` JSON value (Widening conversion from + * std::uint16_t). + */ + JsonValue(std::uint16_t v) noexcept : value(static_cast<std::uint64_t>(v)) {} + + /** + * @brief Creates a `std::int64_t` JSON value (Widening conversion from + * std::int32_t). + */ + JsonValue(std::int32_t v) noexcept : value(static_cast<std::int64_t>(v)) {} + + /** + * @brief Creates a `std::uint64_t` JSON value (Widening conversion from + * std::uint32_t). + */ + JsonValue(std::uint32_t v) noexcept : value(static_cast<std::uint64_t>(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<std::string, JsonValue>& v) : value(v) {} + + /** + * @brief Creates an `Object` JSON value with the given properties. + */ + JsonValue(std::map<std::string, JsonValue>&& v) : value(std::move(v)) {} + + /** + * @brief Creates an `Array` JSON value with the given elements. + */ + JsonValue(const std::vector<JsonValue>& v) : value(v) {} + + /** + * @brief Creates an `Array` JSON value with the given elements. + */ + JsonValue(std::vector<JsonValue>&& v) noexcept : value(std::move(v)) {} + + /** + * @brief Creates an JSON value from the given initializer list. + */ + JsonValue(std::initializer_list<JsonValue> v) + : value(std::vector<JsonValue>(v)) {} + + /** + * @brief Creates an JSON value from the given initializer list. + */ + JsonValue(std::initializer_list<std::pair<const std::string, JsonValue>> v) + : value(std::map<std::string, JsonValue>(v)) {} + + [[nodiscard]] const JsonValue* + getValuePtrForKey(const std::string& key) const; + [[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 <typename T> + const T* getValuePtrForKey(const std::string& key) const { + const JsonValue* pValue = this->getValuePtrForKey(key); + if (!pValue) { + return nullptr; + } + + return std::get_if<T>(&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 <typename T> T* getValuePtrForKey(const std::string& key) { + JsonValue* pValue = this->getValuePtrForKey(key); + return std::get_if<T>(&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}, throws + * `std::bad_variant_access`. If the key does not exist in this object, throws + * `JsonValueMissingKey`. If the named value does not have a numerical type T, + * throws `JsonValueNotRealValue`, if the named value cannot be converted + from + * `double` / `std::uint64_t` / `std::int64_t` without precision loss, throws + * `gsl::narrowing_error` + * @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. + * @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<To>::value || + std::is_floating_point<To>::value>::type* = nullptr> + [[nodiscard]] To getSafeNumericalValueForKey(const std::string& key) const { + const Object& pObject = std::get<Object>(this->value); + const auto it = pObject.find(key); + if (it == pObject.end()) { + throw JsonValueMissingKey(key); + } + return it->second.getSafeNumber<To>(); + } + + /** + * @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. + * @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<To>::value || + std::is_floating_point<To>::value>::type* = nullptr> + [[nodiscard]] To getSafeNumericalValueOrDefaultForKey( + const std::string& key, + To defaultValue) const { + const Object& pObject = std::get<Object>(this->value); + const auto it = pObject.find(key); + if (it == pObject.end()) { + return defaultValue; + } + return it->second.getSafeNumberOrDefault<To>(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<Object>(&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 can be cast without precision loss. + * @throws If the underlying value is not a numerical type or it cannot be + * converted without precision loss. + */ + template < + typename To, + typename std::enable_if< + std::is_integral<To>::value || + std::is_floating_point<To>::value>::type* = nullptr> + [[nodiscard]] To getSafeNumber() const { + const std::uint64_t* uInt = std::get_if<std::uint64_t>(&this->value); + if (uInt) { + return gsl::narrow<To>(*uInt); + } + + const std::int64_t* sInt = std::get_if<std::int64_t>(&this->value); + if (sInt) { + return gsl::narrow<To>(*sInt); + } + + const double* real = std::get_if<double>(&this->value); + if (real) { + return gsl::narrow<To>(*real); + } + + throw JsonValueNotRealValue(); + } + + /** + * @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<To>::value || + std::is_floating_point<To>::value>::type* = nullptr> + [[nodiscard]] To getSafeNumberOrDefault(To defaultValue) const noexcept { + const std::uint64_t* uInt = std::get_if<std::uint64_t>(&this->value); + if (uInt) { + return losslessNarrowOrDefault<To>(*uInt, defaultValue); + } + + const std::int64_t* sInt = std::get_if<std::int64_t>(&this->value); + if (sInt) { + return losslessNarrowOrDefault<To>(*sInt, defaultValue); + } + + const double* real = std::get_if<double>(&this->value); + if (real) { + return losslessNarrowOrDefault<To>(*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<JsonValue::Object>(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<String>(this->value); + } + + /** + * @brief Gets the array from the value. + * @return The arrayj. + * @throws std::bad_variant_access if the underlying type is not a + * JsonValue::Array + */ + [[nodiscard]] inline const JsonValue::Array& getArray() const { + return std::get<JsonValue::Array>(this->value); + } + + /** + * @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<bool>(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<double>(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<std::uint64_t>(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<std::int64_t>(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<bool>(&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<JsonValue::String>(&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<double>(&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<std::uint64_t>(&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<std::int64_t>(&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<Null>(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<Bool>(this->value); + } + + /** + * @brief Returns whether this value is a `String` value. + */ + [[nodiscard]] inline bool isString() const noexcept { + return std::holds_alternative<String>(this->value); + } + + /** + * @brief Returns whether this value is an `Object` value. + */ + [[nodiscard]] inline bool isObject() const noexcept { + return std::holds_alternative<Object>(this->value); + } + + /** + * @brief Returns whether this value is an `Array` value. + */ + [[nodiscard]] inline bool isArray() const noexcept { + return std::holds_alternative<Array>(this->value); + } + + /** + * @brief Returns whether this value is a `double` value. + */ + [[nodiscard]] inline bool isDouble() const noexcept { + return std::holds_alternative<double>(this->value); + } + + /** + * @brief Returns whether this value is a `std::uint64_t` value. + */ + [[nodiscard]] inline bool isUint64() const noexcept { + return std::holds_alternative<std::uint64_t>(this->value); + } + + /** + * @brief Returns whether this value is a `std::int64_t` value. + */ + [[nodiscard]] inline bool isInt64() const noexcept { + return std::holds_alternative<std::int64_t>(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 0000000000000000000000000000000000000000..ed1ded7c0558ef98df3c76bcc4e3bd81e16fb74e --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumUtility/Library.h @@ -0,0 +1,16 @@ +#pragma once + +/** + * @brief Utility classes for Cesium + */ +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/Math.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumUtility/Math.h new file mode 100644 index 0000000000000000000000000000000000000000..5d8b28ef5b1466c3a931e0fddae38c0d77cbe274 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumUtility/Math.h @@ -0,0 +1,456 @@ +#pragma once + +#include "Library.h" + +#include <glm/gtc/epsilon.hpp> + +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 the second value. + * @param relativeEpsilon The relative epsilon. + * @return The absolute epsilon. + */ + template <glm::length_t L, typename T, glm::qualifier Q> + static constexpr glm::vec<L, T, Q> relativeEpsilonToAbsolute( + const glm::vec<L, T, Q>& a, + const glm::vec<L, T, Q>& 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 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 the second value. + * @param relativeEpsilon The relative epsilon. + * @return Whether the values are epsilon-equal + */ + template <glm::length_t L, typename T, glm::qualifier Q> + static bool constexpr equalsEpsilon( + const glm::vec<L, T, Q>& left, + const glm::vec<L, T, Q>& 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 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 <glm::length_t L, typename T, glm::qualifier Q> + static constexpr bool equalsEpsilon( + const glm::vec<L, T, Q>& left, + const glm::vec<L, T, Q>& right, + double relativeEpsilon, + double absoluteEpsilon) noexcept { + const glm::vec<L, T, Q> diff = glm::abs(left - right); + return glm::lessThanEqual(diff, glm::vec<L, T, Q>(absoluteEpsilon)) == + glm::vec<L, bool, Q>(true) || + glm::lessThanEqual( + diff, + relativeEpsilonToAbsolute(left, right, relativeEpsilon)) == + glm::vec<L, bool, Q>(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; + } + } +}; + +} // namespace CesiumUtility diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumUtility/ReferenceCountedNonThreadSafe.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumUtility/ReferenceCountedNonThreadSafe.h new file mode 100644 index 0000000000000000000000000000000000000000..761b02cf27e619e3f72e6906ade6ac4db49ef6b7 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumUtility/ReferenceCountedNonThreadSafe.h @@ -0,0 +1,79 @@ +#pragma once + +#include <cstdint> + +#ifndef NDEBUG +#include <thread> +#endif + +namespace CesiumUtility { + +/** + * @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<MyClass> { ... };` + */ +template <typename T> class ReferenceCountedNonThreadSafe { +public: + ReferenceCountedNonThreadSafe() noexcept +#ifndef NDEBUG + : _threadID(std::this_thread::get_id()) +#endif + { + } + + ~ReferenceCountedNonThreadSafe() noexcept { + assert(this->_referenceCount == 0); + } + + /** + * @brief Adds a counted reference to this object. Use + * {@link CesiumUtility::IntrusivePointer} instead of calling this method + * directly. + * + * This method is _not_ thread safe. Do not call it or use an + * `IntrusivePointer` from multiple threads simultaneously. + */ + void addReference() const /*noexcept*/ { + assert(std::this_thread::get_id() == this->_threadID); + ++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. + * + * This method is _not_ thread safe. Do not call it or use an + * `IntrusivePointer` from multiple threads simultaneously. + */ + void releaseReference() const /*noexcept*/ { + assert(std::this_thread::get_id() == this->_threadID); + assert(this->_referenceCount > 0); + const int32_t references = --this->_referenceCount; + if (references == 0) { + delete static_cast<const T*>(this); + } + } + + /** + * @brief Returns the current reference count of this instance. + */ + std::int32_t getReferenceCount() const noexcept { + return this->_referenceCount; + } + +private: + mutable std::int32_t _referenceCount{0}; +#ifndef NDEBUG + std::thread::id _threadID; +#endif +}; + +} // 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 0000000000000000000000000000000000000000..9a2711af174d11d390cdb8961996c10876d3291b --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumUtility/ScopeGuard.h @@ -0,0 +1,84 @@ +#pragma once + +#include <type_traits> +#include <utility> + +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 <typename ExitFunction> class ScopeGuard { +public: + /** + * @brief Constructor. + * + * @param ExitFunctionArg 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<std::remove_const_t<ExitFunctionArg>>, + ScopeGuard<ExitFunction>>, + int> = 0> + explicit ScopeGuard(ExitFunctionArg&& _exitFunc) + : _callExitFuncOnDestruct{true}, + _exitFunc{std::forward<ExitFunctionArg>(_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; +}; + +template <typename ExistFunction> +ScopeGuard(ExistFunction) -> ScopeGuard<ExistFunction>; +} // 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 0000000000000000000000000000000000000000..84fddffb03ba72e236a0aef4ffec7fb324f54c43 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumUtility/SpanHelper.h @@ -0,0 +1,18 @@ +#pragma once + +#include <gsl/span> + +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 <typename To, typename From> +gsl::span<To> reintepretCastSpan(const gsl::span<From>& from) noexcept { + return gsl::span<To>( + reinterpret_cast<To*>(from.data()), + from.size() * sizeof(From) / sizeof(To)); +} +} // 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 0000000000000000000000000000000000000000..7fb036b72de66028f2247a69087f3dd12c04bd0d --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumUtility/Tracing.h @@ -0,0 +1,347 @@ +#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 <atomic> +#include <cassert> +#include <chrono> +#include <fstream> +#include <mutex> +#include <string> +#include <thread> +#include <vector> + +// 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<int64_t> _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; + +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<Track> 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<TrackReference*> _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 0000000000000000000000000000000000000000..c87ec835a7a37669c4e6b0453eb5580c8f3beba2 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumUtility/Uri.h @@ -0,0 +1,26 @@ +#pragma once + +#include <functional> +#include <string> + +namespace CesiumUtility { +class Uri final { +public: + static std::string resolve( + const std::string& base, + const std::string& relative, + bool useBaseQuery = false); + static std::string addQuery( + const std::string& uri, + const std::string& key, + const std::string& value); + + typedef std::string + SubstitutionCallbackSignature(const std::string& placeholder); + static std::string substituteTemplateParameters( + const std::string& templateUri, + const std::function<SubstitutionCallbackSignature>& substitutionCallback); + + static std::string escape(const std::string& s); +}; +} // 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 0000000000000000000000000000000000000000..848889913f114a70a3a924e210de3235f6d74650 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumUtility/joinToString.h @@ -0,0 +1,56 @@ +#pragma once + +#include <numeric> +#include <string> + +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 <class TIterator> +std::string +joinToString(TIterator begin, TIterator end, const std::string& separator) { + return std::accumulate( + begin, + end, + std::string(), + [&separator](const std::string& acc, const std::string& element) { + if (!acc.empty()) { + return acc + separator + element; + } else { + return 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 <class TCollection> +std::string joinToString(TCollection collection, const std::string& separator) { + return std::accumulate( + collection.cbegin(), + collection.cend(), + std::string(), + [&separator](const std::string& acc, const std::string& element) { + if (!acc.empty()) { + return acc + separator + element; + } else { + return element; + } + }); +} +} // namespace CesiumUtility diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/Uri.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/Uri.h new file mode 100644 index 0000000000000000000000000000000000000000..ea4a91302976e89e821a4f6d5634c2d371742cb4 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/Uri.h @@ -0,0 +1,1124 @@ +/* 0beb20dace01f4b2fa24c3bf9f7e8e616f621e4697260805a2b63a4d190e64c0 (0.9.6+) + * + * uriparser - RFC 3986 URI parsing library + * + * Copyright (C) 2007, Weijia Song <songweijia@gmail.com> + * Copyright (C) 2007, Sebastian Pipping <sebastian@pipping.org> + * 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 <c>first</c> + * to one before <c>afterLast</c>. 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 <c>URI_FALSE</c> 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 <b>INOUT</b>: Parser state with set output %URI, must not be NULL + * @param first <b>IN</b>: Pointer to the first character to parse, must not be NULL + * @param afterLast <b>IN</b>: 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 <b>INOUT</b>: Parser state with set output %URI, must not be NULL + * @param text <b>IN</b>: 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 <b>OUT</b>: Output %URI, must not be NULL + * @param text <b>IN</b>: Pointer to the first character to parse, + * must not be NULL + * @param errorPos <b>OUT</b>: 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 <b>OUT</b>: Output %URI, must not be NULL + * @param first <b>IN</b>: Pointer to the first character to parse, + * must not be NULL + * @param afterLast <b>IN</b>: Pointer to the character after the last to + * parse, can be NULL + * (to use first + strlen(first)) + * @param errorPos <b>OUT</b>: 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 <b>OUT</b>: Output %URI, must not be NULL + * @param first <b>IN</b>: Pointer to the first character to parse, + * must not be NULL + * @param afterLast <b>IN</b>: Pointer to the character after the last to + * parse, can be NULL + * (to use first + strlen(first)) + * @param errorPos <b>OUT</b>: 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 <b>IN</b>: 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 <b>INOUT</b>: %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 <b>INOUT</b>: %URI structure whose members should be freed + * @param memory <b>IN</b>: 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. + * Be sure to allocate <b>3 times</b> the space of the input buffer for + * the output buffer for <c>normalizeBreaks == URI_FALSE</c> and <b>6 times</b> + * the space for <c>normalizeBreaks == URI_TRUE</c> + * (since e.g. "\x0d" becomes "%0D%0A" in that case) + * + * @param inFirst <b>IN</b>: Pointer to first character of the input text + * @param inAfterLast <b>IN</b>: Pointer after the last character of the input text + * @param out <b>OUT</b>: Encoded text destination + * @param spaceToPlus <b>IN</b>: Whether to convert ' ' to '+' or not + * @param normalizeBreaks <b>IN</b>: 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. + * Be sure to allocate <b>3 times</b> the space of the input buffer for + * the output buffer for <c>normalizeBreaks == URI_FALSE</c> and <b>6 times</b> + * the space for <c>normalizeBreaks == URI_TRUE</c> + * (since e.g. "\x0d" becomes "%0D%0A" in that case) + * + * @param in <b>IN</b>: Text source + * @param out <b>OUT</b>: Encoded text destination + * @param spaceToPlus <b>IN</b>: Whether to convert ' ' to '+' or not + * @param normalizeBreaks <b>IN</b>: 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 <c>inout</c> + * is NULL. + * + * @param inout <b>INOUT</b>: Text to unescape/decode + * @param plusToSpace <b>IN</b>: Whether to convert '+' to ' ' or not + * @param breakConversion <b>IN</b>: 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 <c>inout</c> + * is NULL. + * + * NOTE: '+' is not decoded to ' ' and line breaks are not converted. + * Use the more advanced UnescapeInPlaceEx for that features instead. + * + * @param inout <b>INOUT</b>: 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 + * <a href="http://tools.ietf.org/html/rfc3986#section-5.2.2">section 5.2.2 of RFC 3986</a>. + * Uses default libc-based memory manager. + * NOTE: On success you have to call uriFreeUriMembersA on \p absoluteDest manually later. + * + * @param absoluteDest <b>OUT</b>: Result %URI + * @param relativeSource <b>IN</b>: Reference to resolve + * @param absoluteBase <b>IN</b>: 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 + * <a href="http://tools.ietf.org/html/rfc3986#section-5.2.2">section 5.2.2 of RFC 3986</a>. + * Uses default libc-based memory manager. + * NOTE: On success you have to call uriFreeUriMembersA on \p absoluteDest manually later. + * + * @param absoluteDest <b>OUT</b>: Result %URI + * @param relativeSource <b>IN</b>: Reference to resolve + * @param absoluteBase <b>IN</b>: Base %URI to apply + * @param options <b>IN</b>: 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 + * <a href="http://tools.ietf.org/html/rfc3986#section-5.2.2">section 5.2.2 of RFC 3986</a>. + * NOTE: On success you have to call uriFreeUriMembersMmA on \p absoluteDest manually later. + * + * @param absoluteDest <b>OUT</b>: Result %URI + * @param relativeSource <b>IN</b>: Reference to resolve + * @param absoluteBase <b>IN</b>: Base %URI to apply + * @param options <b>IN</b>: Configuration to apply + * @param memory <b>IN</b>: 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 <b>OUT</b>: Result %URI + * @param absoluteSource <b>IN</b>: Absolute %URI to make relative + * @param absoluteBase <b>IN</b>: Base %URI + * @param domainRootMode <b>IN</b>: 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 <b>OUT</b>: Result %URI + * @param absoluteSource <b>IN</b>: Absolute %URI to make relative + * @param absoluteBase <b>IN</b>: Base %URI + * @param domainRootMode <b>IN</b>: Create %URI with path relative to domain root + * @param memory <b>IN</b>: 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 <c>NULL</c> URIs are equal as well. + * + * @param a <b>IN</b>: First %URI + * @param b <b>IN</b>: Second %URI + * @return <c>URI_TRUE</c> when equal, <c>URI_FAlSE</c> 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 <b>IN</b>: %URI to measure + * @param charsRequired <b>OUT</b>: Length of the string representation in characters <b>excluding</b> 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 + * <a href="http://tools.ietf.org/html/rfc3986#section-5.3">section 5.3 of RFC 3986</a>. + * + * @param dest <b>OUT</b>: Output destination + * @param uri <b>IN</b>: %URI to convert + * @param maxChars <b>IN</b>: Maximum number of characters to copy <b>including</b> terminator + * @param charsWritten <b>OUT</b>: 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 <b>IN</b>: %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 <b>IN</b>: %URI to check + * @param outMask <b>OUT</b>: 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 <b>INOUT</b>: %URI to normalize + * @param mask <b>IN</b>: 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 <b>INOUT</b>: %URI to normalize + * @param mask <b>IN</b>: Normalization mask + * @param memory <b>IN</b>: 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 <b>INOUT</b>: %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 <b>IN</b>: Unix filename to convert + * @param uriString <b>OUT</b>: 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 <b>IN</b>: Windows filename to convert + * @param uriString <b>OUT</b>: 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 <b>IN</b>: %URI string to convert + * @param filename <b>OUT</b>: 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 <b>IN</b>: %URI string to convert + * @param filename <b>OUT</b>: 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 <b>IN</b>: Query list to measure + * @param charsRequired <b>OUT</b>: Length of the string representation in characters <b>excluding</b> 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 <b>IN</b>: Query list to measure + * @param charsRequired <b>OUT</b>: Length of the string representation in characters <b>excluding</b> terminator + * @param spaceToPlus <b>IN</b>: Whether to convert ' ' to '+' or not + * @param normalizeBreaks <b>IN</b>: 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 <b>OUT</b>: Output destination + * @param queryList <b>IN</b>: Query list to convert + * @param maxChars <b>IN</b>: Maximum number of characters to copy <b>including</b> terminator + * @param charsWritten <b>OUT</b>: 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 <b>OUT</b>: Output destination + * @param queryList <b>IN</b>: Query list to convert + * @param maxChars <b>IN</b>: Maximum number of characters to copy <b>including</b> terminator + * @param charsWritten <b>OUT</b>: Number of characters written, can be lower than maxChars even if the query list is too long! + * @param spaceToPlus <b>IN</b>: Whether to convert ' ' to '+' or not + * @param normalizeBreaks <b>IN</b>: 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 <b>OUT</b>: Output destination + * @param queryList <b>IN</b>: 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 <b>OUT</b>: Output destination + * @param queryList <b>IN</b>: Query list to convert + * @param spaceToPlus <b>IN</b>: Whether to convert ' ' to '+' or not + * @param normalizeBreaks <b>IN</b>: 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 <b>OUT</b>: Output destination + * @param queryList <b>IN</b>: Query list to convert + * @param spaceToPlus <b>IN</b>: Whether to convert ' ' to '+' or not + * @param normalizeBreaks <b>IN</b>: Whether to convert CR and LF to CR-LF or not. + * @param memory <b>IN</b>: 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 <b>OUT</b>: Output destination + * @param itemCount <b>OUT</b>: Number of items found, can be NULL + * @param first <b>IN</b>: Pointer to first character <b>after</b> '?' + * @param afterLast <b>IN</b>: 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 <b>OUT</b>: Output destination + * @param itemCount <b>OUT</b>: Number of items found, can be NULL + * @param first <b>IN</b>: Pointer to first character <b>after</b> '?' + * @param afterLast <b>IN</b>: Pointer to character after the last one still in + * @param plusToSpace <b>IN</b>: Whether to convert '+' to ' ' or not + * @param breakConversion <b>IN</b>: 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 <b>OUT</b>: Output destination + * @param itemCount <b>OUT</b>: Number of items found, can be NULL + * @param first <b>IN</b>: Pointer to first character <b>after</b> '?' + * @param afterLast <b>IN</b>: Pointer to character after the last one still in + * @param plusToSpace <b>IN</b>: Whether to convert '+' to ' ' or not + * @param breakConversion <b>IN</b>: Line break conversion mode + * @param memory <b>IN</b>: 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 <b>INOUT</b>: 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 <b>INOUT</b>: Query list to free + * @param memory <b>IN</b>: 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 <c>URI_TRUE</c> and does not modify the %URI further. + * + * Uses default libc-based memory manager. + * + * @param uri <b>INOUT</b>: %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 <c>URI_TRUE</c> and does not modify the %URI further. + * + * @param uri <b>INOUT</b>: %URI to make independent + * @param memory <b>IN</b>: 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/UriBase.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/UriBase.h new file mode 100644 index 0000000000000000000000000000000000000000..089c2c6f176f4d695b4c08be3c1e6cb5ced12524 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/UriBase.h @@ -0,0 +1,377 @@ +/* + * uriparser - RFC 3986 URI parsing library + * + * Copyright (C) 2007, Weijia Song <songweijia@gmail.com> + * Copyright (C) 2007, Sebastian Pipping <sebastian@pipping.org> + * 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 6 +#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(URI_STATIC_BUILD) +# define URI_PUBLIC +#else +# if defined(URI_LIBRARY_BUILD) +# if defined(_MSC_VER) +# define URI_PUBLIC __declspec(dllexport) +# elif defined(URI_VISIBILITY) +# define URI_PUBLIC __attribute__ ((visibility("default"))) +# else +# define URI_PUBLIC +# endif +# else +# if defined(_MSC_VER) +# define URI_PUBLIC __declspec(dllimport) +# else +# define URI_PUBLIC +# endif +# 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 <stdio.h> /* For NULL, snprintf */ +# include <ctype.h> /* For wchar_t */ +# include <string.h> /* For strlen, memset, memcpy */ +# include <stdlib.h> /* 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 <b>OUT</b>: Where to write the wrapped memory manager to + * @param backend <b>IN</b>: 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 <b>IN</b>: Memory manager to use, should not be NULL + * @param nmemb <b>IN</b>: Number of elements to allocate + * @param size <b>IN</b>: 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 <b>IN</b>: Memory manager to use, should not be NULL + * @param ptr <b>IN</b>: Pointer allocated using memory->malloc/... or NULL + * @param nmemb <b>IN</b>: Number of elements to allocate + * @param size <b>IN</b>: 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 <b>IN</b>: 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/UriDefsAnsi.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/UriDefsAnsi.h new file mode 100644 index 0000000000000000000000000000000000000000..af581b91a2152342bd9c20f3be39c77b595baa7f --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/UriDefsAnsi.h @@ -0,0 +1,82 @@ +/* + * uriparser - RFC 3986 URI parsing library + * + * Copyright (C) 2007, Weijia Song <songweijia@gmail.com> + * Copyright (C) 2007, Sebastian Pipping <sebastian@pipping.org> + * 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/UriDefsConfig.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/UriDefsConfig.h new file mode 100644 index 0000000000000000000000000000000000000000..51bc93eeddaaed83185778580c6d4534713a8574 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/UriDefsConfig.h @@ -0,0 +1,101 @@ +/* + * uriparser - RFC 3986 URI parsing library + * + * Copyright (C) 2007, Weijia Song <songweijia@gmail.com> + * Copyright (C) 2007, Sebastian Pipping <sebastian@pipping.org> + * 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/UriDefsUnicode.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/UriDefsUnicode.h new file mode 100644 index 0000000000000000000000000000000000000000..01421f5f861df041cb4245402fa4ceacc8442566 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/UriDefsUnicode.h @@ -0,0 +1,82 @@ +/* + * uriparser - RFC 3986 URI parsing library + * + * Copyright (C) 2007, Weijia Song <songweijia@gmail.com> + * Copyright (C) 2007, Sebastian Pipping <sebastian@pipping.org> + * 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/UriIp4.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/UriIp4.h new file mode 100644 index 0000000000000000000000000000000000000000..c2e59a6bf2d13a39f8e55f97147730d45d043822 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/UriIp4.h @@ -0,0 +1,110 @@ +/* + * uriparser - RFC 3986 URI parsing library + * + * Copyright (C) 2007, Weijia Song <songweijia@gmail.com> + * Copyright (C) 2007, Sebastian Pipping <sebastian@pipping.org> + * 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 <wchar.h> +# 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/include/async++.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/async++.h new file mode 100644 index 0000000000000000000000000000000000000000..36e151694a3b5091a58eb2ab4260c2ea1a229cd0 --- /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 <algorithm> +#include <atomic> +#include <cassert> +#include <cstddef> +#include <cstdint> +#include <cstdlib> +#include <cstring> +#include <exception> +#include <functional> +#include <iterator> +#include <memory> +#include <mutex> +#include <thread> +#include <type_traits> +#include <utility> +#include <vector> + +// 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<typename Result> +class task; +template<typename Result> +class shared_task; +template<typename Result> +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 0000000000000000000000000000000000000000..cf4c2a314271a35c4fb9aa760323ee9a31642063 --- /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<typename T, std::size_t Align = std::alignment_of<T>::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<T*>(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 0000000000000000000000000000000000000000..36d0307f0108093d56565de9a723b2322325f5d3 --- /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 <async++.h> 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<bool> 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 0000000000000000000000000000000000000000..f0d909554a9fda7265ca57d65c70b29856f7561e --- /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 <async++.h> 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<std::uintptr_t Mask, bool Enable> +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<typename T> + T* get_ptr() const + { + return static_cast<T*>(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<std::uintptr_t Mask> +class compressed_ptr<Mask, true> { + std::uintptr_t data; + +public: + compressed_ptr() = default; + compressed_ptr(void* ptr_, std::uintptr_t flags_) + : data(reinterpret_cast<std::uintptr_t>(ptr_) | flags_) {} + + template<typename T> + T* get_ptr() const + { + return reinterpret_cast<T*>(data & ~Mask); + } + std::uintptr_t get_flags() const + { + return data & Mask; + } + + void set_ptr(void* p) + { + data = reinterpret_cast<std::uintptr_t>(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<task_base*> 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<flags_mask, (LIBASYNC_CACHELINE_SIZE & flags_mask) == 0 && + (std::alignment_of<vector_data>::value & flags_mask) == 0> internal_data; + + // All changes to the internal data are atomic + std::atomic<internal_data> 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_data>()->vector) + (task_ptr(i)); + delete data.get_ptr<vector_data>(); + } 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<task_base>()); + } + } + + // 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_data> 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<std::mutex> locked(data.get_ptr<vector_data>()->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_data>()->vector.push_back(t.release()); + return true; + } else { + if (data.get_ptr<task_base>()) { + // Going from 1 to 2 elements, allocate a vector_data + if (!vector) + vector.reset(new vector_data{{data.get_ptr<task_base>(), 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<typename Func> 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<std::mutex> locked(data.get_ptr<vector_data>()->lock); + for (auto i: data.get_ptr<vector_data>()->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_data>()->vector.clear(); + } else { + // If there is an inline element, just pass it on + if (data.get_ptr<task_base>()) + func(task_ptr(data.get_ptr<task_base>())); + } + } +}; + +} // 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 0000000000000000000000000000000000000000..4fe52689fd7a575c7d625883822ac68ab2b76c74 --- /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 <async++.h> instead." +#endif + +namespace async { +namespace detail { + +// Internal implementation of parallel_for that only accepts a partitioner +// argument. +template<typename Sched, typename Partitioner, typename Func> +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<decltype(i)>(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<typename Sched, typename Range, typename Func> +void parallel_for(Sched& sched, Range&& range, const Func& func) +{ + detail::internal_parallel_for(sched, async::to_partitioner(std::forward<Range>(range)), func); +} + +// Overload with default scheduler +template<typename Range, typename Func> +void parallel_for(Range&& range, const Func& func) +{ + async::parallel_for(::async::default_scheduler(), range, func); +} + +// Overloads with std::initializer_list +template<typename Sched, typename T, typename Func> +void parallel_for(Sched& sched, std::initializer_list<T> range, const Func& func) +{ + async::parallel_for(sched, async::make_range(range.begin(), range.end()), func); +} +template<typename T, typename Func> +void parallel_for(std::initializer_list<T> 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 0000000000000000000000000000000000000000..0734bb6ec29670b919e143da0c24f64c612d66a5 --- /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 <async++.h> instead." +#endif + +namespace async { +namespace detail { + +// Recursively split the arguments so tasks are spawned in parallel +template<std::size_t Start, std::size_t Count> +struct parallel_invoke_internal { + template<typename Sched, typename Tuple> + static void run(Sched& sched, const Tuple& args) + { + auto&& t = async::local_spawn(sched, [&sched, &args] { + parallel_invoke_internal<Start + Count / 2, Count - Count / 2>::run(sched, args); + }); + parallel_invoke_internal<Start, Count / 2>::run(sched, args); + t.get(); + } +}; +template<std::size_t Index> +struct parallel_invoke_internal<Index, 1> { + template<typename Sched, typename Tuple> + static void run(Sched&, const Tuple& args) + { + // Make sure to preserve the rvalue/lvalue-ness of the original parameter + std::forward<typename std::tuple_element<Index, Tuple>::type>(std::get<Index>(args))(); + } +}; +template<std::size_t Index> +struct parallel_invoke_internal<Index, 0> { + template<typename Sched, typename Tuple> + static void run(Sched&, const Tuple&) {} +}; + +} // namespace detail + +// Run several functions in parallel, optionally using the specified scheduler. +template<typename Sched, typename... Args> +typename std::enable_if<detail::is_scheduler<Sched>::value>::type parallel_invoke(Sched& sched, Args&&... args) +{ + detail::parallel_invoke_internal<0, sizeof...(Args)>::run(sched, std::forward_as_tuple(std::forward<Args>(args)...)); +} +template<typename... Args> +void parallel_invoke(Args&&... args) +{ + async::parallel_invoke(::async::default_scheduler(), std::forward<Args>(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 0000000000000000000000000000000000000000..06545f6384e208ad694371f8e7ca9b05bf505a66 --- /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 <async++.h> instead." +#endif + +namespace async { +namespace detail { + +// Default map function which simply passes its parameter through unmodified +struct default_map { + template<typename T> + T&& operator()(T&& x) const + { + return std::forward<T>(x); + } +}; + +// Internal implementation of parallel_map_reduce that only accepts a +// partitioner argument. +template<typename Sched, typename Partitioner, typename Result, typename MapFunc, typename ReduceFunc> +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<decltype(i)>(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<typename Sched, typename Range, typename Result, typename MapFunc, typename ReduceFunc> +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>(range)), init, map, reduce); +} + +// Overload with default scheduler +template<typename Range, typename Result, typename MapFunc, typename ReduceFunc> +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<typename Sched, typename T, typename Result, typename MapFunc, typename ReduceFunc> +Result parallel_map_reduce(Sched& sched, std::initializer_list<T> 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<typename T, typename Result, typename MapFunc, typename ReduceFunc> +Result parallel_map_reduce(std::initializer_list<T> 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<typename Sched, typename Range, typename Result, typename ReduceFunc> +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<typename Range, typename Result, typename ReduceFunc> +Result parallel_reduce(Range&& range, Result init, const ReduceFunc& reduce) +{ + return async::parallel_reduce(::async::default_scheduler(), range, init, reduce); +} +template<typename Sched, typename T, typename Result, typename ReduceFunc> +Result parallel_reduce(Sched& sched, std::initializer_list<T> range, Result init, const ReduceFunc& reduce) +{ + return async::parallel_reduce(sched, async::make_range(range.begin(), range.end()), init, reduce); +} +template<typename T, typename Result, typename ReduceFunc> +Result parallel_reduce(std::initializer_list<T> 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 0000000000000000000000000000000000000000..f6403bdfc1798b8afb50076fd8907e0d711d06b1 --- /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 <async++.h> 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<typename T, typename = decltype(std::declval<T>().split())> +two& is_partitioner_helper(int); +template<typename T> +one& is_partitioner_helper(...); +template<typename T> +struct is_partitioner: public std::integral_constant<bool, sizeof(is_partitioner_helper<T>(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<typename Iter> +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<typename Iter> +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<typename Range> +detail::static_partitioner_impl<decltype(std::begin(std::declval<Range>()))> static_partitioner(Range&& range, std::size_t grain) +{ + return {std::begin(range), std::end(range), grain}; +} +template<typename Range> +detail::static_partitioner_impl<decltype(std::begin(std::declval<Range>()))> 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<typename Range> +detail::auto_partitioner_impl<decltype(std::begin(std::declval<Range>()))> 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 Partitioner> +typename std::enable_if<detail::is_partitioner<typename std::decay<Partitioner>::type>::value, Partitioner&&>::type to_partitioner(Partitioner&& partitioner) +{ + return std::forward<Partitioner>(partitioner); +} +template<typename Range> +typename std::enable_if<!detail::is_partitioner<typename std::decay<Range>::type>::value, detail::auto_partitioner_impl<decltype(std::begin(std::declval<Range>()))>>::type to_partitioner(Range&& range) +{ + return async::auto_partitioner(std::forward<Range>(range)); +} + +// Overloads with std::initializer_list +template<typename T> +detail::static_partitioner_impl<decltype(std::declval<std::initializer_list<T>>().begin())> static_partitioner(std::initializer_list<T> range) +{ + return async::static_partitioner(async::make_range(range.begin(), range.end())); +} +template<typename T> +detail::static_partitioner_impl<decltype(std::declval<std::initializer_list<T>>().begin())> static_partitioner(std::initializer_list<T> range, std::size_t grain) +{ + return async::static_partitioner(async::make_range(range.begin(), range.end()), grain); +} +template<typename T> +detail::auto_partitioner_impl<decltype(std::declval<std::initializer_list<T>>().begin())> auto_partitioner(std::initializer_list<T> range) +{ + return async::auto_partitioner(async::make_range(range.begin(), range.end())); +} +template<typename T> +detail::auto_partitioner_impl<decltype(std::declval<std::initializer_list<T>>().begin())> to_partitioner(std::initializer_list<T> 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 0000000000000000000000000000000000000000..d23ee0c450f42c3cf287ff97d8660dbbae130bc4 --- /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 <async++.h> instead." +#endif + +namespace async { + +// Range type representing a pair of iterators +template<typename Iter> +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<typename Iter> +range<Iter> make_range(Iter begin, Iter end) +{ + return {begin, end}; +} + +// A range of integers +template<typename T> +class int_range { + T value_begin, value_end; + + static_assert(std::is_integral<T>::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<T>; + + 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<typename T, typename U> +int_range<typename std::common_type<T, U>::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 0000000000000000000000000000000000000000..5eb118559d664b2ad87474511f9e01235fb5a0fe --- /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 <async++.h> instead." +#endif + +namespace async { +namespace detail { + +// Default deleter which just uses the delete keyword +template<typename T> +struct default_deleter { + static void do_delete(T* p) + { + delete p; + } +}; + +// Reference-counted object base class +template<typename T, typename Deleter = default_deleter<T>> +struct ref_count_base { + std::atomic<std::size_t> 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<T*>(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<typename T> +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 0000000000000000000000000000000000000000..67180953e201d2a8df8545fce99e57ed54c67aaf --- /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 <async++.h> 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<typename Func> + struct wait_exec_func: private detail::func_base<Func> { + template<typename F> + explicit wait_exec_func(F&& f) + : detail::func_base<Func>(std::forward<F>(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<typename Func> + void on_finish(Func&& func) + { + // Make sure the function type is callable + static_assert(detail::is_callable<Func()>::value, "Invalid function type passed to on_finish()"); + + auto cont = new detail::task_func<typename std::remove_reference<decltype(inline_scheduler())>::type, wait_exec_func<typename std::decay<Func>::type>, detail::fake_void>(std::forward<Func>(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<typename Sched> + 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<detail::task_base*>(ptr))); + } +}; + +namespace detail { + +// Schedule a task for execution using its scheduler +template<typename Sched> +void schedule_task(Sched& sched, task_ptr t) +{ + static_assert(is_scheduler<Sched>::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 0000000000000000000000000000000000000000..6e124b0f247f63eed2348b75c4a8a88eef11caee --- /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 <async++.h> 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<typename T, typename = decltype(std::declval<T>().schedule(std::declval<task_run_handle>()))> +two& is_scheduler_helper(int); +template<typename T> +one& is_scheduler_helper(...); +template<typename T> +struct is_scheduler: public std::integral_constant<bool, sizeof(is_scheduler_helper<T>(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_base> task_ptr; + +// Helper function to schedule a task using a scheduler +template<typename Sched> +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<internal_data> 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<detail::threadpool_data> 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<void()>&& prerun_, + std::function<void()>&& 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<decltype(::async::default_scheduler())>::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 0000000000000000000000000000000000000000..7735c3067127ac3fdbb3500f292a153b3baea2fb --- /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 <async++.h> 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<typename Result> +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<Result>::type internal_result; + + // Type-specific task object + typedef task_result<internal_result> internal_task_type; + + // Friend access + friend async::task<Result>; + friend async::shared_task<Result>; + template<typename T> + friend typename T::internal_task_type* get_internal_task(const T& t); + template<typename T> + 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 Sched, typename Func, typename Parent> + typename continuation_traits<Parent, Func>::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<Parent, Func> traits; + typedef typename void_to_fake_void<typename traits::task_type::result_type>::type cont_internal_result; + typedef continuation_exec_func<Sched, typename std::decay<Parent>::type, cont_internal_result, typename traits::decay_func, typename traits::is_value_cont, is_task<typename traits::result_type>::value> exec_func; + typename traits::task_type cont; + set_internal_task(cont, task_ptr(new task_func<Sched, exec_func, cont_internal_result>(std::forward<Func>(f), std::forward<Parent>(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<typename Result> +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<Result>::type internal_result; + + // Type-specific task object + typedef detail::task_result<internal_result> internal_task_type; + + // Friend access + friend async::event_task<Result>; + template<typename T> + friend typename T::internal_task_type* get_internal_task(const T& t); + + // Common code for set() + template<typename T> + 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<T>(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<Result> 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<Result> 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<typename Result> +class task: public detail::basic_task<Result> { +public: + // Movable but not copyable + task() = default; + task(task&& other) LIBASYNC_NOEXCEPT + : detail::basic_task<Result>(std::move(other)) {} + task& operator=(task&& other) LIBASYNC_NOEXCEPT + { + detail::basic_task<Result>::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<typename task::internal_task_type*>(my_internal.get())->get_result(*this)); + } + + // Add a continuation to the task + template<typename Sched, typename Func> + typename detail::continuation_traits<task, Func>::task_type then(Sched& sched, Func&& f) + { + return this->then_internal(sched, std::forward<Func>(f), std::move(*this)); + } + template<typename Func> + typename detail::continuation_traits<task, Func>::task_type then(Func&& f) + { + return then(::async::default_scheduler(), std::forward<Func>(f)); + } + + // Create a shared_task from this task + shared_task<Result> share() + { + LIBASYNC_ASSERT(this->internal_task, std::invalid_argument, "Use of empty task object"); + + shared_task<Result> out; + detail::set_internal_task(out, std::move(this->internal_task)); + return out; + } +}; + +template<typename Result> +class shared_task: public detail::basic_task<Result> { + // get() return value: const Result& -or- void + typedef typename std::conditional< + std::is_void<Result>::value, + void, + typename std::add_lvalue_reference< + typename std::add_const<Result>::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 Sched, typename Func> + typename detail::continuation_traits<shared_task, Func>::task_type then(Sched& sched, Func&& f) const + { + return this->then_internal(sched, std::forward<Func>(f), *this); + } + template<typename Func> + typename detail::continuation_traits<shared_task, Func>::task_type then(Func&& f) const + { + return then(::async::default_scheduler(), std::forward<Func>(f)); + } +}; + +// Special task type which can be triggered manually rather than when a function executes. +template<typename Result> +class event_task: public detail::basic_event<Result> { +public: + // Movable but not copyable + event_task() = default; + event_task(event_task&& other) LIBASYNC_NOEXCEPT + : detail::basic_event<Result>(std::move(other)) {} + event_task& operator=(event_task&& other) LIBASYNC_NOEXCEPT + { + detail::basic_event<Result>::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<typename Result> +class event_task<Result&>: public detail::basic_event<Result&> { +public: + // Movable but not copyable + event_task() = default; + event_task(event_task&& other) LIBASYNC_NOEXCEPT + : detail::basic_event<Result&>(std::move(other)) {} + event_task& operator=(event_task&& other) LIBASYNC_NOEXCEPT + { + detail::basic_event<Result&>::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<void>: public detail::basic_event<void> { +public: + // Movable but not copyable + event_task() = default; + event_task(event_task&& other) LIBASYNC_NOEXCEPT + : detail::basic_event<void>(std::move(other)) {} + event_task& operator=(event_task&& other) LIBASYNC_NOEXCEPT + { + detail::basic_event<void>::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<typename Sched, typename Func> +class local_task { + // Make sure the function type is callable + typedef typename std::decay<Func>::type decay_func; + static_assert(detail::is_callable<decay_func()>::value, "Invalid function type passed to local_spawn()"); + + // Task result type + typedef typename detail::remove_task<decltype(std::declval<decay_func>()())>::type result_type; + typedef typename detail::void_to_fake_void<result_type>::type internal_result; + + // Task execution function type + typedef detail::root_exec_func<Sched, internal_result, decay_func, detail::is_task<decltype(std::declval<decay_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<Sched, exec_func, internal_result> internal_task; + + // Friend access for local_spawn + template<typename S, typename F> + friend local_task<S, F> local_spawn(S& sched, F&& f); + template<typename F> + friend local_task<detail::default_scheduler_type, F> local_spawn(F&& f); + + // Constructor, used by local_spawn + local_task(Sched& sched, Func&& f) + : internal_task(std::forward<Func>(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<result_type>())); + } + + // 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<typename Sched, typename Func> +task<typename detail::remove_task<std::invoke_result_t<std::decay_t<Func>>>::type> spawn(Sched& sched, Func&& f) +#else +template<typename Sched, typename Func> +task<typename detail::remove_task<typename std::result_of<typename std::decay<Func>::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<Func>::type decay_func; + static_assert(detail::is_callable<decay_func()>::value, "Invalid function type passed to spawn()"); + + // Create task + typedef typename detail::void_to_fake_void<typename detail::remove_task<decltype(std::declval<decay_func>()())>::type>::type internal_result; + typedef detail::root_exec_func<Sched, internal_result, decay_func, detail::is_task<decltype(std::declval<decay_func>()())>::value> exec_func; + task<typename detail::remove_task<decltype(std::declval<decay_func>()())>::type> out; + detail::set_internal_task(out, detail::task_ptr(new detail::task_func<Sched, exec_func, internal_result>(std::forward<Func>(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<typename Func> +decltype(async::spawn(::async::default_scheduler(), std::declval<Func>())) spawn(Func&& f) +{ + return async::spawn(::async::default_scheduler(), std::forward<Func>(f)); +} + +// Create a completed task containing a value +template<typename T> +task<typename std::decay<T>::type> make_task(T&& value) +{ + task<typename std::decay<T>::type> out; + + detail::set_internal_task(out, detail::task_ptr(new detail::task_result<typename std::decay<T>::type>)); + detail::get_internal_task(out)->set_result(std::forward<T>(value)); + detail::get_internal_task(out)->state.store(detail::task_state::completed, std::memory_order_relaxed); + + return out; +} +template<typename T> +task<T&> make_task(std::reference_wrapper<T> value) +{ + task<T&> out; + + detail::set_internal_task(out, detail::task_ptr(new detail::task_result<T&>)); + 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<void> make_task() +{ + task<void> out; + + detail::set_internal_task(out, detail::task_ptr(new detail::task_result<detail::fake_void>)); + 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<typename T> +task<T> make_exception_task(std::exception_ptr except) +{ + task<T> out; + + detail::set_internal_task(out, detail::task_ptr(new detail::task_result<typename detail::void_to_fake_void<T>::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<typename Sched, typename Func> +#ifdef __GNUC__ +__attribute__((warn_unused_result)) +#endif +local_task<Sched, Func> 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<Func>(f)}; +} +template<typename Func> +#ifdef __GNUC__ +__attribute__((warn_unused_result)) +#endif +local_task<detail::default_scheduler_type, Func> local_spawn(Func&& f) +{ + return {::async::default_scheduler(), std::forward<Func>(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 0000000000000000000000000000000000000000..2f16e7e89b3a7a232aa38e11ee24ce91847b9f64 --- /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 <async++.h> 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_base, task_base_deleter> { + // Task state + std::atomic<task_state> 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<typename Sched> + void run_continuation(Sched& sched, task_ptr&& cont) + { + LIBASYNC_TRY { + detail::schedule_task(sched, std::move(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<typename Sched> + 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<typename Result> +struct task_result_holder: public task_base { + union { + typename std::aligned_storage<sizeof(Result), std::alignment_of<Result>::value>::type result; + std::aligned_storage<sizeof(std::exception_ptr), std::alignment_of<std::exception_ptr>::value>::type except; + + // Scheduler that should be used to schedule this task. The scheduler + // type has been erased and is held by vtable->schedule. + void* sched; + }; + + template<typename T> + void set_result(T&& t) + { + new(&result) Result(std::forward<T>(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<typename T> + Result&& get_result(const task<T>&) + { + return std::move(*reinterpret_cast<Result*>(&result)); + } + template<typename T> + const Result& get_result(const shared_task<T>&) + { + return *reinterpret_cast<Result*>(&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)->~Result(); + } +}; + +// Specialization for references +template<typename Result> +struct task_result_holder<Result&>: public task_base { + union { + // Store as pointer internally + Result* result; + std::aligned_storage<sizeof(std::exception_ptr), std::alignment_of<std::exception_ptr>::value>::type except; + void* sched; + }; + + void set_result(Result& obj) + { + result = std::addressof(obj); + } + + template<typename T> + Result& get_result(const task<T>&) + { + return *result; + } + template<typename T> + Result& get_result(const shared_task<T>&) + { + return *result; + } +}; + +// Specialization for void +template<> +struct task_result_holder<fake_void>: public task_base { + union { + std::aligned_storage<sizeof(std::exception_ptr), std::alignment_of<std::exception_ptr>::value>::type except; + 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<typename T> + fake_void get_result(const task<T>&) + { + return fake_void(); + } + template<typename T> + fake_void get_result(const shared_task<T>&) + { + return fake_void(); + } +}; + +template<typename Result> +struct task_result: public task_result_holder<Result> { + // 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<std::exception_ptr*>(&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<std::exception_ptr*>(&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<task_result<Result>*>(t); + } +}; +template<typename Result> +const task_base_vtable task_result<Result>::vtable_impl = { + task_result<Result>::destroy, // destroy + nullptr, // run + nullptr, // cancel + nullptr // schedule +}; + +// Class to hold a function object, with empty base class optimization +template<typename Func, typename = void> +struct func_base { + Func func; + + template<typename F> + explicit func_base(F&& f) + : func(std::forward<F>(f)) {} + Func& get_func() + { + return func; + } +}; +template<typename Func> +struct func_base<Func, typename std::enable_if<std::is_empty<Func>::value>::type> { + template<typename F> + explicit func_base(F&& f) + { + new(this) Func(std::forward<F>(f)); + } + ~func_base() + { + get_func().~Func(); + } + Func& get_func() + { + return *reinterpret_cast<Func*>(this); + } +}; + +// Class to hold a function object and initialize/destroy it at any time +template<typename Func, typename = void> +struct func_holder { + typename std::aligned_storage<sizeof(Func), std::alignment_of<Func>::value>::type func; + + Func& get_func() + { + return *reinterpret_cast<Func*>(&func); + } + template<typename... Args> + void init_func(Args&&... args) + { + new(&func) Func(std::forward<Args>(args)...); + } + void destroy_func() + { + get_func().~Func(); + } +}; +template<typename Func> +struct func_holder<Func, typename std::enable_if<std::is_empty<Func>::value>::type> { + Func& get_func() + { + return *reinterpret_cast<Func*>(this); + } + template<typename... Args> + void init_func(Args&&... args) + { + new(this) Func(std::forward<Args>(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<typename Sched, typename Func, typename Result> +struct task_func: public task_result<Result>, func_holder<Func> { + // Virtual function table for task_func + static const task_base_vtable vtable_impl; + template<typename... Args> + explicit task_func(Args&&... args) + { + this->vtable = &vtable_impl; + this->init_func(std::forward<Args>(args)...); + } + + // Run the stored function + static void run(task_base* t) LIBASYNC_NOEXCEPT + { + LIBASYNC_TRY { + // Dispatch to execution function + static_cast<task_func<Sched, Func, Result>*>(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<task_func<Sched, Func, Result>*>(t)->destroy_func(); + static_cast<task_func<Sched, Func, Result>*>(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<task_func<Sched, Func, Result>*>(t.get())->sched; + parent->run_continuation(*static_cast<Sched*>(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<task_func<Sched, Func, Result>*>(t); + } +}; +template<typename Sched, typename Func, typename Result> +const task_base_vtable task_func<Sched, Func, Result>::vtable_impl = { + task_func<Sched, Func, Result>::destroy, // destroy + task_func<Sched, Func, Result>::run, // run + task_func<Sched, Func, Result>::cancel, // cancel + task_func<Sched, Func, Result>::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> +typename Task::internal_task_type* get_internal_task(const Task& t) +{ + return static_cast<typename Task::internal_task_type*>(t.internal_task.get()); +} +template<typename Task> +void set_internal_task(Task& t, task_ptr p) +{ + t.internal_task = std::move(p); +} + +// Common code for task unwrapping +template<typename Result, typename Child> +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<Result>* parent = static_cast<task_result<Result>*>(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<typename Sched, typename Result, typename Func, typename Child> +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<task_func<Sched, Func, Result>*>(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<Result, Child>(task_ptr(parent_base))); + } LIBASYNC_CATCH(...) { + // Use cancel_base here because the function object is already destroyed. + static_cast<task_result<Result>*>(parent_base)->cancel_base(std::current_exception()); + } +} + +// Execution functions for root tasks: +// - With and without task unwraping +template<typename Sched, typename Result, typename Func, bool Unwrap> +struct root_exec_func: private func_base<Func> { + template<typename F> + explicit root_exec_func(F&& f) + : func_base<Func>(std::forward<F>(f)) {} + void operator()(task_base* t) + { + static_cast<task_result<Result>*>(t)->set_result(detail::invoke_fake_void(std::move(this->get_func()))); + static_cast<task_func<Sched, root_exec_func, Result>*>(t)->destroy_func(); + t->finish(); + } +}; +template<typename Sched, typename Result, typename Func> +struct root_exec_func<Sched, Result, Func, true>: private func_base<Func> { + template<typename F> + explicit root_exec_func(F&& f) + : func_base<Func>(std::forward<F>(f)) {} + void operator()(task_base* t) + { + unwrapped_finish<Sched, Result, root_exec_func>(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<typename Sched, typename Parent, typename Result, typename Func, typename ValueCont, bool Unwrap> +struct continuation_exec_func: private func_base<Func> { + template<typename F, typename P> + continuation_exec_func(F&& f, P&& p) + : func_base<Func>(std::forward<F>(f)), parent(std::forward<P>(p)) {} + void operator()(task_base* t) + { + static_cast<task_result<Result>*>(t)->set_result(detail::invoke_fake_void(std::move(this->get_func()), std::move(parent))); + static_cast<task_func<Sched, continuation_exec_func, Result>*>(t)->destroy_func(); + t->finish(); + } + Parent parent; +}; +template<typename Sched, typename Parent, typename Result, typename Func> +struct continuation_exec_func<Sched, Parent, Result, Func, std::true_type, false>: private func_base<Func> { + template<typename F, typename P> + continuation_exec_func(F&& f, P&& p) + : func_base<Func>(std::forward<F>(f)), parent(std::forward<P>(p)) {} + void operator()(task_base* t) + { + if (get_internal_task(parent)->state.load(std::memory_order_relaxed) == task_state::canceled) + task_func<Sched, continuation_exec_func, Result>::cancel(t, std::exception_ptr(get_internal_task(parent)->get_exception())); + else { + static_cast<task_result<Result>*>(t)->set_result(detail::invoke_fake_void(std::move(this->get_func()), get_internal_task(parent)->get_result(parent))); + static_cast<task_func<Sched, continuation_exec_func, Result>*>(t)->destroy_func(); + t->finish(); + } + } + Parent parent; +}; +template<typename Sched, typename Parent, typename Result, typename Func> +struct continuation_exec_func<Sched, Parent, Result, Func, fake_void, false>: private func_base<Func> { + template<typename F, typename P> + continuation_exec_func(F&& f, P&& p) + : func_base<Func>(std::forward<F>(f)), parent(std::forward<P>(p)) {} + void operator()(task_base* t) + { + if (get_internal_task(parent)->state.load(std::memory_order_relaxed) == task_state::canceled) + task_func<Sched, continuation_exec_func, Result>::cancel(t, std::exception_ptr(get_internal_task(parent)->get_exception())); + else { + static_cast<task_result<Result>*>(t)->set_result(detail::invoke_fake_void(std::move(this->get_func()), fake_void())); + static_cast<task_func<Sched, continuation_exec_func, Result>*>(t)->destroy_func(); + t->finish(); + } + } + Parent parent; +}; +template<typename Sched, typename Parent, typename Result, typename Func> +struct continuation_exec_func<Sched, Parent, Result, Func, std::false_type, true>: private func_base<Func> { + template<typename F, typename P> + continuation_exec_func(F&& f, P&& p) + : func_base<Func>(std::forward<F>(f)), parent(std::forward<P>(p)) {} + void operator()(task_base* t) + { + unwrapped_finish<Sched, Result, continuation_exec_func>(t, detail::invoke_fake_void(std::move(this->get_func()), std::move(parent))); + } + Parent parent; +}; +template<typename Sched, typename Parent, typename Result, typename Func> +struct continuation_exec_func<Sched, Parent, Result, Func, std::true_type, true>: private func_base<Func> { + template<typename F, typename P> + continuation_exec_func(F&& f, P&& p) + : func_base<Func>(std::forward<F>(f)), parent(std::forward<P>(p)) {} + void operator()(task_base* t) + { + if (get_internal_task(parent)->state.load(std::memory_order_relaxed) == task_state::canceled) + task_func<Sched, continuation_exec_func, Result>::cancel(t, std::exception_ptr(get_internal_task(parent)->get_exception())); + else + unwrapped_finish<Sched, Result, continuation_exec_func>(t, detail::invoke_fake_void(std::move(this->get_func()), get_internal_task(parent)->get_result(parent))); + } + Parent parent; +}; +template<typename Sched, typename Parent, typename Result, typename Func> +struct continuation_exec_func<Sched, Parent, Result, Func, fake_void, true>: private func_base<Func> { + template<typename F, typename P> + continuation_exec_func(F&& f, P&& p) + : func_base<Func>(std::forward<F>(f)), parent(std::forward<P>(p)) {} + void operator()(task_base* t) + { + if (get_internal_task(parent)->state.load(std::memory_order_relaxed) == task_state::canceled) + task_func<Sched, continuation_exec_func, Result>::cancel(t, std::exception_ptr(get_internal_task(parent)->get_exception())); + else + unwrapped_finish<Sched, Result, continuation_exec_func>(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 0000000000000000000000000000000000000000..087e60b16d43ba955ba6fa55f0e5bcc0453cd71a --- /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 <async++.h> instead." +#endif + +namespace async { +namespace detail { + +// Pseudo-void type: it takes up no space but can be moved and copied +struct fake_void {}; +template<typename T> +struct void_to_fake_void { + typedef T type; +}; +template<> +struct void_to_fake_void<void> { + typedef fake_void type; +}; +template<typename T> +T fake_void_to_void(T&& x) +{ + return std::forward<T>(x); +} +inline void fake_void_to_void(fake_void) {} + +// Check if type is a task type, used to detect task unwraping +template<typename T> +struct is_task: public std::false_type {}; +template<typename T> +struct is_task<task<T>>: public std::true_type {}; +template<typename T> +struct is_task<const task<T>>: public std::true_type {}; +template<typename T> +struct is_task<shared_task<T>>: public std::true_type {}; +template<typename T> +struct is_task<const shared_task<T>>: public std::true_type {}; + +// Extract the result type of a task if T is a task, otherwise just return T +template<typename T> +struct remove_task { + typedef T type; +}; +template<typename T> +struct remove_task<task<T>> { + typedef T type; +}; +template<typename T> +struct remove_task<const task<T>> { + typedef T type; +}; +template<typename T> +struct remove_task<shared_task<T>> { + typedef T type; +}; +template<typename T> +struct remove_task<const shared_task<T>> { + typedef T type; +}; + +// Check if a type is callable with the given arguments +typedef char one[1]; +typedef char two[2]; +template<typename Func, typename... Args, typename = decltype(std::declval<Func>()(std::declval<Args>()...))> +two& is_callable_helper(int); +template<typename Func, typename... Args> +one& is_callable_helper(...); +template<typename T> +struct is_callable; +template<typename Func, typename... Args> +struct is_callable<Func(Args...)>: public std::integral_constant<bool, sizeof(is_callable_helper<Func, Args...>(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<typename Func, typename = typename std::enable_if<!std::is_void<decltype(std::declval<Func>()())>::value>::type> +decltype(std::declval<Func>()()) invoke_fake_void(Func&& f) +{ + return std::forward<Func>(f)(); +} +template<typename Func, typename = typename std::enable_if<std::is_void<decltype(std::declval<Func>()())>::value>::type> +fake_void invoke_fake_void(Func&& f) +{ + std::forward<Func>(f)(); + return fake_void(); +} +template<typename Func, typename Param> +typename void_to_fake_void<decltype(std::declval<Func>()(std::declval<Param>()))>::type invoke_fake_void(Func&& f, Param&& p) +{ + return detail::invoke_fake_void([&f, &p] {return std::forward<Func>(f)(std::forward<Param>(p));}); +} +template<typename Func> +typename void_to_fake_void<decltype(std::declval<Func>()())>::type invoke_fake_void(Func&& f, fake_void) +{ + return detail::invoke_fake_void(std::forward<Func>(f)); +} + +// Various properties of a continuation function +template<typename Func, typename Parent, typename = decltype(std::declval<Func>()())> +fake_void is_value_cont_helper(const Parent&, int, int); +template<typename Func, typename Parent, typename = decltype(std::declval<Func>()(std::declval<Parent>().get()))> +std::true_type is_value_cont_helper(const Parent&, int, int); +template<typename Func, typename = decltype(std::declval<Func>()())> +std::true_type is_value_cont_helper(const task<void>&, int, int); +template<typename Func, typename = decltype(std::declval<Func>()())> +std::true_type is_value_cont_helper(const shared_task<void>&, int, int); +template<typename Func, typename Parent, typename = decltype(std::declval<Func>()(std::declval<Parent>()))> +std::false_type is_value_cont_helper(const Parent&, int, ...); +template<typename Func, typename Parent> +void is_value_cont_helper(const Parent&, ...); +template<typename Parent, typename Func> +struct continuation_traits { + typedef typename std::decay<Func>::type decay_func; + typedef decltype(detail::is_value_cont_helper<decay_func>(std::declval<Parent>(), 0, 0)) is_value_cont; + static_assert(!std::is_void<is_value_cont>::value, "Parameter type for continuation function is invalid for parent task type"); + typedef typename std::conditional<std::is_same<is_value_cont, fake_void>::value, fake_void, typename std::conditional<std::is_same<is_value_cont, std::true_type>::value, typename void_to_fake_void<decltype(std::declval<Parent>().get())>::type, Parent>::type>::type param_type; + typedef decltype(detail::fake_void_to_void(detail::invoke_fake_void(std::declval<decay_func>(), std::declval<param_type>()))) result_type; + typedef task<typename remove_task<result_type>::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 0000000000000000000000000000000000000000..7166026334254cb2659702596dfdccf77a5722b2 --- /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 <async++.h> instead." +#endif + +namespace async { + +// Result type for when_any +template<typename Result> +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<typename Result> +struct when_all_state: public ref_count_base<when_all_state<Result>> { + event_task<Result> event; + Result result; + + when_all_state(std::size_t count) + : ref_count_base<when_all_state<Result>>(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<typename Task, typename Result> +struct when_all_func_range { + std::size_t index; + ref_count_ptr<when_all_state<Result>> state; + + when_all_func_range(std::size_t index_, ref_count_ptr<when_all_state<Result>> 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<std::size_t index, typename Task, typename Result> +struct when_all_func_tuple { + ref_count_ptr<when_all_state<Result>> state; + + when_all_func_tuple(ref_count_ptr<when_all_state<Result>> 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<index>(state->result) = std::move(t); + } +}; + +// Shared state for when_any +template<typename Result> +struct when_any_state: public ref_count_base<when_any_state<Result>> { + event_task<when_any_result<Result>> event; + Result result; + + when_any_state(std::size_t count) + : ref_count_base<when_any_state<Result>>(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<typename Task, typename Result> +struct when_any_func { + std::size_t index; + ref_count_ptr<when_any_state<Result>> state; + + when_any_func(std::size_t index_, ref_count_ptr<when_any_state<Result>> 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<std::size_t index, typename Result> +void when_all_variadic(when_all_state<Result>*) {} +template<std::size_t index, typename Result, typename First, typename... T> +void when_all_variadic(when_all_state<Result>* state, First&& first, T&&... tasks) +{ + typedef typename std::decay<First>::type task_type; + + // Add a continuation to the task + LIBASYNC_TRY { + first.then(inline_scheduler(), detail::when_all_func_tuple<index, task_type, Result>(detail::ref_count_ptr<detail::when_all_state<Result>>(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<index + 1>(state, std::forward<T>(tasks)...); +} + +// Internal implementation of when_any for variadic arguments +template<std::size_t index, typename Result> +void when_any_variadic(when_any_state<Result>*) {} +template<std::size_t index, typename Result, typename First, typename... T> +void when_any_variadic(when_any_state<Result>* state, First&& first, T&&... tasks) +{ + typedef typename std::decay<First>::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<index>(state->result), detail::task_ptr(t)); + + // Add a continuation to the task + LIBASYNC_TRY { + first.then(inline_scheduler(), detail::when_any_func<task_type, Result>(index, detail::ref_count_ptr<detail::when_any_state<Result>>(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<index + 1>(state, std::forward<T>(tasks)...); +} + +} // namespace detail + +// Combine a set of tasks into one task which is signaled when all specified tasks finish +template<typename Iter> +task<std::vector<typename std::decay<typename std::iterator_traits<Iter>::value_type>::type>> when_all(Iter begin, Iter end) +{ + typedef typename std::decay<typename std::iterator_traits<Iter>::value_type>::type task_type; + typedef std::vector<task_type> 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<result_type>(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<task_type, result_type>(i, detail::ref_count_ptr<detail::when_all_state<result_type>>(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<typename Iter> +task<when_any_result<std::vector<typename std::decay<typename std::iterator_traits<Iter>::value_type>::type>>> when_any(Iter begin, Iter end) +{ + typedef typename std::decay<typename std::iterator_traits<Iter>::value_type>::type task_type; + typedef std::vector<task_type> result_type; + + // Handle empty ranges + if (begin == end) + return make_task(when_any_result<result_type>()); + + // Create shared state, initialized with the proper reference count + std::size_t count = std::distance(begin, end); + auto* state = new detail::when_any_state<result_type>(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<task_type, result_type>(i, detail::ref_count_ptr<detail::when_any_state<result_type>>(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<typename T> +decltype(async::when_all(std::begin(std::declval<T>()), std::end(std::declval<T>()))) when_all(T&& tasks) +{ + return async::when_all(std::begin(std::forward<T>(tasks)), std::end(std::forward<T>(tasks))); +} + +// when_any wrapper accepting ranges +template<typename T> +decltype(async::when_any(std::begin(std::declval<T>()), std::end(std::declval<T>()))) when_any(T&& tasks) +{ + return async::when_any(std::begin(std::forward<T>(tasks)), std::end(std::forward<T>(tasks))); +} + +// when_all with variadic arguments +inline task<std::tuple<>> when_all() +{ + return async::make_task(std::tuple<>()); +} +template<typename... T> +task<std::tuple<typename std::decay<T>::type...>> when_all(T&&... tasks) +{ + typedef std::tuple<typename std::decay<T>::type...> result_type; + + // Create shared state + auto state = new detail::when_all_state<result_type>(sizeof...(tasks)); + auto out = state->event.get_task(); + + // Register all the tasks on the event + detail::when_all_variadic<0>(state, std::forward<T>(tasks)...); + + return out; +} + +// when_any with variadic arguments +inline task<when_any_result<std::tuple<>>> when_any() +{ + return async::make_task(when_any_result<std::tuple<>>()); +} +template<typename... T> +task<when_any_result<std::tuple<typename std::decay<T>::type...>>> when_any(T&&... tasks) +{ + typedef std::tuple<typename std::decay<T>::type...> result_type; + + // Create shared state + auto state = new detail::when_any_state<result_type>(sizeof...(tasks)); + auto out = state->event.get_task(); + + // Register all the tasks on the event + detail::when_any_variadic<0>(state, std::forward<T>(tasks)...); + + return out; +} + +} // namespace async diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/decode.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/decode.h new file mode 100644 index 0000000000000000000000000000000000000000..d98247509a8cbbb6158e170811fbf2b64db3937a --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/decode.h @@ -0,0 +1,503 @@ +// Copyright 2010 Google Inc. All Rights Reserved. +// +// Use of this source code is governed by a BSD-style license +// that can be found in the COPYING file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. +// ----------------------------------------------------------------------------- +// +// Main decoding functions for WebP images. +// +// Author: Skal (pascal.massimino@gmail.com) + +#ifndef WEBP_WEBP_DECODE_H_ +#define WEBP_WEBP_DECODE_H_ + +#include "./types.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#define WEBP_DECODER_ABI_VERSION 0x0209 // MAJOR(8b) + MINOR(8b) + +// Note: forward declaring enumerations is not allowed in (strict) C and C++, +// the types are left here for reference. +// typedef enum VP8StatusCode VP8StatusCode; +// typedef enum WEBP_CSP_MODE WEBP_CSP_MODE; +typedef struct WebPRGBABuffer WebPRGBABuffer; +typedef struct WebPYUVABuffer WebPYUVABuffer; +typedef struct WebPDecBuffer WebPDecBuffer; +typedef struct WebPIDecoder WebPIDecoder; +typedef struct WebPBitstreamFeatures WebPBitstreamFeatures; +typedef struct WebPDecoderOptions WebPDecoderOptions; +typedef struct WebPDecoderConfig WebPDecoderConfig; + +// Return the decoder's version number, packed in hexadecimal using 8bits for +// each of major/minor/revision. E.g: v2.5.7 is 0x020507. +WEBP_EXTERN int WebPGetDecoderVersion(void); + +// Retrieve basic header information: width, height. +// This function will also validate the header, returning true on success, +// false otherwise. '*width' and '*height' are only valid on successful return. +// Pointers 'width' and 'height' can be passed NULL if deemed irrelevant. +// Note: The following chunk sequences (before the raw VP8/VP8L data) are +// considered valid by this function: +// RIFF + VP8(L) +// RIFF + VP8X + (optional chunks) + VP8(L) +// ALPH + VP8 <-- Not a valid WebP format: only allowed for internal purpose. +// VP8(L) <-- Not a valid WebP format: only allowed for internal purpose. +WEBP_EXTERN int WebPGetInfo(const uint8_t* data, size_t data_size, + int* width, int* height); + +// Decodes WebP images pointed to by 'data' and returns RGBA samples, along +// with the dimensions in *width and *height. The ordering of samples in +// memory is R, G, B, A, R, G, B, A... in scan order (endian-independent). +// The returned pointer should be deleted calling WebPFree(). +// Returns NULL in case of error. +WEBP_EXTERN uint8_t* WebPDecodeRGBA(const uint8_t* data, size_t data_size, + int* width, int* height); + +// Same as WebPDecodeRGBA, but returning A, R, G, B, A, R, G, B... ordered data. +WEBP_EXTERN uint8_t* WebPDecodeARGB(const uint8_t* data, size_t data_size, + int* width, int* height); + +// Same as WebPDecodeRGBA, but returning B, G, R, A, B, G, R, A... ordered data. +WEBP_EXTERN uint8_t* WebPDecodeBGRA(const uint8_t* data, size_t data_size, + int* width, int* height); + +// Same as WebPDecodeRGBA, but returning R, G, B, R, G, B... ordered data. +// If the bitstream contains transparency, it is ignored. +WEBP_EXTERN uint8_t* WebPDecodeRGB(const uint8_t* data, size_t data_size, + int* width, int* height); + +// Same as WebPDecodeRGB, but returning B, G, R, B, G, R... ordered data. +WEBP_EXTERN uint8_t* WebPDecodeBGR(const uint8_t* data, size_t data_size, + int* width, int* height); + + +// Decode WebP images pointed to by 'data' to Y'UV format(*). The pointer +// returned is the Y samples buffer. Upon return, *u and *v will point to +// the U and V chroma data. These U and V buffers need NOT be passed to +// WebPFree(), unlike the returned Y luma one. The dimension of the U and V +// planes are both (*width + 1) / 2 and (*height + 1)/ 2. +// Upon return, the Y buffer has a stride returned as '*stride', while U and V +// have a common stride returned as '*uv_stride'. +// Return NULL in case of error. +// (*) Also named Y'CbCr. See: https://en.wikipedia.org/wiki/YCbCr +WEBP_EXTERN uint8_t* WebPDecodeYUV(const uint8_t* data, size_t data_size, + int* width, int* height, + uint8_t** u, uint8_t** v, + int* stride, int* uv_stride); + +// These five functions are variants of the above ones, that decode the image +// directly into a pre-allocated buffer 'output_buffer'. The maximum storage +// available in this buffer is indicated by 'output_buffer_size'. If this +// storage is not sufficient (or an error occurred), NULL is returned. +// Otherwise, output_buffer is returned, for convenience. +// The parameter 'output_stride' specifies the distance (in bytes) +// between scanlines. Hence, output_buffer_size is expected to be at least +// output_stride x picture-height. +WEBP_EXTERN uint8_t* WebPDecodeRGBAInto( + const uint8_t* data, size_t data_size, + uint8_t* output_buffer, size_t output_buffer_size, int output_stride); +WEBP_EXTERN uint8_t* WebPDecodeARGBInto( + const uint8_t* data, size_t data_size, + uint8_t* output_buffer, size_t output_buffer_size, int output_stride); +WEBP_EXTERN uint8_t* WebPDecodeBGRAInto( + const uint8_t* data, size_t data_size, + uint8_t* output_buffer, size_t output_buffer_size, int output_stride); + +// RGB and BGR variants. Here too the transparency information, if present, +// will be dropped and ignored. +WEBP_EXTERN uint8_t* WebPDecodeRGBInto( + const uint8_t* data, size_t data_size, + uint8_t* output_buffer, size_t output_buffer_size, int output_stride); +WEBP_EXTERN uint8_t* WebPDecodeBGRInto( + const uint8_t* data, size_t data_size, + uint8_t* output_buffer, size_t output_buffer_size, int output_stride); + +// WebPDecodeYUVInto() is a variant of WebPDecodeYUV() that operates directly +// into pre-allocated luma/chroma plane buffers. This function requires the +// strides to be passed: one for the luma plane and one for each of the +// chroma ones. The size of each plane buffer is passed as 'luma_size', +// 'u_size' and 'v_size' respectively. +// Pointer to the luma plane ('*luma') is returned or NULL if an error occurred +// during decoding (or because some buffers were found to be too small). +WEBP_EXTERN uint8_t* WebPDecodeYUVInto( + const uint8_t* data, size_t data_size, + uint8_t* luma, size_t luma_size, int luma_stride, + uint8_t* u, size_t u_size, int u_stride, + uint8_t* v, size_t v_size, int v_stride); + +//------------------------------------------------------------------------------ +// Output colorspaces and buffer + +// Colorspaces +// Note: the naming describes the byte-ordering of packed samples in memory. +// For instance, MODE_BGRA relates to samples ordered as B,G,R,A,B,G,R,A,... +// Non-capital names (e.g.:MODE_Argb) relates to pre-multiplied RGB channels. +// RGBA-4444 and RGB-565 colorspaces are represented by following byte-order: +// RGBA-4444: [r3 r2 r1 r0 g3 g2 g1 g0], [b3 b2 b1 b0 a3 a2 a1 a0], ... +// RGB-565: [r4 r3 r2 r1 r0 g5 g4 g3], [g2 g1 g0 b4 b3 b2 b1 b0], ... +// In the case WEBP_SWAP_16BITS_CSP is defined, the bytes are swapped for +// these two modes: +// RGBA-4444: [b3 b2 b1 b0 a3 a2 a1 a0], [r3 r2 r1 r0 g3 g2 g1 g0], ... +// RGB-565: [g2 g1 g0 b4 b3 b2 b1 b0], [r4 r3 r2 r1 r0 g5 g4 g3], ... + +typedef enum WEBP_CSP_MODE { + MODE_RGB = 0, MODE_RGBA = 1, + MODE_BGR = 2, MODE_BGRA = 3, + MODE_ARGB = 4, MODE_RGBA_4444 = 5, + MODE_RGB_565 = 6, + // RGB-premultiplied transparent modes (alpha value is preserved) + MODE_rgbA = 7, + MODE_bgrA = 8, + MODE_Argb = 9, + MODE_rgbA_4444 = 10, + // YUV modes must come after RGB ones. + MODE_YUV = 11, MODE_YUVA = 12, // yuv 4:2:0 + MODE_LAST = 13 +} WEBP_CSP_MODE; + +// Some useful macros: +static WEBP_INLINE int WebPIsPremultipliedMode(WEBP_CSP_MODE mode) { + return (mode == MODE_rgbA || mode == MODE_bgrA || mode == MODE_Argb || + mode == MODE_rgbA_4444); +} + +static WEBP_INLINE int WebPIsAlphaMode(WEBP_CSP_MODE mode) { + return (mode == MODE_RGBA || mode == MODE_BGRA || mode == MODE_ARGB || + mode == MODE_RGBA_4444 || mode == MODE_YUVA || + WebPIsPremultipliedMode(mode)); +} + +static WEBP_INLINE int WebPIsRGBMode(WEBP_CSP_MODE mode) { + return (mode < MODE_YUV); +} + +//------------------------------------------------------------------------------ +// WebPDecBuffer: Generic structure for describing the output sample buffer. + +struct WebPRGBABuffer { // view as RGBA + uint8_t* rgba; // pointer to RGBA samples + int stride; // stride in bytes from one scanline to the next. + size_t size; // total size of the *rgba buffer. +}; + +struct WebPYUVABuffer { // view as YUVA + uint8_t* y, *u, *v, *a; // pointer to luma, chroma U/V, alpha samples + int y_stride; // luma stride + int u_stride, v_stride; // chroma strides + int a_stride; // alpha stride + size_t y_size; // luma plane size + size_t u_size, v_size; // chroma planes size + size_t a_size; // alpha-plane size +}; + +// Output buffer +struct WebPDecBuffer { + WEBP_CSP_MODE colorspace; // Colorspace. + int width, height; // Dimensions. + int is_external_memory; // If non-zero, 'internal_memory' pointer is not + // used. If value is '2' or more, the external + // memory is considered 'slow' and multiple + // read/write will be avoided. + union { + WebPRGBABuffer RGBA; + WebPYUVABuffer YUVA; + } u; // Nameless union of buffer parameters. + uint32_t pad[4]; // padding for later use + + uint8_t* private_memory; // Internally allocated memory (only when + // is_external_memory is 0). Should not be used + // externally, but accessed via the buffer union. +}; + +// Internal, version-checked, entry point +WEBP_EXTERN int WebPInitDecBufferInternal(WebPDecBuffer*, int); + +// Initialize the structure as empty. Must be called before any other use. +// Returns false in case of version mismatch +static WEBP_INLINE int WebPInitDecBuffer(WebPDecBuffer* buffer) { + return WebPInitDecBufferInternal(buffer, WEBP_DECODER_ABI_VERSION); +} + +// Free any memory associated with the buffer. Must always be called last. +// Note: doesn't free the 'buffer' structure itself. +WEBP_EXTERN void WebPFreeDecBuffer(WebPDecBuffer* buffer); + +//------------------------------------------------------------------------------ +// Enumeration of the status codes + +typedef enum VP8StatusCode { + VP8_STATUS_OK = 0, + VP8_STATUS_OUT_OF_MEMORY, + VP8_STATUS_INVALID_PARAM, + VP8_STATUS_BITSTREAM_ERROR, + VP8_STATUS_UNSUPPORTED_FEATURE, + VP8_STATUS_SUSPENDED, + VP8_STATUS_USER_ABORT, + VP8_STATUS_NOT_ENOUGH_DATA +} VP8StatusCode; + +//------------------------------------------------------------------------------ +// Incremental decoding +// +// This API allows streamlined decoding of partial data. +// Picture can be incrementally decoded as data become available thanks to the +// WebPIDecoder object. This object can be left in a SUSPENDED state if the +// picture is only partially decoded, pending additional input. +// Code example: +// +// WebPInitDecBuffer(&output_buffer); +// output_buffer.colorspace = mode; +// ... +// WebPIDecoder* idec = WebPINewDecoder(&output_buffer); +// while (additional_data_is_available) { +// // ... (get additional data in some new_data[] buffer) +// status = WebPIAppend(idec, new_data, new_data_size); +// if (status != VP8_STATUS_OK && status != VP8_STATUS_SUSPENDED) { +// break; // an error occurred. +// } +// +// // The above call decodes the current available buffer. +// // Part of the image can now be refreshed by calling +// // WebPIDecGetRGB()/WebPIDecGetYUVA() etc. +// } +// WebPIDelete(idec); + +// Creates a new incremental decoder with the supplied buffer parameter. +// This output_buffer can be passed NULL, in which case a default output buffer +// is used (with MODE_RGB). Otherwise, an internal reference to 'output_buffer' +// is kept, which means that the lifespan of 'output_buffer' must be larger than +// that of the returned WebPIDecoder object. +// The supplied 'output_buffer' content MUST NOT be changed between calls to +// WebPIAppend() or WebPIUpdate() unless 'output_buffer.is_external_memory' is +// not set to 0. In such a case, it is allowed to modify the pointers, size and +// stride of output_buffer.u.RGBA or output_buffer.u.YUVA, provided they remain +// within valid bounds. +// All other fields of WebPDecBuffer MUST remain constant between calls. +// Returns NULL if the allocation failed. +WEBP_EXTERN WebPIDecoder* WebPINewDecoder(WebPDecBuffer* output_buffer); + +// This function allocates and initializes an incremental-decoder object, which +// will output the RGB/A samples specified by 'csp' into a preallocated +// buffer 'output_buffer'. The size of this buffer is at least +// 'output_buffer_size' and the stride (distance in bytes between two scanlines) +// is specified by 'output_stride'. +// Additionally, output_buffer can be passed NULL in which case the output +// buffer will be allocated automatically when the decoding starts. The +// colorspace 'csp' is taken into account for allocating this buffer. All other +// parameters are ignored. +// Returns NULL if the allocation failed, or if some parameters are invalid. +WEBP_EXTERN WebPIDecoder* WebPINewRGB( + WEBP_CSP_MODE csp, + uint8_t* output_buffer, size_t output_buffer_size, int output_stride); + +// This function allocates and initializes an incremental-decoder object, which +// will output the raw luma/chroma samples into a preallocated planes if +// supplied. The luma plane is specified by its pointer 'luma', its size +// 'luma_size' and its stride 'luma_stride'. Similarly, the chroma-u plane +// is specified by the 'u', 'u_size' and 'u_stride' parameters, and the chroma-v +// plane by 'v' and 'v_size'. And same for the alpha-plane. The 'a' pointer +// can be pass NULL in case one is not interested in the transparency plane. +// Conversely, 'luma' can be passed NULL if no preallocated planes are supplied. +// In this case, the output buffer will be automatically allocated (using +// MODE_YUVA) when decoding starts. All parameters are then ignored. +// Returns NULL if the allocation failed or if a parameter is invalid. +WEBP_EXTERN WebPIDecoder* WebPINewYUVA( + uint8_t* luma, size_t luma_size, int luma_stride, + uint8_t* u, size_t u_size, int u_stride, + uint8_t* v, size_t v_size, int v_stride, + uint8_t* a, size_t a_size, int a_stride); + +// Deprecated version of the above, without the alpha plane. +// Kept for backward compatibility. +WEBP_EXTERN WebPIDecoder* WebPINewYUV( + uint8_t* luma, size_t luma_size, int luma_stride, + uint8_t* u, size_t u_size, int u_stride, + uint8_t* v, size_t v_size, int v_stride); + +// Deletes the WebPIDecoder object and associated memory. Must always be called +// if WebPINewDecoder, WebPINewRGB or WebPINewYUV succeeded. +WEBP_EXTERN void WebPIDelete(WebPIDecoder* idec); + +// Copies and decodes the next available data. Returns VP8_STATUS_OK when +// the image is successfully decoded. Returns VP8_STATUS_SUSPENDED when more +// data is expected. Returns error in other cases. +WEBP_EXTERN VP8StatusCode WebPIAppend( + WebPIDecoder* idec, const uint8_t* data, size_t data_size); + +// A variant of the above function to be used when data buffer contains +// partial data from the beginning. In this case data buffer is not copied +// to the internal memory. +// Note that the value of the 'data' pointer can change between calls to +// WebPIUpdate, for instance when the data buffer is resized to fit larger data. +WEBP_EXTERN VP8StatusCode WebPIUpdate( + WebPIDecoder* idec, const uint8_t* data, size_t data_size); + +// Returns the RGB/A image decoded so far. Returns NULL if output params +// are not initialized yet. The RGB/A output type corresponds to the colorspace +// specified during call to WebPINewDecoder() or WebPINewRGB(). +// *last_y is the index of last decoded row in raster scan order. Some pointers +// (*last_y, *width etc.) can be NULL if corresponding information is not +// needed. The values in these pointers are only valid on successful (non-NULL) +// return. +WEBP_EXTERN uint8_t* WebPIDecGetRGB( + const WebPIDecoder* idec, int* last_y, + int* width, int* height, int* stride); + +// Same as above function to get a YUVA image. Returns pointer to the luma +// plane or NULL in case of error. If there is no alpha information +// the alpha pointer '*a' will be returned NULL. +WEBP_EXTERN uint8_t* WebPIDecGetYUVA( + const WebPIDecoder* idec, int* last_y, + uint8_t** u, uint8_t** v, uint8_t** a, + int* width, int* height, int* stride, int* uv_stride, int* a_stride); + +// Deprecated alpha-less version of WebPIDecGetYUVA(): it will ignore the +// alpha information (if present). Kept for backward compatibility. +static WEBP_INLINE uint8_t* WebPIDecGetYUV( + const WebPIDecoder* idec, int* last_y, uint8_t** u, uint8_t** v, + int* width, int* height, int* stride, int* uv_stride) { + return WebPIDecGetYUVA(idec, last_y, u, v, NULL, width, height, + stride, uv_stride, NULL); +} + +// Generic call to retrieve information about the displayable area. +// If non NULL, the left/right/width/height pointers are filled with the visible +// rectangular area so far. +// Returns NULL in case the incremental decoder object is in an invalid state. +// Otherwise returns the pointer to the internal representation. This structure +// is read-only, tied to WebPIDecoder's lifespan and should not be modified. +WEBP_EXTERN const WebPDecBuffer* WebPIDecodedArea( + const WebPIDecoder* idec, int* left, int* top, int* width, int* height); + +//------------------------------------------------------------------------------ +// Advanced decoding parametrization +// +// Code sample for using the advanced decoding API +/* + // A) Init a configuration object + WebPDecoderConfig config; + CHECK(WebPInitDecoderConfig(&config)); + + // B) optional: retrieve the bitstream's features. + CHECK(WebPGetFeatures(data, data_size, &config.input) == VP8_STATUS_OK); + + // C) Adjust 'config', if needed + config.no_fancy_upsampling = 1; + config.output.colorspace = MODE_BGRA; + // etc. + + // Note that you can also make config.output point to an externally + // supplied memory buffer, provided it's big enough to store the decoded + // picture. Otherwise, config.output will just be used to allocate memory + // and store the decoded picture. + + // D) Decode! + CHECK(WebPDecode(data, data_size, &config) == VP8_STATUS_OK); + + // E) Decoded image is now in config.output (and config.output.u.RGBA) + + // F) Reclaim memory allocated in config's object. It's safe to call + // this function even if the memory is external and wasn't allocated + // by WebPDecode(). + WebPFreeDecBuffer(&config.output); +*/ + +// Features gathered from the bitstream +struct WebPBitstreamFeatures { + int width; // Width in pixels, as read from the bitstream. + int height; // Height in pixels, as read from the bitstream. + int has_alpha; // True if the bitstream contains an alpha channel. + int has_animation; // True if the bitstream is an animation. + int format; // 0 = undefined (/mixed), 1 = lossy, 2 = lossless + + uint32_t pad[5]; // padding for later use +}; + +// Internal, version-checked, entry point +WEBP_EXTERN VP8StatusCode WebPGetFeaturesInternal( + const uint8_t*, size_t, WebPBitstreamFeatures*, int); + +// Retrieve features from the bitstream. The *features structure is filled +// with information gathered from the bitstream. +// Returns VP8_STATUS_OK when the features are successfully retrieved. Returns +// VP8_STATUS_NOT_ENOUGH_DATA when more data is needed to retrieve the +// features from headers. Returns error in other cases. +// Note: The following chunk sequences (before the raw VP8/VP8L data) are +// considered valid by this function: +// RIFF + VP8(L) +// RIFF + VP8X + (optional chunks) + VP8(L) +// ALPH + VP8 <-- Not a valid WebP format: only allowed for internal purpose. +// VP8(L) <-- Not a valid WebP format: only allowed for internal purpose. +static WEBP_INLINE VP8StatusCode WebPGetFeatures( + const uint8_t* data, size_t data_size, + WebPBitstreamFeatures* features) { + return WebPGetFeaturesInternal(data, data_size, features, + WEBP_DECODER_ABI_VERSION); +} + +// Decoding options +struct WebPDecoderOptions { + int bypass_filtering; // if true, skip the in-loop filtering + int no_fancy_upsampling; // if true, use faster pointwise upsampler + int use_cropping; // if true, cropping is applied _first_ + int crop_left, crop_top; // top-left position for cropping. + // Will be snapped to even values. + int crop_width, crop_height; // dimension of the cropping area + int use_scaling; // if true, scaling is applied _afterward_ + int scaled_width, scaled_height; // final resolution + int use_threads; // if true, use multi-threaded decoding + int dithering_strength; // dithering strength (0=Off, 100=full) + int flip; // if true, flip output vertically + int alpha_dithering_strength; // alpha dithering strength in [0..100] + + uint32_t pad[5]; // padding for later use +}; + +// Main object storing the configuration for advanced decoding. +struct WebPDecoderConfig { + WebPBitstreamFeatures input; // Immutable bitstream features (optional) + WebPDecBuffer output; // Output buffer (can point to external mem) + WebPDecoderOptions options; // Decoding options +}; + +// Internal, version-checked, entry point +WEBP_EXTERN int WebPInitDecoderConfigInternal(WebPDecoderConfig*, int); + +// Initialize the configuration as empty. This function must always be +// called first, unless WebPGetFeatures() is to be called. +// Returns false in case of mismatched version. +static WEBP_INLINE int WebPInitDecoderConfig(WebPDecoderConfig* config) { + return WebPInitDecoderConfigInternal(config, WEBP_DECODER_ABI_VERSION); +} + +// Instantiate a new incremental decoder object with the requested +// configuration. The bitstream can be passed using 'data' and 'data_size' +// parameter, in which case the features will be parsed and stored into +// config->input. Otherwise, 'data' can be NULL and no parsing will occur. +// Note that 'config' can be NULL too, in which case a default configuration +// is used. If 'config' is not NULL, it must outlive the WebPIDecoder object +// as some references to its fields will be used. No internal copy of 'config' +// is made. +// The return WebPIDecoder object must always be deleted calling WebPIDelete(). +// Returns NULL in case of error (and config->status will then reflect +// the error condition, if available). +WEBP_EXTERN WebPIDecoder* WebPIDecode(const uint8_t* data, size_t data_size, + WebPDecoderConfig* config); + +// Non-incremental version. This version decodes the full data at once, taking +// 'config' into account. Returns decoding status (which should be VP8_STATUS_OK +// if the decoding was successful). Note that 'config' cannot be NULL. +WEBP_EXTERN VP8StatusCode WebPDecode(const uint8_t* data, size_t data_size, + WebPDecoderConfig* config); + +#ifdef __cplusplus +} // extern "C" +#endif + +#endif // WEBP_WEBP_DECODE_H_ diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/CMakeLists.txt b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/CMakeLists.txt new file mode 100644 index 0000000000000000000000000000000000000000..4ff51c8180b8526683dd50a8296f0c84da87d380 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/CMakeLists.txt @@ -0,0 +1,70 @@ +file(GLOB ROOT_SOURCE *.cpp) +file(GLOB ROOT_INLINE *.inl) +file(GLOB ROOT_HEADER *.hpp) +file(GLOB ROOT_TEXT ../*.txt) +file(GLOB ROOT_MD ../*.md) +file(GLOB ROOT_NAT ../util/glm.natvis) + +file(GLOB_RECURSE CORE_SOURCE ./detail/*.cpp) +file(GLOB_RECURSE CORE_INLINE ./detail/*.inl) +file(GLOB_RECURSE CORE_HEADER ./detail/*.hpp) + +file(GLOB_RECURSE EXT_SOURCE ./ext/*.cpp) +file(GLOB_RECURSE EXT_INLINE ./ext/*.inl) +file(GLOB_RECURSE EXT_HEADER ./ext/*.hpp) + +file(GLOB_RECURSE GTC_SOURCE ./gtc/*.cpp) +file(GLOB_RECURSE GTC_INLINE ./gtc/*.inl) +file(GLOB_RECURSE GTC_HEADER ./gtc/*.hpp) + +file(GLOB_RECURSE GTX_SOURCE ./gtx/*.cpp) +file(GLOB_RECURSE GTX_INLINE ./gtx/*.inl) +file(GLOB_RECURSE GTX_HEADER ./gtx/*.hpp) + +file(GLOB_RECURSE SIMD_SOURCE ./simd/*.cpp) +file(GLOB_RECURSE SIMD_INLINE ./simd/*.inl) +file(GLOB_RECURSE SIMD_HEADER ./simd/*.h) + +source_group("Text Files" FILES ${ROOT_TEXT} ${ROOT_MD}) +source_group("Core Files" FILES ${CORE_SOURCE}) +source_group("Core Files" FILES ${CORE_INLINE}) +source_group("Core Files" FILES ${CORE_HEADER}) +source_group("EXT Files" FILES ${EXT_SOURCE}) +source_group("EXT Files" FILES ${EXT_INLINE}) +source_group("EXT Files" FILES ${EXT_HEADER}) +source_group("GTC Files" FILES ${GTC_SOURCE}) +source_group("GTC Files" FILES ${GTC_INLINE}) +source_group("GTC Files" FILES ${GTC_HEADER}) +source_group("GTX Files" FILES ${GTX_SOURCE}) +source_group("GTX Files" FILES ${GTX_INLINE}) +source_group("GTX Files" FILES ${GTX_HEADER}) +source_group("SIMD Files" FILES ${SIMD_SOURCE}) +source_group("SIMD Files" FILES ${SIMD_INLINE}) +source_group("SIMD Files" FILES ${SIMD_HEADER}) + +add_library(glm INTERFACE) +target_include_directories(glm INTERFACE ../) + +if(BUILD_STATIC_LIBS) +add_library(glm_static STATIC ${ROOT_TEXT} ${ROOT_MD} ${ROOT_NAT} + ${ROOT_SOURCE} ${ROOT_INLINE} ${ROOT_HEADER} + ${CORE_SOURCE} ${CORE_INLINE} ${CORE_HEADER} + ${EXT_SOURCE} ${EXT_INLINE} ${EXT_HEADER} + ${GTC_SOURCE} ${GTC_INLINE} ${GTC_HEADER} + ${GTX_SOURCE} ${GTX_INLINE} ${GTX_HEADER} + ${SIMD_SOURCE} ${SIMD_INLINE} ${SIMD_HEADER}) + target_link_libraries(glm_static PUBLIC glm) + add_library(glm::glm_static ALIAS glm_static) +endif() + +if(BUILD_SHARED_LIBS) +add_library(glm_shared SHARED ${ROOT_TEXT} ${ROOT_MD} ${ROOT_NAT} + ${ROOT_SOURCE} ${ROOT_INLINE} ${ROOT_HEADER} + ${CORE_SOURCE} ${CORE_INLINE} ${CORE_HEADER} + ${EXT_SOURCE} ${EXT_INLINE} ${EXT_HEADER} + ${GTC_SOURCE} ${GTC_INLINE} ${GTC_HEADER} + ${GTX_SOURCE} ${GTX_INLINE} ${GTX_HEADER} + ${SIMD_SOURCE} ${SIMD_INLINE} ${SIMD_HEADER}) + target_link_libraries(glm_shared PUBLIC glm) + add_library(glm::glm_shared ALIAS glm_shared) +endif() 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 0000000000000000000000000000000000000000..0328dc91ee26fb5a760342b09879a3152840414c --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/common.hpp @@ -0,0 +1,539 @@ +/// @ref core +/// @file glm/common.hpp +/// +/// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 8.3 Common Functions</a> +/// +/// @defgroup core_func_common Common functions +/// @ingroup core +/// +/// Provides GLSL common functions +/// +/// These all operate component-wise. The description is per component. +/// +/// Include <glm/common.hpp> 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 <a href="http://www.opengl.org/sdk/docs/manglsl/xhtml/abs.xml">GLSL abs man page</a> + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 8.3 Common Functions</a> + template<typename genType> + 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 <a href="http://www.opengl.org/sdk/docs/manglsl/xhtml/abs.xml">GLSL abs man page</a> + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 8.3 Common Functions</a> + template<length_t L, typename T, qualifier Q> + GLM_FUNC_DECL GLM_CONSTEXPR vec<L, T, Q> abs(vec<L, T, Q> 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 <a href="http://www.opengl.org/sdk/docs/manglsl/xhtml/sign.xml">GLSL sign man page</a> + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 8.3 Common Functions</a> + template<length_t L, typename T, qualifier Q> + GLM_FUNC_DECL vec<L, T, Q> sign(vec<L, T, Q> 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 <a href="http://www.opengl.org/sdk/docs/manglsl/xhtml/floor.xml">GLSL floor man page</a> + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 8.3 Common Functions</a> + template<length_t L, typename T, qualifier Q> + GLM_FUNC_DECL vec<L, T, Q> floor(vec<L, T, Q> 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 <a href="http://www.opengl.org/sdk/docs/manglsl/xhtml/trunc.xml">GLSL trunc man page</a> + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 8.3 Common Functions</a> + template<length_t L, typename T, qualifier Q> + GLM_FUNC_DECL vec<L, T, Q> trunc(vec<L, T, Q> 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 <a href="http://www.opengl.org/sdk/docs/manglsl/xhtml/round.xml">GLSL round man page</a> + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 8.3 Common Functions</a> + template<length_t L, typename T, qualifier Q> + GLM_FUNC_DECL vec<L, T, Q> round(vec<L, T, Q> 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 <a href="http://www.opengl.org/sdk/docs/manglsl/xhtml/roundEven.xml">GLSL roundEven man page</a> + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 8.3 Common Functions</a> + /// @see <a href="http://developer.amd.com/documentation/articles/pages/New-Round-to-Even-Technique.aspx">New round to even technique</a> + template<length_t L, typename T, qualifier Q> + GLM_FUNC_DECL vec<L, T, Q> roundEven(vec<L, T, Q> 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 <a href="http://www.opengl.org/sdk/docs/manglsl/xhtml/ceil.xml">GLSL ceil man page</a> + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 8.3 Common Functions</a> + template<length_t L, typename T, qualifier Q> + GLM_FUNC_DECL vec<L, T, Q> ceil(vec<L, T, Q> const& x); + + /// Return x - floor(x). + /// + /// @tparam genType Floating-point scalar or vector types. + /// + /// @see <a href="http://www.opengl.org/sdk/docs/manglsl/xhtml/fract.xml">GLSL fract man page</a> + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 8.3 Common Functions</a> + template<typename genType> + 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 <a href="http://www.opengl.org/sdk/docs/manglsl/xhtml/fract.xml">GLSL fract man page</a> + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 8.3 Common Functions</a> + template<length_t L, typename T, qualifier Q> + GLM_FUNC_DECL vec<L, T, Q> fract(vec<L, T, Q> const& x); + + template<typename genType> + GLM_FUNC_DECL genType mod(genType x, genType y); + + template<length_t L, typename T, qualifier Q> + GLM_FUNC_DECL vec<L, T, Q> mod(vec<L, T, Q> 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 <a href="http://www.opengl.org/sdk/docs/manglsl/xhtml/mod.xml">GLSL mod man page</a> + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 8.3 Common Functions</a> + template<length_t L, typename T, qualifier Q> + GLM_FUNC_DECL vec<L, T, Q> mod(vec<L, T, Q> const& x, vec<L, T, Q> 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 <a href="http://www.opengl.org/sdk/docs/manglsl/xhtml/modf.xml">GLSL modf man page</a> + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 8.3 Common Functions</a> + template<typename genType> + 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 <a href="http://www.opengl.org/sdk/docs/manglsl/xhtml/min.xml">GLSL min man page</a> + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 8.3 Common Functions</a> + template<typename genType> + 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 <a href="http://www.opengl.org/sdk/docs/manglsl/xhtml/min.xml">GLSL min man page</a> + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 8.3 Common Functions</a> + template<length_t L, typename T, qualifier Q> + GLM_FUNC_DECL GLM_CONSTEXPR vec<L, T, Q> min(vec<L, T, Q> 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 <a href="http://www.opengl.org/sdk/docs/manglsl/xhtml/min.xml">GLSL min man page</a> + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 8.3 Common Functions</a> + template<length_t L, typename T, qualifier Q> + GLM_FUNC_DECL GLM_CONSTEXPR vec<L, T, Q> min(vec<L, T, Q> const& x, vec<L, T, Q> const& y); + + /// Returns y if x < y; otherwise, it returns x. + /// + /// @tparam genType Floating-point or integer; scalar or vector types. + /// + /// @see <a href="http://www.opengl.org/sdk/docs/manglsl/xhtml/max.xml">GLSL max man page</a> + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 8.3 Common Functions</a> + template<typename genType> + 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 <a href="http://www.opengl.org/sdk/docs/manglsl/xhtml/max.xml">GLSL max man page</a> + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 8.3 Common Functions</a> + template<length_t L, typename T, qualifier Q> + GLM_FUNC_DECL GLM_CONSTEXPR vec<L, T, Q> max(vec<L, T, Q> 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 <a href="http://www.opengl.org/sdk/docs/manglsl/xhtml/max.xml">GLSL max man page</a> + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 8.3 Common Functions</a> + template<length_t L, typename T, qualifier Q> + GLM_FUNC_DECL GLM_CONSTEXPR vec<L, T, Q> max(vec<L, T, Q> const& x, vec<L, T, Q> 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 <a href="http://www.opengl.org/sdk/docs/manglsl/xhtml/clamp.xml">GLSL clamp man page</a> + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 8.3 Common Functions</a> + template<typename genType> + 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 <a href="http://www.opengl.org/sdk/docs/manglsl/xhtml/clamp.xml">GLSL clamp man page</a> + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 8.3 Common Functions</a> + template<length_t L, typename T, qualifier Q> + GLM_FUNC_DECL GLM_CONSTEXPR vec<L, T, Q> clamp(vec<L, T, Q> 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 <a href="http://www.opengl.org/sdk/docs/manglsl/xhtml/clamp.xml">GLSL clamp man page</a> + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 8.3 Common Functions</a> + template<length_t L, typename T, qualifier Q> + GLM_FUNC_DECL GLM_CONSTEXPR vec<L, T, Q> clamp(vec<L, T, Q> const& x, vec<L, T, Q> const& minVal, vec<L, T, Q> 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 <a href="http://www.opengl.org/sdk/docs/manglsl/xhtml/mix.xml">GLSL mix man page</a> + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 8.3 Common Functions</a> + /// + /// @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 <glm/glm.hpp> + /// ... + /// 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<typename genTypeT, typename genTypeU> + GLM_FUNC_DECL genTypeT mix(genTypeT x, genTypeT y, genTypeU a); + + template<length_t L, typename T, typename U, qualifier Q> + GLM_FUNC_DECL vec<L, T, Q> mix(vec<L, T, Q> const& x, vec<L, T, Q> const& y, vec<L, U, Q> const& a); + + template<length_t L, typename T, typename U, qualifier Q> + GLM_FUNC_DECL vec<L, T, Q> mix(vec<L, T, Q> const& x, vec<L, T, Q> const& y, U a); + + /// Returns 0.0 if x < edge, otherwise it returns 1.0 for each component of a genType. + /// + /// @see <a href="http://www.opengl.org/sdk/docs/manglsl/xhtml/step.xml">GLSL step man page</a> + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 8.3 Common Functions</a> + template<typename genType> + 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 <a href="http://www.opengl.org/sdk/docs/manglsl/xhtml/step.xml">GLSL step man page</a> + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 8.3 Common Functions</a> + template<length_t L, typename T, qualifier Q> + GLM_FUNC_DECL vec<L, T, Q> step(T edge, vec<L, T, Q> 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 <a href="http://www.opengl.org/sdk/docs/manglsl/xhtml/step.xml">GLSL step man page</a> + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 8.3 Common Functions</a> + template<length_t L, typename T, qualifier Q> + GLM_FUNC_DECL vec<L, T, Q> step(vec<L, T, Q> const& edge, vec<L, T, Q> 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 <a href="http://www.opengl.org/sdk/docs/manglsl/xhtml/smoothstep.xml">GLSL smoothstep man page</a> + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 8.3 Common Functions</a> + template<typename genType> + GLM_FUNC_DECL genType smoothstep(genType edge0, genType edge1, genType x); + + template<length_t L, typename T, qualifier Q> + GLM_FUNC_DECL vec<L, T, Q> smoothstep(T edge0, T edge1, vec<L, T, Q> const& x); + + template<length_t L, typename T, qualifier Q> + GLM_FUNC_DECL vec<L, T, Q> smoothstep(vec<L, T, Q> const& edge0, vec<L, T, Q> const& edge1, vec<L, T, Q> 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 <a href="http://www.opengl.org/sdk/docs/manglsl/xhtml/isnan.xml">GLSL isnan man page</a> + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 8.3 Common Functions</a> + template<length_t L, typename T, qualifier Q> + GLM_FUNC_DECL vec<L, bool, Q> isnan(vec<L, T, Q> 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 <a href="http://www.opengl.org/sdk/docs/manglsl/xhtml/isinf.xml">GLSL isinf man page</a> + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 8.3 Common Functions</a> + template<length_t L, typename T, qualifier Q> + GLM_FUNC_DECL vec<L, bool, Q> isinf(vec<L, T, Q> 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 <a href="http://www.opengl.org/sdk/docs/manglsl/xhtml/floatBitsToInt.xml">GLSL floatBitsToInt man page</a> + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 8.3 Common Functions</a> + GLM_FUNC_DECL int floatBitsToInt(float const& 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 <a href="http://www.opengl.org/sdk/docs/manglsl/xhtml/floatBitsToInt.xml">GLSL floatBitsToInt man page</a> + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 8.3 Common Functions</a> + template<length_t L, qualifier Q> + GLM_FUNC_DECL vec<L, int, Q> floatBitsToInt(vec<L, float, Q> 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 <a href="http://www.opengl.org/sdk/docs/manglsl/xhtml/floatBitsToUint.xml">GLSL floatBitsToUint man page</a> + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 8.3 Common Functions</a> + GLM_FUNC_DECL uint floatBitsToUint(float const& 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 <a href="http://www.opengl.org/sdk/docs/manglsl/xhtml/floatBitsToUint.xml">GLSL floatBitsToUint man page</a> + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 8.3 Common Functions</a> + template<length_t L, qualifier Q> + GLM_FUNC_DECL vec<L, uint, Q> floatBitsToUint(vec<L, float, Q> 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 <a href="http://www.opengl.org/sdk/docs/manglsl/xhtml/intBitsToFloat.xml">GLSL intBitsToFloat man page</a> + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 8.3 Common Functions</a> + GLM_FUNC_DECL float intBitsToFloat(int 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. + /// + /// @tparam L Integer between 1 and 4 included that qualify the dimension of the vector + /// @tparam Q Value from qualifier enum + /// + /// @see <a href="http://www.opengl.org/sdk/docs/manglsl/xhtml/intBitsToFloat.xml">GLSL intBitsToFloat man page</a> + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 8.3 Common Functions</a> + template<length_t L, qualifier Q> + GLM_FUNC_DECL vec<L, float, Q> intBitsToFloat(vec<L, int, Q> 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 <a href="http://www.opengl.org/sdk/docs/manglsl/xhtml/uintBitsToFloat.xml">GLSL uintBitsToFloat man page</a> + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 8.3 Common Functions</a> + GLM_FUNC_DECL float uintBitsToFloat(uint 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. + /// + /// @tparam L Integer between 1 and 4 included that qualify the dimension of the vector + /// @tparam Q Value from qualifier enum + /// + /// @see <a href="http://www.opengl.org/sdk/docs/manglsl/xhtml/uintBitsToFloat.xml">GLSL uintBitsToFloat man page</a> + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 8.3 Common Functions</a> + template<length_t L, qualifier Q> + GLM_FUNC_DECL vec<L, float, Q> uintBitsToFloat(vec<L, uint, Q> const& v); + + /// Computes and returns a * b + c. + /// + /// @tparam genType Floating-point scalar or vector types. + /// + /// @see <a href="http://www.opengl.org/sdk/docs/manglsl/xhtml/fma.xml">GLSL fma man page</a> + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 8.3 Common Functions</a> + template<typename genType> + 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 <a href="http://www.opengl.org/sdk/docs/manglsl/xhtml/frexp.xml">GLSL frexp man page</a> + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 8.3 Common Functions</a> + template<typename genType> + GLM_FUNC_DECL genType frexp(genType x, int& exp); + + template<length_t L, typename T, qualifier Q> + GLM_FUNC_DECL vec<L, T, Q> frexp(vec<L, T, Q> const& v, vec<L, int, Q>& 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 <a href="http://www.opengl.org/sdk/docs/manglsl/xhtml/ldexp.xml">GLSL ldexp man page</a>; + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 8.3 Common Functions</a> + template<typename genType> + GLM_FUNC_DECL genType ldexp(genType const& x, int const& exp); + + template<length_t L, typename T, qualifier Q> + GLM_FUNC_DECL vec<L, T, Q> ldexp(vec<L, T, Q> const& v, vec<L, int, Q> 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 0000000000000000000000000000000000000000..b0cbe9ff02cf50fc8a2e298998efabe59a9b07ea --- /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 0000000000000000000000000000000000000000..a503c7c0d041a9df14c88e391fee1b26b615f2c7 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/detail/_fixes.hpp @@ -0,0 +1,27 @@ +#include <cmath> + +//! 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 0000000000000000000000000000000000000000..5a874a02221f1c5eaa0ed393d9f24aec3be898c5 --- /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<typename T> + GLM_FUNC_QUALIFIER T mod289(T const& x) + { + return x - floor(x * (static_cast<T>(1.0) / static_cast<T>(289.0))) * static_cast<T>(289.0); + } + + template<typename T> + GLM_FUNC_QUALIFIER T permute(T const& x) + { + return mod289(((x * static_cast<T>(34)) + static_cast<T>(1)) * x); + } + + template<typename T, qualifier Q> + GLM_FUNC_QUALIFIER vec<2, T, Q> permute(vec<2, T, Q> const& x) + { + return mod289(((x * static_cast<T>(34)) + static_cast<T>(1)) * x); + } + + template<typename T, qualifier Q> + GLM_FUNC_QUALIFIER vec<3, T, Q> permute(vec<3, T, Q> const& x) + { + return mod289(((x * static_cast<T>(34)) + static_cast<T>(1)) * x); + } + + template<typename T, qualifier Q> + GLM_FUNC_QUALIFIER vec<4, T, Q> permute(vec<4, T, Q> const& x) + { + return mod289(((x * static_cast<T>(34)) + static_cast<T>(1)) * x); + } + + template<typename T> + GLM_FUNC_QUALIFIER T taylorInvSqrt(T const& r) + { + return static_cast<T>(1.79284291400159) - static_cast<T>(0.85373472095314) * r; + } + + template<typename T, qualifier Q> + GLM_FUNC_QUALIFIER vec<2, T, Q> taylorInvSqrt(vec<2, T, Q> const& r) + { + return static_cast<T>(1.79284291400159) - static_cast<T>(0.85373472095314) * r; + } + + template<typename T, qualifier Q> + GLM_FUNC_QUALIFIER vec<3, T, Q> taylorInvSqrt(vec<3, T, Q> const& r) + { + return static_cast<T>(1.79284291400159) - static_cast<T>(0.85373472095314) * r; + } + + template<typename T, qualifier Q> + GLM_FUNC_QUALIFIER vec<4, T, Q> taylorInvSqrt(vec<4, T, Q> const& r) + { + return static_cast<T>(1.79284291400159) - static_cast<T>(0.85373472095314) * r; + } + + template<typename T, qualifier Q> + GLM_FUNC_QUALIFIER vec<2, T, Q> fade(vec<2, T, Q> const& t) + { + return (t * t * t) * (t * (t * static_cast<T>(6) - static_cast<T>(15)) + static_cast<T>(10)); + } + + template<typename T, qualifier Q> + GLM_FUNC_QUALIFIER vec<3, T, Q> fade(vec<3, T, Q> const& t) + { + return (t * t * t) * (t * (t * static_cast<T>(6) - static_cast<T>(15)) + static_cast<T>(10)); + } + + template<typename T, qualifier Q> + GLM_FUNC_QUALIFIER vec<4, T, Q> fade(vec<4, T, Q> const& t) + { + return (t * t * t) * (t * (t * static_cast<T>(6) - static_cast<T>(15)) + static_cast<T>(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 0000000000000000000000000000000000000000..87896ef4f6f25e5d336a74c98b8369adea378e80 --- /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<typename T, int N> + struct _swizzle_base0 + { + protected: + GLM_FUNC_QUALIFIER T& elem(size_t i){ return (reinterpret_cast<T*>(_buffer))[i]; } + GLM_FUNC_QUALIFIER T const& elem(size_t i) const{ return (reinterpret_cast<const T*>(_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<int N, typename T, qualifier Q, int E0, int E1, int E2, int E3, bool Aligned> + struct _swizzle_base1 : public _swizzle_base0<T, N> + { + }; + + template<typename T, qualifier Q, int E0, int E1, bool Aligned> + struct _swizzle_base1<2, T, Q, E0,E1,-1,-2, Aligned> : public _swizzle_base0<T, 2> + { + GLM_FUNC_QUALIFIER vec<2, T, Q> operator ()() const { return vec<2, T, Q>(this->elem(E0), this->elem(E1)); } + }; + + template<typename T, qualifier Q, int E0, int E1, int E2, bool Aligned> + struct _swizzle_base1<3, T, Q, E0,E1,E2,-1, Aligned> : public _swizzle_base0<T, 3> + { + GLM_FUNC_QUALIFIER vec<3, T, Q> operator ()() const { return vec<3, T, Q>(this->elem(E0), this->elem(E1), this->elem(E2)); } + }; + + template<typename T, qualifier Q, int E0, int E1, int E2, int E3, bool Aligned> + struct _swizzle_base1<4, T, Q, E0,E1,E2,E3, Aligned> : public _swizzle_base0<T, 4> + { + 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<int N, typename T, qualifier Q, int E0, int E1, int E2, int E3, int DUPLICATE_ELEMENTS> + struct _swizzle_base2 : public _swizzle_base1<N, T, Q, E0,E1,E2,E3, detail::is_aligned<Q>::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<N, T, Q> const& that) + { + _apply_op(that, op_equal()); + return *this; + } + + GLM_FUNC_QUALIFIER void operator -= (vec<N, T, Q> const& that) + { + _apply_op(that, op_minus()); + } + + GLM_FUNC_QUALIFIER void operator += (vec<N, T, Q> const& that) + { + _apply_op(that, op_plus()); + } + + GLM_FUNC_QUALIFIER void operator *= (vec<N, T, Q> const& that) + { + _apply_op(that, op_mul()); + } + + GLM_FUNC_QUALIFIER void operator /= (vec<N, T, Q> const& that) + { + _apply_op(that, op_div()); + } + + GLM_FUNC_QUALIFIER T& operator[](size_t i) + { + const int offset_dst[4] = { E0, E1, E2, E3 }; + return this->elem(offset_dst[i]); + } + GLM_FUNC_QUALIFIER T operator[](size_t i) const + { + const int offset_dst[4] = { E0, E1, E2, E3 }; + return this->elem(offset_dst[i]); + } + + protected: + template<typename U> + GLM_FUNC_QUALIFIER void _apply_op(vec<N, T, Q> 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<int N, typename T, qualifier Q, int E0, int E1, int E2, int E3> + struct _swizzle_base2<N, T, Q, E0,E1,E2,E3, 1> : public _swizzle_base1<N, T, Q, E0,E1,E2,E3, detail::is_aligned<Q>::value> + { + struct Stub {}; + + GLM_FUNC_QUALIFIER _swizzle_base2& operator= (Stub const&) { return *this; } + + GLM_FUNC_QUALIFIER T operator[] (size_t i) const + { + const int offset_dst[4] = { E0, E1, E2, E3 }; + return this->elem(offset_dst[i]); + } + }; + + template<int N, typename T, qualifier Q, int E0, int E1, int E2, int E3> + struct _swizzle : public _swizzle_base2<N, T, Q, E0, E1, E2, E3, (E0 == E1 || E0 == E2 || E0 == E3 || E1 == E2 || E1 == E3 || E2 == E3)> + { + typedef _swizzle_base2<N, T, Q, E0, E1, E2, E3, (E0 == E1 || E0 == E2 || E0 == E3 || E1 == E2 || E1 == E3 || E2 == E3)> base_type; + + using base_type::operator=; + + GLM_FUNC_QUALIFIER operator vec<N, T, Q> () const { return (*this)(); } + }; + +// +// To prevent the C++ syntax from getting entirely overwhelming, define some alias macros +// +#define GLM_SWIZZLE_TEMPLATE1 template<int N, typename T, qualifier Q, int E0, int E1, int E2, int E3> +#define GLM_SWIZZLE_TEMPLATE2 template<int N, typename T, qualifier Q, int E0, int E1, int E2, int E3, int F0, int F1, int F2, int F3> +#define GLM_SWIZZLE_TYPE1 _swizzle<N, T, Q, E0, E1, E2, E3> +#define GLM_SWIZZLE_TYPE2 _swizzle<N, T, Q, F0, F1, F2, F3> + +// +// 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<N, T, Q> operator OPERAND ( const GLM_SWIZZLE_TYPE1& a, const GLM_SWIZZLE_TYPE2& b) \ + { \ + return a() OPERAND b(); \ + } \ + GLM_SWIZZLE_TEMPLATE1 \ + GLM_FUNC_QUALIFIER vec<N, T, Q> operator OPERAND ( const GLM_SWIZZLE_TYPE1& a, const vec<N, T, Q>& b) \ + { \ + return a() OPERAND b; \ + } \ + GLM_SWIZZLE_TEMPLATE1 \ + GLM_FUNC_QUALIFIER vec<N, T, Q> operator OPERAND ( const vec<N, T, Q>& 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<N, T, Q> operator OPERAND ( const GLM_SWIZZLE_TYPE1& a, const T& b) \ + { \ + return a() OPERAND b; \ + } \ + GLM_SWIZZLE_TEMPLATE1 \ + GLM_FUNC_QUALIFIER vec<N, T, Q> 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 0000000000000000000000000000000000000000..d93c6afd5b79aeda66f5e96077503625519888fa --- /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) \ + 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) \ + 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) \ + 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<typename T> \ + vec<L, T, Q> vec<L, T, Q>::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<typename T> \ + vec<3, T, Q> vec<L, T, Q>::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<typename T> \ + vec<4, T, Q> vec<L, T, Q>::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 0000000000000000000000000000000000000000..1fcaec3152846e6796a48a35b2cf8ad810415820 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/detail/_vectorize.hpp @@ -0,0 +1,162 @@ +#pragma once + +namespace glm{ +namespace detail +{ + template<template<length_t L, typename T, qualifier Q> class vec, length_t L, typename R, typename T, qualifier Q> + struct functor1{}; + + template<template<length_t L, typename T, qualifier Q> class vec, typename R, typename T, qualifier Q> + struct functor1<vec, 1, R, T, Q> + { + 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<template<length_t L, typename T, qualifier Q> class vec, typename R, typename T, qualifier Q> + struct functor1<vec, 2, R, T, Q> + { + 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<template<length_t L, typename T, qualifier Q> class vec, typename R, typename T, qualifier Q> + struct functor1<vec, 3, R, T, Q> + { + 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<template<length_t L, typename T, qualifier Q> class vec, typename R, typename T, qualifier Q> + struct functor1<vec, 4, R, T, Q> + { + 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<template<length_t L, typename T, qualifier Q> class vec, length_t L, typename T, qualifier Q> + struct functor2{}; + + template<template<length_t L, typename T, qualifier Q> class vec, typename T, qualifier Q> + struct functor2<vec, 1, T, Q> + { + 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<template<length_t L, typename T, qualifier Q> class vec, typename T, qualifier Q> + struct functor2<vec, 2, T, Q> + { + 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<template<length_t L, typename T, qualifier Q> class vec, typename T, qualifier Q> + struct functor2<vec, 3, T, Q> + { + 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<template<length_t L, typename T, qualifier Q> class vec, typename T, qualifier Q> + struct functor2<vec, 4, T, Q> + { + 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<template<length_t L, typename T, qualifier Q> class vec, length_t L, typename T, qualifier Q> + struct functor2_vec_sca{}; + + template<template<length_t L, typename T, qualifier Q> class vec, typename T, qualifier Q> + struct functor2_vec_sca<vec, 1, T, Q> + { + 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<template<length_t L, typename T, qualifier Q> class vec, typename T, qualifier Q> + struct functor2_vec_sca<vec, 2, T, Q> + { + 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<template<length_t L, typename T, qualifier Q> class vec, typename T, qualifier Q> + struct functor2_vec_sca<vec, 3, T, Q> + { + 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<template<length_t L, typename T, qualifier Q> class vec, typename T, qualifier Q> + struct functor2_vec_sca<vec, 4, T, Q> + { + 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<length_t L, typename T, qualifier Q> + struct functor2_vec_int {}; + + template<typename T, qualifier Q> + 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<typename T, qualifier Q> + 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<typename T, qualifier Q> + 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<typename T, qualifier Q> + 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 0000000000000000000000000000000000000000..cc24b9e62f50cd2fe6d54c2b82335c76fd70bac8 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/detail/compute_common.hpp @@ -0,0 +1,50 @@ +#pragma once + +#include "setup.hpp" +#include <limits> + +namespace glm{ +namespace detail +{ + template<typename genFIType, bool /*signed*/> + struct compute_abs + {}; + + template<typename genFIType> + struct compute_abs<genFIType, true> + { + GLM_FUNC_QUALIFIER GLM_CONSTEXPR static genFIType call(genFIType x) + { + GLM_STATIC_ASSERT( + std::numeric_limits<genFIType>::is_iec559 || std::numeric_limits<genFIType>::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 + template<> + struct compute_abs<float, true> + { + GLM_FUNC_QUALIFIER GLM_CONSTEXPR static float call(float x) + { + return fabsf(x); + } + }; +#endif + + template<typename genFIType> + struct compute_abs<genFIType, false> + { + GLM_FUNC_QUALIFIER GLM_CONSTEXPR static genFIType call(genFIType x) + { + GLM_STATIC_ASSERT( + (!std::numeric_limits<genFIType>::is_signed && std::numeric_limits<genFIType>::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_relational.hpp b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/detail/compute_vector_relational.hpp new file mode 100644 index 0000000000000000000000000000000000000000..167b6345dd398e3822c772a113dab5864470f64e --- /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 <limits> + +namespace glm{ +namespace detail +{ + template <typename T, bool isFloat> + struct compute_equal + { + GLM_FUNC_QUALIFIER GLM_CONSTEXPR static bool call(T a, T b) + { + return a == b; + } + }; +/* + template <typename T> + struct compute_equal<T, true> + { + GLM_FUNC_QUALIFIER GLM_CONSTEXPR static bool call(T a, T b) + { + return detail::compute_abs<T, std::numeric_limits<T>::is_signed>::call(b - a) <= static_cast<T>(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 0000000000000000000000000000000000000000..4b5f14410ff6d6bb92e1a4baa83c199e54fd5e76 --- /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 <limits> + +namespace glm +{ + // min + template<typename genType> + GLM_FUNC_QUALIFIER GLM_CONSTEXPR genType min(genType x, genType y) + { + GLM_STATIC_ASSERT(std::numeric_limits<genType>::is_iec559 || std::numeric_limits<genType>::is_integer, "'min' only accept floating-point or integer inputs"); + return (y < x) ? y : x; + } + + // max + template<typename genType> + GLM_FUNC_QUALIFIER GLM_CONSTEXPR genType max(genType x, genType y) + { + GLM_STATIC_ASSERT(std::numeric_limits<genType>::is_iec559 || std::numeric_limits<genType>::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<typename genType> + GLM_FUNC_QUALIFIER genType round(genType x) + { + GLM_STATIC_ASSERT(std::numeric_limits<genType>::is_iec559, "'round' only accept floating-point inputs"); + + return x < static_cast<genType>(0) ? static_cast<genType>(int(x - static_cast<genType>(0.5))) : static_cast<genType>(int(x + static_cast<genType>(0.5))); + } +# endif + + // trunc +# if GLM_HAS_CXX11_STL + using ::std::trunc; +# else + template<typename genType> + GLM_FUNC_QUALIFIER genType trunc(genType x) + { + GLM_STATIC_ASSERT(std::numeric_limits<genType>::is_iec559, "'trunc' only accept floating-point inputs"); + + return x < static_cast<genType>(0) ? -std::floor(-x) : std::floor(x); + } +# endif + +}//namespace glm + +namespace glm{ +namespace detail +{ + template<length_t L, typename T, qualifier Q, bool Aligned> + struct compute_abs_vector + { + GLM_FUNC_QUALIFIER GLM_CONSTEXPR static vec<L, T, Q> call(vec<L, T, Q> const& x) + { + return detail::functor1<vec, L, T, T, Q>::call(abs, x); + } + }; + + template<length_t L, typename T, typename U, qualifier Q, bool Aligned> + struct compute_mix_vector + { + GLM_FUNC_QUALIFIER static vec<L, T, Q> call(vec<L, T, Q> const& x, vec<L, T, Q> const& y, vec<L, U, Q> const& a) + { + GLM_STATIC_ASSERT(std::numeric_limits<U>::is_iec559 || GLM_CONFIG_UNRESTRICTED_GENTYPE, "'mix' only accept floating-point inputs for the interpolator a"); + + return vec<L, T, Q>(vec<L, U, Q>(x) * (static_cast<U>(1) - a) + vec<L, U, Q>(y) * a); + } + }; + + template<length_t L, typename T, qualifier Q, bool Aligned> + struct compute_mix_vector<L, T, bool, Q, Aligned> + { + GLM_FUNC_QUALIFIER static vec<L, T, Q> call(vec<L, T, Q> const& x, vec<L, T, Q> const& y, vec<L, bool, Q> const& a) + { + vec<L, T, Q> Result; + for(length_t i = 0; i < x.length(); ++i) + Result[i] = a[i] ? y[i] : x[i]; + return Result; + } + }; + + template<length_t L, typename T, typename U, qualifier Q, bool Aligned> + struct compute_mix_scalar + { + GLM_FUNC_QUALIFIER static vec<L, T, Q> call(vec<L, T, Q> const& x, vec<L, T, Q> const& y, U const& a) + { + GLM_STATIC_ASSERT(std::numeric_limits<U>::is_iec559 || GLM_CONFIG_UNRESTRICTED_GENTYPE, "'mix' only accept floating-point inputs for the interpolator a"); + + return vec<L, T, Q>(vec<L, U, Q>(x) * (static_cast<U>(1) - a) + vec<L, U, Q>(y) * a); + } + }; + + template<length_t L, typename T, qualifier Q, bool Aligned> + struct compute_mix_scalar<L, T, bool, Q, Aligned> + { + GLM_FUNC_QUALIFIER static vec<L, T, Q> call(vec<L, T, Q> const& x, vec<L, T, Q> const& y, bool const& a) + { + return a ? y : x; + } + }; + + template<typename T, typename U> + struct compute_mix + { + GLM_FUNC_QUALIFIER static T call(T const& x, T const& y, U const& a) + { + GLM_STATIC_ASSERT(std::numeric_limits<U>::is_iec559 || GLM_CONFIG_UNRESTRICTED_GENTYPE, "'mix' only accept floating-point inputs for the interpolator a"); + + return static_cast<T>(static_cast<U>(x) * (static_cast<U>(1) - a) + static_cast<U>(y) * a); + } + }; + + template<typename T> + struct compute_mix<T, bool> + { + GLM_FUNC_QUALIFIER static T call(T const& x, T const& y, bool const& a) + { + return a ? y : x; + } + }; + + template<length_t L, typename T, qualifier Q, bool isFloat, bool Aligned> + struct compute_sign + { + GLM_FUNC_QUALIFIER static vec<L, T, Q> call(vec<L, T, Q> const& x) + { + return vec<L, T, Q>(glm::lessThan(vec<L, T, Q>(0), x)) - vec<L, T, Q>(glm::lessThan(x, vec<L, T, Q>(0))); + } + }; + +# if GLM_ARCH == GLM_ARCH_X86 + template<length_t L, typename T, qualifier Q, bool Aligned> + struct compute_sign<L, T, Q, false, Aligned> + { + GLM_FUNC_QUALIFIER static vec<L, T, Q> call(vec<L, T, Q> const& x) + { + T const Shift(static_cast<T>(sizeof(T) * 8 - 1)); + vec<L, T, Q> const y(vec<L, typename detail::make_unsigned<T>::type, Q>(-x) >> typename detail::make_unsigned<T>::type(Shift)); + + return (x >> Shift) | y; + } + }; +# endif + + template<length_t L, typename T, qualifier Q, bool Aligned> + struct compute_floor + { + GLM_FUNC_QUALIFIER static vec<L, T, Q> call(vec<L, T, Q> const& x) + { + return detail::functor1<vec, L, T, T, Q>::call(std::floor, x); + } + }; + + template<length_t L, typename T, qualifier Q, bool Aligned> + struct compute_ceil + { + GLM_FUNC_QUALIFIER static vec<L, T, Q> call(vec<L, T, Q> const& x) + { + return detail::functor1<vec, L, T, T, Q>::call(std::ceil, x); + } + }; + + template<length_t L, typename T, qualifier Q, bool Aligned> + struct compute_fract + { + GLM_FUNC_QUALIFIER static vec<L, T, Q> call(vec<L, T, Q> const& x) + { + return x - floor(x); + } + }; + + template<length_t L, typename T, qualifier Q, bool Aligned> + struct compute_trunc + { + GLM_FUNC_QUALIFIER static vec<L, T, Q> call(vec<L, T, Q> const& x) + { + return detail::functor1<vec, L, T, T, Q>::call(trunc, x); + } + }; + + template<length_t L, typename T, qualifier Q, bool Aligned> + struct compute_round + { + GLM_FUNC_QUALIFIER static vec<L, T, Q> call(vec<L, T, Q> const& x) + { + return detail::functor1<vec, L, T, T, Q>::call(round, x); + } + }; + + template<length_t L, typename T, qualifier Q, bool Aligned> + struct compute_mod + { + GLM_FUNC_QUALIFIER static vec<L, T, Q> call(vec<L, T, Q> const& a, vec<L, T, Q> const& b) + { + GLM_STATIC_ASSERT(std::numeric_limits<T>::is_iec559, "'mod' only accept floating-point inputs. Include <glm/gtc/integer.hpp> for integer inputs."); + return a - b * floor(a / b); + } + }; + + template<length_t L, typename T, qualifier Q, bool Aligned> + struct compute_min_vector + { + GLM_FUNC_QUALIFIER static vec<L, T, Q> call(vec<L, T, Q> const& x, vec<L, T, Q> const& y) + { + return detail::functor2<vec, L, T, Q>::call(min, x, y); + } + }; + + template<length_t L, typename T, qualifier Q, bool Aligned> + struct compute_max_vector + { + GLM_FUNC_QUALIFIER static vec<L, T, Q> call(vec<L, T, Q> const& x, vec<L, T, Q> const& y) + { + return detail::functor2<vec, L, T, Q>::call(max, x, y); + } + }; + + template<length_t L, typename T, qualifier Q, bool Aligned> + struct compute_clamp_vector + { + GLM_FUNC_QUALIFIER static vec<L, T, Q> call(vec<L, T, Q> const& x, vec<L, T, Q> const& minVal, vec<L, T, Q> const& maxVal) + { + return min(max(x, minVal), maxVal); + } + }; + + template<length_t L, typename T, qualifier Q, bool Aligned> + struct compute_step_vector + { + GLM_FUNC_QUALIFIER static vec<L, T, Q> call(vec<L, T, Q> const& edge, vec<L, T, Q> const& x) + { + return mix(vec<L, T, Q>(1), vec<L, T, Q>(0), glm::lessThan(x, edge)); + } + }; + + template<length_t L, typename T, qualifier Q, bool Aligned> + struct compute_smoothstep_vector + { + GLM_FUNC_QUALIFIER static vec<L, T, Q> call(vec<L, T, Q> const& edge0, vec<L, T, Q> const& edge1, vec<L, T, Q> const& x) + { + GLM_STATIC_ASSERT(std::numeric_limits<T>::is_iec559 || GLM_CONFIG_UNRESTRICTED_GENTYPE, "'smoothstep' only accept floating-point inputs"); + vec<L, T, Q> const tmp(clamp((x - edge0) / (edge1 - edge0), static_cast<T>(0), static_cast<T>(1))); + return tmp * tmp * (static_cast<T>(3) - static_cast<T>(2) * tmp); + } + }; +}//namespace detail + + template<typename genFIType> + GLM_FUNC_QUALIFIER GLM_CONSTEXPR genFIType abs(genFIType x) + { + return detail::compute_abs<genFIType, std::numeric_limits<genFIType>::is_signed>::call(x); + } + + template<length_t L, typename T, qualifier Q> + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<L, T, Q> abs(vec<L, T, Q> const& x) + { + return detail::compute_abs_vector<L, T, Q, detail::is_aligned<Q>::value>::call(x); + } + + // sign + // fast and works for any type + template<typename genFIType> + GLM_FUNC_QUALIFIER genFIType sign(genFIType x) + { + GLM_STATIC_ASSERT( + std::numeric_limits<genFIType>::is_iec559 || (std::numeric_limits<genFIType>::is_signed && std::numeric_limits<genFIType>::is_integer), + "'sign' only accept signed inputs"); + + return detail::compute_sign<1, genFIType, defaultp, + std::numeric_limits<genFIType>::is_iec559, detail::is_aligned<highp>::value>::call(vec<1, genFIType>(x)).x; + } + + template<length_t L, typename T, qualifier Q> + GLM_FUNC_QUALIFIER vec<L, T, Q> sign(vec<L, T, Q> const& x) + { + GLM_STATIC_ASSERT( + std::numeric_limits<T>::is_iec559 || (std::numeric_limits<T>::is_signed && std::numeric_limits<T>::is_integer), + "'sign' only accept signed inputs"); + + return detail::compute_sign<L, T, Q, std::numeric_limits<T>::is_iec559, detail::is_aligned<Q>::value>::call(x); + } + + // floor + using ::std::floor; + template<length_t L, typename T, qualifier Q> + GLM_FUNC_QUALIFIER vec<L, T, Q> floor(vec<L, T, Q> const& x) + { + GLM_STATIC_ASSERT(std::numeric_limits<T>::is_iec559, "'floor' only accept floating-point inputs."); + return detail::compute_floor<L, T, Q, detail::is_aligned<Q>::value>::call(x); + } + + template<length_t L, typename T, qualifier Q> + GLM_FUNC_QUALIFIER vec<L, T, Q> trunc(vec<L, T, Q> const& x) + { + GLM_STATIC_ASSERT(std::numeric_limits<T>::is_iec559, "'trunc' only accept floating-point inputs"); + return detail::compute_trunc<L, T, Q, detail::is_aligned<Q>::value>::call(x); + } + + template<length_t L, typename T, qualifier Q> + GLM_FUNC_QUALIFIER vec<L, T, Q> round(vec<L, T, Q> const& x) + { + GLM_STATIC_ASSERT(std::numeric_limits<T>::is_iec559, "'round' only accept floating-point inputs"); + return detail::compute_round<L, T, Q, detail::is_aligned<Q>::value>::call(x); + } + +/* + // roundEven + template<typename genType> + GLM_FUNC_QUALIFIER genType roundEven(genType const& x) + { + GLM_STATIC_ASSERT(std::numeric_limits<genType>::is_iec559, "'roundEven' only accept floating-point inputs"); + + return genType(int(x + genType(int(x) % 2))); + } +*/ + + // roundEven + template<typename genType> + GLM_FUNC_QUALIFIER genType roundEven(genType x) + { + GLM_STATIC_ASSERT(std::numeric_limits<genType>::is_iec559, "'roundEven' only accept floating-point inputs"); + + int Integer = static_cast<int>(x); + genType IntegerPart = static_cast<genType>(Integer); + genType FractionalPart = fract(x); + + if(FractionalPart > static_cast<genType>(0.5) || FractionalPart < static_cast<genType>(0.5)) + { + return round(x); + } + else if((Integer % 2) == 0) + { + return IntegerPart; + } + else if(x <= static_cast<genType>(0)) // Work around... + { + return IntegerPart - static_cast<genType>(1); + } + else + { + return IntegerPart + static_cast<genType>(1); + } + //else // Bug on MinGW 4.5.2 + //{ + // return mix(IntegerPart + genType(-1), IntegerPart + genType(1), x <= genType(0)); + //} + } + + template<length_t L, typename T, qualifier Q> + GLM_FUNC_QUALIFIER vec<L, T, Q> roundEven(vec<L, T, Q> const& x) + { + GLM_STATIC_ASSERT(std::numeric_limits<T>::is_iec559, "'roundEven' only accept floating-point inputs"); + return detail::functor1<vec, L, T, T, Q>::call(roundEven, x); + } + + // ceil + using ::std::ceil; + template<length_t L, typename T, qualifier Q> + GLM_FUNC_QUALIFIER vec<L, T, Q> ceil(vec<L, T, Q> const& x) + { + GLM_STATIC_ASSERT(std::numeric_limits<T>::is_iec559, "'ceil' only accept floating-point inputs"); + return detail::compute_ceil<L, T, Q, detail::is_aligned<Q>::value>::call(x); + } + + // fract + template<typename genType> + GLM_FUNC_QUALIFIER genType fract(genType x) + { + return fract(vec<1, genType>(x)).x; + } + + template<length_t L, typename T, qualifier Q> + GLM_FUNC_QUALIFIER vec<L, T, Q> fract(vec<L, T, Q> const& x) + { + GLM_STATIC_ASSERT(std::numeric_limits<T>::is_iec559, "'fract' only accept floating-point inputs"); + return detail::compute_fract<L, T, Q, detail::is_aligned<Q>::value>::call(x); + } + + // mod + template<typename genType> + GLM_FUNC_QUALIFIER genType mod(genType x, genType y) + { +# if GLM_COMPILER & GLM_COMPILER_CUDA + // 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<length_t L, typename T, qualifier Q> + GLM_FUNC_QUALIFIER vec<L, T, Q> mod(vec<L, T, Q> const& x, T y) + { + return detail::compute_mod<L, T, Q, detail::is_aligned<Q>::value>::call(x, vec<L, T, Q>(y)); + } + + template<length_t L, typename T, qualifier Q> + GLM_FUNC_QUALIFIER vec<L, T, Q> mod(vec<L, T, Q> const& x, vec<L, T, Q> const& y) + { + return detail::compute_mod<L, T, Q, detail::is_aligned<Q>::value>::call(x, y); + } + + // modf + template<typename genType> + GLM_FUNC_QUALIFIER genType modf(genType x, genType & i) + { + GLM_STATIC_ASSERT(std::numeric_limits<genType>::is_iec559, "'modf' only accept floating-point inputs"); + return std::modf(x, &i); + } + + template<typename T, qualifier Q> + 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<typename T, qualifier Q> + 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<typename T, qualifier Q> + 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<typename T, qualifier Q> + 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<length_t L, typename T, qualifier Q> + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<L, T, Q> min(vec<L, T, Q> const& a, T b) + { + GLM_STATIC_ASSERT(std::numeric_limits<T>::is_iec559 || std::numeric_limits<T>::is_integer, "'min' only accept floating-point or integer inputs"); + return detail::compute_min_vector<L, T, Q, detail::is_aligned<Q>::value>::call(a, vec<L, T, Q>(b)); + } + + template<length_t L, typename T, qualifier Q> + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<L, T, Q> min(vec<L, T, Q> const& a, vec<L, T, Q> const& b) + { + return detail::compute_min_vector<L, T, Q, detail::is_aligned<Q>::value>::call(a, b); + } + + // max + template<length_t L, typename T, qualifier Q> + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<L, T, Q> max(vec<L, T, Q> const& a, T b) + { + GLM_STATIC_ASSERT(std::numeric_limits<T>::is_iec559 || std::numeric_limits<T>::is_integer, "'max' only accept floating-point or integer inputs"); + return detail::compute_max_vector<L, T, Q, detail::is_aligned<Q>::value>::call(a, vec<L, T, Q>(b)); + } + + template<length_t L, typename T, qualifier Q> + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<L, T, Q> max(vec<L, T, Q> const& a, vec<L, T, Q> const& b) + { + return detail::compute_max_vector<L, T, Q, detail::is_aligned<Q>::value>::call(a, b); + } + + // clamp + template<typename genType> + GLM_FUNC_QUALIFIER GLM_CONSTEXPR genType clamp(genType x, genType minVal, genType maxVal) + { + GLM_STATIC_ASSERT(std::numeric_limits<genType>::is_iec559 || std::numeric_limits<genType>::is_integer, "'clamp' only accept floating-point or integer inputs"); + return min(max(x, minVal), maxVal); + } + + template<length_t L, typename T, qualifier Q> + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<L, T, Q> clamp(vec<L, T, Q> const& x, T minVal, T maxVal) + { + GLM_STATIC_ASSERT(std::numeric_limits<T>::is_iec559 || std::numeric_limits<T>::is_integer, "'clamp' only accept floating-point or integer inputs"); + return detail::compute_clamp_vector<L, T, Q, detail::is_aligned<Q>::value>::call(x, vec<L, T, Q>(minVal), vec<L, T, Q>(maxVal)); + } + + template<length_t L, typename T, qualifier Q> + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<L, T, Q> clamp(vec<L, T, Q> const& x, vec<L, T, Q> const& minVal, vec<L, T, Q> const& maxVal) + { + GLM_STATIC_ASSERT(std::numeric_limits<T>::is_iec559 || std::numeric_limits<T>::is_integer, "'clamp' only accept floating-point or integer inputs"); + return detail::compute_clamp_vector<L, T, Q, detail::is_aligned<Q>::value>::call(x, minVal, maxVal); + } + + template<typename genTypeT, typename genTypeU> + GLM_FUNC_QUALIFIER genTypeT mix(genTypeT x, genTypeT y, genTypeU a) + { + return detail::compute_mix<genTypeT, genTypeU>::call(x, y, a); + } + + template<length_t L, typename T, typename U, qualifier Q> + GLM_FUNC_QUALIFIER vec<L, T, Q> mix(vec<L, T, Q> const& x, vec<L, T, Q> const& y, U a) + { + return detail::compute_mix_scalar<L, T, U, Q, detail::is_aligned<Q>::value>::call(x, y, a); + } + + template<length_t L, typename T, typename U, qualifier Q> + GLM_FUNC_QUALIFIER vec<L, T, Q> mix(vec<L, T, Q> const& x, vec<L, T, Q> const& y, vec<L, U, Q> const& a) + { + return detail::compute_mix_vector<L, T, U, Q, detail::is_aligned<Q>::value>::call(x, y, a); + } + + // step + template<typename genType> + GLM_FUNC_QUALIFIER genType step(genType edge, genType x) + { + return mix(static_cast<genType>(1), static_cast<genType>(0), x < edge); + } + + template<length_t L, typename T, qualifier Q> + GLM_FUNC_QUALIFIER vec<L, T, Q> step(T edge, vec<L, T, Q> const& x) + { + return detail::compute_step_vector<L, T, Q, detail::is_aligned<Q>::value>::call(vec<L, T, Q>(edge), x); + } + + template<length_t L, typename T, qualifier Q> + GLM_FUNC_QUALIFIER vec<L, T, Q> step(vec<L, T, Q> const& edge, vec<L, T, Q> const& x) + { + return detail::compute_step_vector<L, T, Q, detail::is_aligned<Q>::value>::call(edge, x); + } + + // smoothstep + template<typename genType> + GLM_FUNC_QUALIFIER genType smoothstep(genType edge0, genType edge1, genType x) + { + GLM_STATIC_ASSERT(std::numeric_limits<genType>::is_iec559 || 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<length_t L, typename T, qualifier Q> + GLM_FUNC_QUALIFIER vec<L, T, Q> smoothstep(T edge0, T edge1, vec<L, T, Q> const& x) + { + return detail::compute_smoothstep_vector<L, T, Q, detail::is_aligned<Q>::value>::call(vec<L, T, Q>(edge0), vec<L, T, Q>(edge1), x); + } + + template<length_t L, typename T, qualifier Q> + GLM_FUNC_QUALIFIER vec<L, T, Q> smoothstep(vec<L, T, Q> const& edge0, vec<L, T, Q> const& edge1, vec<L, T, Q> const& x) + { + return detail::compute_smoothstep_vector<L, T, Q, detail::is_aligned<Q>::value>::call(edge0, edge1, x); + } + +# if GLM_HAS_CXX11_STL + using std::isnan; +# else + template<typename genType> + GLM_FUNC_QUALIFIER bool isnan(genType x) + { + GLM_STATIC_ASSERT(std::numeric_limits<genType>::is_iec559, "'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 + return ::isnan(x) != 0; +# else + return std::isnan(x); +# endif + } +# endif + + template<length_t L, typename T, qualifier Q> + GLM_FUNC_QUALIFIER vec<L, bool, Q> isnan(vec<L, T, Q> const& v) + { + GLM_STATIC_ASSERT(std::numeric_limits<T>::is_iec559, "'isnan' only accept floating-point inputs"); + + vec<L, bool, Q> Result; + 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<typename genType> + GLM_FUNC_QUALIFIER bool isinf(genType x) + { + GLM_STATIC_ASSERT(std::numeric_limits<genType>::is_iec559, "'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 + // 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<length_t L, typename T, qualifier Q> + GLM_FUNC_QUALIFIER vec<L, bool, Q> isinf(vec<L, T, Q> const& v) + { + GLM_STATIC_ASSERT(std::numeric_limits<T>::is_iec559, "'isinf' only accept floating-point inputs"); + + vec<L, bool, Q> Result; + for (length_t l = 0; l < v.length(); ++l) + Result[l] = glm::isinf(v[l]); + return Result; + } + + GLM_FUNC_QUALIFIER int floatBitsToInt(float const& v) + { + union + { + float in; + int out; + } u; + + u.in = v; + + return u.out; + } + + template<length_t L, qualifier Q> + GLM_FUNC_QUALIFIER vec<L, int, Q> floatBitsToInt(vec<L, float, Q> const& v) + { + return reinterpret_cast<vec<L, int, Q>&>(const_cast<vec<L, float, Q>&>(v)); + } + + GLM_FUNC_QUALIFIER uint floatBitsToUint(float const& v) + { + union + { + float in; + uint out; + } u; + + u.in = v; + + return u.out; + } + + template<length_t L, qualifier Q> + GLM_FUNC_QUALIFIER vec<L, uint, Q> floatBitsToUint(vec<L, float, Q> const& v) + { + return reinterpret_cast<vec<L, uint, Q>&>(const_cast<vec<L, float, Q>&>(v)); + } + + GLM_FUNC_QUALIFIER float intBitsToFloat(int const& v) + { + union + { + int in; + float out; + } u; + + u.in = v; + + return u.out; + } + + template<length_t L, qualifier Q> + GLM_FUNC_QUALIFIER vec<L, float, Q> intBitsToFloat(vec<L, int, Q> const& v) + { + return reinterpret_cast<vec<L, float, Q>&>(const_cast<vec<L, int, Q>&>(v)); + } + + GLM_FUNC_QUALIFIER float uintBitsToFloat(uint const& v) + { + union + { + uint in; + float out; + } u; + + u.in = v; + + return u.out; + } + + template<length_t L, qualifier Q> + GLM_FUNC_QUALIFIER vec<L, float, Q> uintBitsToFloat(vec<L, uint, Q> const& v) + { + return reinterpret_cast<vec<L, float, Q>&>(const_cast<vec<L, uint, Q>&>(v)); + } + +# if GLM_HAS_CXX11_STL + using std::fma; +# else + template<typename genType> + GLM_FUNC_QUALIFIER genType fma(genType const& a, genType const& b, genType const& c) + { + return a * b + c; + } +# endif + + template<typename genType> + GLM_FUNC_QUALIFIER genType frexp(genType x, int& exp) + { + GLM_STATIC_ASSERT(std::numeric_limits<genType>::is_iec559, "'frexp' only accept floating-point inputs"); + + return std::frexp(x, &exp); + } + + template<length_t L, typename T, qualifier Q> + GLM_FUNC_QUALIFIER vec<L, T, Q> frexp(vec<L, T, Q> const& v, vec<L, int, Q>& exp) + { + GLM_STATIC_ASSERT(std::numeric_limits<T>::is_iec559, "'frexp' only accept floating-point inputs"); + + vec<L, T, Q> Result; + for (length_t l = 0; l < v.length(); ++l) + Result[l] = std::frexp(v[l], &exp[l]); + return Result; + } + + template<typename genType> + GLM_FUNC_QUALIFIER genType ldexp(genType const& x, int const& exp) + { + GLM_STATIC_ASSERT(std::numeric_limits<genType>::is_iec559, "'ldexp' only accept floating-point inputs"); + + return std::ldexp(x, exp); + } + + template<length_t L, typename T, qualifier Q> + GLM_FUNC_QUALIFIER vec<L, T, Q> ldexp(vec<L, T, Q> const& v, vec<L, int, Q> const& exp) + { + GLM_STATIC_ASSERT(std::numeric_limits<T>::is_iec559, "'ldexp' only accept floating-point inputs"); + + vec<L, T, Q> Result; + 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 0000000000000000000000000000000000000000..ce0032d33fefbf095f9d5eb38ba56c88d11dc3a7 --- /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 <immintrin.h> + +namespace glm{ +namespace detail +{ + template<qualifier Q> + 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<qualifier Q> + 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<qualifier Q> + 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<qualifier Q> + 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<qualifier Q> + 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<qualifier Q> + 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<qualifier Q> + 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<qualifier Q> + 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<qualifier Q> + 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<qualifier Q> + 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<qualifier Q> + 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<qualifier Q> + 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<qualifier Q> + 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<qualifier Q> + 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<qualifier Q> + 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<qualifier Q> + 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<qualifier Q> + 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<int>(a.w), -static_cast<int>(a.z), -static_cast<int>(a.y), -static_cast<int>(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<qualifier Q> + struct compute_step_vector<float, Q, tvec4> + { + 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<qualifier Q> + 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 0000000000000000000000000000000000000000..2040d41f8a3dfe17cc129601e0d25b7ba56a2e55 --- /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 <limits> +#include <cmath> +#include <cassert> + +namespace glm{ +namespace detail +{ +# if GLM_HAS_CXX11_STL + using std::log2; +# else + template<typename genType> + genType log2(genType Value) + { + return std::log(Value) * static_cast<genType>(1.4426950408889634073599246810019); + } +# endif + + template<length_t L, typename T, qualifier Q, bool isFloat, bool Aligned> + struct compute_log2 + { + GLM_FUNC_QUALIFIER static vec<L, T, Q> call(vec<L, T, Q> const& v) + { + GLM_STATIC_ASSERT(std::numeric_limits<T>::is_iec559, "'log2' only accept floating-point inputs. Include <glm/gtc/integer.hpp> for integer inputs."); + + return detail::functor1<vec, L, T, T, Q>::call(log2, v); + } + }; + + template<length_t L, typename T, qualifier Q, bool Aligned> + struct compute_sqrt + { + GLM_FUNC_QUALIFIER static vec<L, T, Q> call(vec<L, T, Q> const& x) + { + return detail::functor1<vec, L, T, T, Q>::call(std::sqrt, x); + } + }; + + template<length_t L, typename T, qualifier Q, bool Aligned> + struct compute_inversesqrt + { + GLM_FUNC_QUALIFIER static vec<L, T, Q> call(vec<L, T, Q> const& x) + { + return static_cast<T>(1) / sqrt(x); + } + }; + + template<length_t L, bool Aligned> + struct compute_inversesqrt<L, float, lowp, Aligned> + { + GLM_FUNC_QUALIFIER static vec<L, float, lowp> call(vec<L, float, lowp> const& x) + { + vec<L, float, lowp> tmp(x); + vec<L, float, lowp> xhalf(tmp * 0.5f); + vec<L, uint, lowp>* p = reinterpret_cast<vec<L, uint, lowp>*>(const_cast<vec<L, float, lowp>*>(&x)); + vec<L, uint, lowp> i = vec<L, uint, lowp>(0x5f375a86) - (*p >> vec<L, uint, lowp>(1)); + vec<L, float, lowp>* ptmp = reinterpret_cast<vec<L, float, lowp>*>(&i); + tmp = *ptmp; + tmp = tmp * (1.5f - xhalf * tmp * tmp); + return tmp; + } + }; +}//namespace detail + + // pow + using std::pow; + template<length_t L, typename T, qualifier Q> + GLM_FUNC_QUALIFIER vec<L, T, Q> pow(vec<L, T, Q> const& base, vec<L, T, Q> const& exponent) + { + return detail::functor2<vec, L, T, Q>::call(pow, base, exponent); + } + + // exp + using std::exp; + template<length_t L, typename T, qualifier Q> + GLM_FUNC_QUALIFIER vec<L, T, Q> exp(vec<L, T, Q> const& x) + { + return detail::functor1<vec, L, T, T, Q>::call(exp, x); + } + + // log + using std::log; + template<length_t L, typename T, qualifier Q> + GLM_FUNC_QUALIFIER vec<L, T, Q> log(vec<L, T, Q> const& x) + { + return detail::functor1<vec, L, T, T, Q>::call(log, x); + } + +# if GLM_HAS_CXX11_STL + using std::exp2; +# else + //exp2, ln2 = 0.69314718055994530941723212145818f + template<typename genType> + GLM_FUNC_QUALIFIER genType exp2(genType x) + { + GLM_STATIC_ASSERT(std::numeric_limits<genType>::is_iec559, "'exp2' only accept floating-point inputs"); + + return std::exp(static_cast<genType>(0.69314718055994530941723212145818) * x); + } +# endif + + template<length_t L, typename T, qualifier Q> + GLM_FUNC_QUALIFIER vec<L, T, Q> exp2(vec<L, T, Q> const& x) + { + return detail::functor1<vec, L, T, T, Q>::call(exp2, x); + } + + // log2, ln2 = 0.69314718055994530941723212145818f + template<typename genType> + GLM_FUNC_QUALIFIER genType log2(genType x) + { + return log2(vec<1, genType>(x)).x; + } + + template<length_t L, typename T, qualifier Q> + GLM_FUNC_QUALIFIER vec<L, T, Q> log2(vec<L, T, Q> const& x) + { + return detail::compute_log2<L, T, Q, std::numeric_limits<T>::is_iec559, detail::is_aligned<Q>::value>::call(x); + } + + // sqrt + using std::sqrt; + template<length_t L, typename T, qualifier Q> + GLM_FUNC_QUALIFIER vec<L, T, Q> sqrt(vec<L, T, Q> const& x) + { + GLM_STATIC_ASSERT(std::numeric_limits<T>::is_iec559, "'sqrt' only accept floating-point inputs"); + return detail::compute_sqrt<L, T, Q, detail::is_aligned<Q>::value>::call(x); + } + + // inversesqrt + template<typename genType> + GLM_FUNC_QUALIFIER genType inversesqrt(genType x) + { + return static_cast<genType>(1) / sqrt(x); + } + + template<length_t L, typename T, qualifier Q> + GLM_FUNC_QUALIFIER vec<L, T, Q> inversesqrt(vec<L, T, Q> const& x) + { + GLM_STATIC_ASSERT(std::numeric_limits<T>::is_iec559, "'inversesqrt' only accept floating-point inputs"); + return detail::compute_inversesqrt<L, T, Q, detail::is_aligned<Q>::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 0000000000000000000000000000000000000000..fb78951727f1c5e419418fbac9394322f579f1c4 --- /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<qualifier Q> + 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 0000000000000000000000000000000000000000..9cde28fed189636790ed32b285357442cb5ddf9a --- /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<length_t L, typename T, qualifier Q, bool Aligned> + struct compute_length + { + GLM_FUNC_QUALIFIER static T call(vec<L, T, Q> const& v) + { + return sqrt(dot(v, v)); + } + }; + + template<length_t L, typename T, qualifier Q, bool Aligned> + struct compute_distance + { + GLM_FUNC_QUALIFIER static T call(vec<L, T, Q> const& p0, vec<L, T, Q> const& p1) + { + return length(p1 - p0); + } + }; + + template<typename V, typename T, bool Aligned> + struct compute_dot{}; + + template<typename T, qualifier Q, bool Aligned> + struct compute_dot<vec<1, T, Q>, T, Aligned> + { + GLM_FUNC_QUALIFIER static T call(vec<1, T, Q> const& a, vec<1, T, Q> const& b) + { + return a.x * b.x; + } + }; + + template<typename T, qualifier Q, bool Aligned> + struct compute_dot<vec<2, T, Q>, T, Aligned> + { + GLM_FUNC_QUALIFIER 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<typename T, qualifier Q, bool Aligned> + struct compute_dot<vec<3, T, Q>, T, Aligned> + { + GLM_FUNC_QUALIFIER 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<typename T, qualifier Q, bool Aligned> + struct compute_dot<vec<4, T, Q>, T, Aligned> + { + GLM_FUNC_QUALIFIER 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<typename T, qualifier Q, bool Aligned> + struct compute_cross + { + GLM_FUNC_QUALIFIER static vec<3, T, Q> call(vec<3, T, Q> const& x, vec<3, T, Q> const& y) + { + GLM_STATIC_ASSERT(std::numeric_limits<T>::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<length_t L, typename T, qualifier Q, bool Aligned> + struct compute_normalize + { + GLM_FUNC_QUALIFIER static vec<L, T, Q> call(vec<L, T, Q> const& v) + { + GLM_STATIC_ASSERT(std::numeric_limits<T>::is_iec559, "'normalize' accepts only floating-point inputs"); + + return v * inversesqrt(dot(v, v)); + } + }; + + template<length_t L, typename T, qualifier Q, bool Aligned> + struct compute_faceforward + { + GLM_FUNC_QUALIFIER static vec<L, T, Q> call(vec<L, T, Q> const& N, vec<L, T, Q> const& I, vec<L, T, Q> const& Nref) + { + GLM_STATIC_ASSERT(std::numeric_limits<T>::is_iec559, "'normalize' accepts only floating-point inputs"); + + return dot(Nref, I) < static_cast<T>(0) ? N : -N; + } + }; + + template<length_t L, typename T, qualifier Q, bool Aligned> + struct compute_reflect + { + GLM_FUNC_QUALIFIER static vec<L, T, Q> call(vec<L, T, Q> const& I, vec<L, T, Q> const& N) + { + return I - N * dot(N, I) * static_cast<T>(2); + } + }; + + template<length_t L, typename T, qualifier Q, bool Aligned> + struct compute_refract + { + GLM_FUNC_QUALIFIER static vec<L, T, Q> call(vec<L, T, Q> const& I, vec<L, T, Q> const& N, T eta) + { + T const dotValue(dot(N, I)); + T const k(static_cast<T>(1) - eta * eta * (static_cast<T>(1) - dotValue * dotValue)); + vec<L, T, Q> const Result = + (k >= static_cast<T>(0)) ? (eta * I - (eta * dotValue + std::sqrt(k)) * N) : vec<L, T, Q>(0); + return Result; + } + }; +}//namespace detail + + // length + template<typename genType> + GLM_FUNC_QUALIFIER genType length(genType x) + { + GLM_STATIC_ASSERT(std::numeric_limits<genType>::is_iec559, "'length' accepts only floating-point inputs"); + + return abs(x); + } + + template<length_t L, typename T, qualifier Q> + GLM_FUNC_QUALIFIER T length(vec<L, T, Q> const& v) + { + GLM_STATIC_ASSERT(std::numeric_limits<T>::is_iec559, "'length' accepts only floating-point inputs"); + + return detail::compute_length<L, T, Q, detail::is_aligned<Q>::value>::call(v); + } + + // distance + template<typename genType> + GLM_FUNC_QUALIFIER genType distance(genType const& p0, genType const& p1) + { + GLM_STATIC_ASSERT(std::numeric_limits<genType>::is_iec559, "'distance' accepts only floating-point inputs"); + + return length(p1 - p0); + } + + template<length_t L, typename T, qualifier Q> + GLM_FUNC_QUALIFIER T distance(vec<L, T, Q> const& p0, vec<L, T, Q> const& p1) + { + return detail::compute_distance<L, T, Q, detail::is_aligned<Q>::value>::call(p0, p1); + } + + // dot + template<typename T> + GLM_FUNC_QUALIFIER T dot(T x, T y) + { + GLM_STATIC_ASSERT(std::numeric_limits<T>::is_iec559, "'dot' accepts only floating-point inputs"); + return x * y; + } + + template<length_t L, typename T, qualifier Q> + GLM_FUNC_QUALIFIER T dot(vec<L, T, Q> const& x, vec<L, T, Q> const& y) + { + GLM_STATIC_ASSERT(std::numeric_limits<T>::is_iec559, "'dot' accepts only floating-point inputs"); + return detail::compute_dot<vec<L, T, Q>, T, detail::is_aligned<Q>::value>::call(x, y); + } + + // cross + template<typename T, qualifier Q> + GLM_FUNC_QUALIFIER vec<3, T, Q> cross(vec<3, T, Q> const& x, vec<3, T, Q> const& y) + { + return detail::compute_cross<T, Q, detail::is_aligned<Q>::value>::call(x, y); + } +/* + // normalize + template<typename genType> + GLM_FUNC_QUALIFIER genType normalize(genType const& x) + { + GLM_STATIC_ASSERT(std::numeric_limits<genType>::is_iec559, "'normalize' accepts only floating-point inputs"); + + return x < genType(0) ? genType(-1) : genType(1); + } +*/ + template<length_t L, typename T, qualifier Q> + GLM_FUNC_QUALIFIER vec<L, T, Q> normalize(vec<L, T, Q> const& x) + { + GLM_STATIC_ASSERT(std::numeric_limits<T>::is_iec559, "'normalize' accepts only floating-point inputs"); + + return detail::compute_normalize<L, T, Q, detail::is_aligned<Q>::value>::call(x); + } + + // faceforward + template<typename genType> + GLM_FUNC_QUALIFIER genType faceforward(genType const& N, genType const& I, genType const& Nref) + { + return dot(Nref, I) < static_cast<genType>(0) ? N : -N; + } + + template<length_t L, typename T, qualifier Q> + GLM_FUNC_QUALIFIER vec<L, T, Q> faceforward(vec<L, T, Q> const& N, vec<L, T, Q> const& I, vec<L, T, Q> const& Nref) + { + return detail::compute_faceforward<L, T, Q, detail::is_aligned<Q>::value>::call(N, I, Nref); + } + + // reflect + template<typename genType> + GLM_FUNC_QUALIFIER genType reflect(genType const& I, genType const& N) + { + return I - N * dot(N, I) * genType(2); + } + + template<length_t L, typename T, qualifier Q> + GLM_FUNC_QUALIFIER vec<L, T, Q> reflect(vec<L, T, Q> const& I, vec<L, T, Q> const& N) + { + return detail::compute_reflect<L, T, Q, detail::is_aligned<Q>::value>::call(I, N); + } + + // refract + template<typename genType> + GLM_FUNC_QUALIFIER genType refract(genType const& I, genType const& N, genType eta) + { + GLM_STATIC_ASSERT(std::numeric_limits<genType>::is_iec559, "'refract' accepts only floating-point inputs"); + genType const dotValue(dot(N, I)); + genType const k(static_cast<genType>(1) - eta * eta * (static_cast<genType>(1) - dotValue * dotValue)); + return (eta * I - (eta * dotValue + sqrt(k)) * N) * static_cast<genType>(k >= static_cast<genType>(0)); + } + + template<length_t L, typename T, qualifier Q> + GLM_FUNC_QUALIFIER vec<L, T, Q> refract(vec<L, T, Q> const& I, vec<L, T, Q> const& N, T eta) + { + GLM_STATIC_ASSERT(std::numeric_limits<T>::is_iec559, "'refract' accepts only floating-point inputs"); + return detail::compute_refract<L, T, Q, detail::is_aligned<Q>::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 0000000000000000000000000000000000000000..2076dae055c3c689046e258f726440041b4afd85 --- /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<qualifier Q> + 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<qualifier Q> + 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<qualifier Q> + struct compute_dot<vec<4, float, Q>, 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<qualifier Q> + struct compute_cross<float, Q, true> + { + 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<qualifier Q> + 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<qualifier Q> + 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<qualifier Q> + 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<qualifier Q> + 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<qualifier Q> + struct compute_length<4, float, Q, true> + { + GLM_FUNC_QUALIFIER static float call(vec<4, float, Q> const& v) + { + return sqrt(compute_dot<vec<4, float, Q>, float, true>::call(v, v)); + } + }; + + template<qualifier Q> + 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<qualifier Q> + struct compute_dot<vec<4, float, Q>, 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<qualifier Q> + 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 0000000000000000000000000000000000000000..091e1e0c202d30bad78d4fe49e1e0167e54c3ed0 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/detail/func_integer.inl @@ -0,0 +1,372 @@ +/// @ref core + +#include "_vectorize.hpp" +#if(GLM_ARCH & GLM_ARCH_X86 && GLM_COMPILER & GLM_COMPILER_VC) +# include <intrin.h> +# pragma intrinsic(_BitScanReverse) +#endif//(GLM_ARCH & GLM_ARCH_X86 && GLM_COMPILER & GLM_COMPILER_VC) +#include <limits> + +#if !GLM_HAS_EXTENDED_INTEGER_TYPE +# if GLM_COMPILER & GLM_COMPILER_GCC +# pragma GCC diagnostic ignored "-Wlong-long" +# endif +# if (GLM_COMPILER & GLM_COMPILER_CLANG) +# pragma clang diagnostic ignored "-Wc++11-long-long" +# endif +#endif + +namespace glm{ +namespace detail +{ + template<typename T> + GLM_FUNC_QUALIFIER T mask(T Bits) + { + return Bits >= static_cast<T>(sizeof(T) * 8) ? ~static_cast<T>(0) : (static_cast<T>(1) << Bits) - static_cast<T>(1); + } + + template<length_t L, typename T, qualifier Q, bool Aligned, bool EXEC> + struct compute_bitfieldReverseStep + { + GLM_FUNC_QUALIFIER static vec<L, T, Q> call(vec<L, T, Q> const& v, T, T) + { + return v; + } + }; + + template<length_t L, typename T, qualifier Q, bool Aligned> + struct compute_bitfieldReverseStep<L, T, Q, Aligned, true> + { + GLM_FUNC_QUALIFIER static vec<L, T, Q> call(vec<L, T, Q> const& v, T Mask, T Shift) + { + return (v & Mask) << Shift | (v & (~Mask)) >> Shift; + } + }; + + template<length_t L, typename T, qualifier Q, bool Aligned, bool EXEC> + struct compute_bitfieldBitCountStep + { + GLM_FUNC_QUALIFIER static vec<L, T, Q> call(vec<L, T, Q> const& v, T, T) + { + return v; + } + }; + + template<length_t L, typename T, qualifier Q, bool Aligned> + struct compute_bitfieldBitCountStep<L, T, Q, Aligned, true> + { + GLM_FUNC_QUALIFIER static vec<L, T, Q> call(vec<L, T, Q> const& v, T Mask, T Shift) + { + return (v & Mask) + ((v >> Shift) & Mask); + } + }; + + template<typename genIUType, size_t Bits> + struct compute_findLSB + { + GLM_FUNC_QUALIFIER static int call(genIUType Value) + { + if(Value == 0) + return -1; + + return glm::bitCount(~Value & (Value - static_cast<genIUType>(1))); + } + }; + +# if GLM_HAS_BITSCAN_WINDOWS + template<typename genIUType> + struct compute_findLSB<genIUType, 32> + { + GLM_FUNC_QUALIFIER static int call(genIUType Value) + { + unsigned long Result(0); + unsigned char IsNotNull = _BitScanForward(&Result, *reinterpret_cast<unsigned long*>(&Value)); + return IsNotNull ? int(Result) : -1; + } + }; + +# if !((GLM_COMPILER & GLM_COMPILER_VC) && (GLM_MODEL == GLM_MODEL_32)) + template<typename genIUType> + struct compute_findLSB<genIUType, 64> + { + GLM_FUNC_QUALIFIER static int call(genIUType Value) + { + unsigned long Result(0); + unsigned char IsNotNull = _BitScanForward64(&Result, *reinterpret_cast<unsigned __int64*>(&Value)); + return IsNotNull ? int(Result) : -1; + } + }; +# endif +# endif//GLM_HAS_BITSCAN_WINDOWS + + template<length_t L, typename T, qualifier Q, bool EXEC = true> + struct compute_findMSB_step_vec + { + GLM_FUNC_QUALIFIER static vec<L, T, Q> call(vec<L, T, Q> const& x, T Shift) + { + return x | (x >> Shift); + } + }; + + template<length_t L, typename T, qualifier Q> + struct compute_findMSB_step_vec<L, T, Q, false> + { + GLM_FUNC_QUALIFIER static vec<L, T, Q> call(vec<L, T, Q> const& x, T) + { + return x; + } + }; + + template<length_t L, typename T, qualifier Q, int> + struct compute_findMSB_vec + { + GLM_FUNC_QUALIFIER static vec<L, int, Q> call(vec<L, T, Q> const& v) + { + vec<L, T, Q> x(v); + x = compute_findMSB_step_vec<L, T, Q, sizeof(T) * 8 >= 8>::call(x, static_cast<T>( 1)); + x = compute_findMSB_step_vec<L, T, Q, sizeof(T) * 8 >= 8>::call(x, static_cast<T>( 2)); + x = compute_findMSB_step_vec<L, T, Q, sizeof(T) * 8 >= 8>::call(x, static_cast<T>( 4)); + x = compute_findMSB_step_vec<L, T, Q, sizeof(T) * 8 >= 16>::call(x, static_cast<T>( 8)); + x = compute_findMSB_step_vec<L, T, Q, sizeof(T) * 8 >= 32>::call(x, static_cast<T>(16)); + x = compute_findMSB_step_vec<L, T, Q, sizeof(T) * 8 >= 64>::call(x, static_cast<T>(32)); + return vec<L, int, Q>(sizeof(T) * 8 - 1) - glm::bitCount(~x); + } + }; + +# if GLM_HAS_BITSCAN_WINDOWS + template<typename genIUType> + GLM_FUNC_QUALIFIER int compute_findMSB_32(genIUType Value) + { + unsigned long Result(0); + unsigned char IsNotNull = _BitScanReverse(&Result, *reinterpret_cast<unsigned long*>(&Value)); + return IsNotNull ? int(Result) : -1; + } + + template<length_t L, typename T, qualifier Q> + struct compute_findMSB_vec<L, T, Q, 32> + { + GLM_FUNC_QUALIFIER static vec<L, int, Q> call(vec<L, T, Q> const& x) + { + return detail::functor1<vec, L, int, T, Q>::call(compute_findMSB_32, x); + } + }; + +# if !((GLM_COMPILER & GLM_COMPILER_VC) && (GLM_MODEL == GLM_MODEL_32)) + template<typename genIUType> + GLM_FUNC_QUALIFIER int compute_findMSB_64(genIUType Value) + { + unsigned long Result(0); + unsigned char IsNotNull = _BitScanReverse64(&Result, *reinterpret_cast<unsigned __int64*>(&Value)); + return IsNotNull ? int(Result) : -1; + } + + template<length_t L, typename T, qualifier Q> + struct compute_findMSB_vec<L, T, Q, 64> + { + GLM_FUNC_QUALIFIER static vec<L, int, Q> call(vec<L, T, Q> const& x) + { + return detail::functor1<vec, L, int, T, Q>::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<detail::uint64>(x) + static_cast<detail::uint64>(y)); + detail::uint64 const Max32((static_cast<detail::uint64>(1) << static_cast<detail::uint64>(32)) - static_cast<detail::uint64>(1)); + Carry = Value64 > Max32 ? 1u : 0u; + return static_cast<uint>(Value64 % (Max32 + static_cast<detail::uint64>(1))); + } + + template<length_t L, qualifier Q> + GLM_FUNC_QUALIFIER vec<L, uint, Q> uaddCarry(vec<L, uint, Q> const& x, vec<L, uint, Q> const& y, vec<L, uint, Q>& Carry) + { + vec<L, detail::uint64, Q> Value64(vec<L, detail::uint64, Q>(x) + vec<L, detail::uint64, Q>(y)); + vec<L, detail::uint64, Q> Max32((static_cast<detail::uint64>(1) << static_cast<detail::uint64>(32)) - static_cast<detail::uint64>(1)); + Carry = mix(vec<L, uint, Q>(0), vec<L, uint, Q>(1), greaterThan(Value64, Max32)); + return vec<L, uint, Q>(Value64 % (Max32 + static_cast<detail::uint64>(1))); + } + + // usubBorrow + GLM_FUNC_QUALIFIER uint usubBorrow(uint const& x, uint const& y, uint & Borrow) + { + Borrow = x >= y ? static_cast<uint>(0) : static_cast<uint>(1); + if(y >= x) + return y - x; + else + return static_cast<uint>((static_cast<detail::int64>(1) << static_cast<detail::int64>(32)) + (static_cast<detail::int64>(y) - static_cast<detail::int64>(x))); + } + + template<length_t L, qualifier Q> + GLM_FUNC_QUALIFIER vec<L, uint, Q> usubBorrow(vec<L, uint, Q> const& x, vec<L, uint, Q> const& y, vec<L, uint, Q>& Borrow) + { + Borrow = mix(vec<L, uint, Q>(1), vec<L, uint, Q>(0), greaterThanEqual(x, y)); + vec<L, uint, Q> const YgeX(y - x); + vec<L, uint, Q> const XgeY(vec<L, uint, Q>((static_cast<detail::int64>(1) << static_cast<detail::int64>(32)) + (vec<L, detail::int64, Q>(y) - vec<L, detail::int64, Q>(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<detail::uint64>(x) * static_cast<detail::uint64>(y); + msb = static_cast<uint>(Value64 >> static_cast<detail::uint64>(32)); + lsb = static_cast<uint>(Value64); + } + + template<length_t L, qualifier Q> + GLM_FUNC_QUALIFIER void umulExtended(vec<L, uint, Q> const& x, vec<L, uint, Q> const& y, vec<L, uint, Q>& msb, vec<L, uint, Q>& lsb) + { + vec<L, detail::uint64, Q> Value64(vec<L, detail::uint64, Q>(x) * vec<L, detail::uint64, Q>(y)); + msb = vec<L, uint, Q>(Value64 >> static_cast<detail::uint64>(32)); + lsb = vec<L, uint, Q>(Value64); + } + + // imulExtended + GLM_FUNC_QUALIFIER void imulExtended(int x, int y, int& msb, int& lsb) + { + detail::int64 Value64 = static_cast<detail::int64>(x) * static_cast<detail::int64>(y); + msb = static_cast<int>(Value64 >> static_cast<detail::int64>(32)); + lsb = static_cast<int>(Value64); + } + + template<length_t L, qualifier Q> + GLM_FUNC_QUALIFIER void imulExtended(vec<L, int, Q> const& x, vec<L, int, Q> const& y, vec<L, int, Q>& msb, vec<L, int, Q>& lsb) + { + vec<L, detail::int64, Q> Value64(vec<L, detail::int64, Q>(x) * vec<L, detail::int64, Q>(y)); + lsb = vec<L, int, Q>(Value64 & static_cast<detail::int64>(0xFFFFFFFF)); + msb = vec<L, int, Q>((Value64 >> static_cast<detail::int64>(32)) & static_cast<detail::int64>(0xFFFFFFFF)); + } + + // bitfieldExtract + template<typename genIUType> + GLM_FUNC_QUALIFIER genIUType bitfieldExtract(genIUType Value, int Offset, int Bits) + { + return bitfieldExtract(vec<1, genIUType>(Value), Offset, Bits).x; + } + + template<length_t L, typename T, qualifier Q> + GLM_FUNC_QUALIFIER vec<L, T, Q> bitfieldExtract(vec<L, T, Q> const& Value, int Offset, int Bits) + { + GLM_STATIC_ASSERT(std::numeric_limits<T>::is_integer, "'bitfieldExtract' only accept integer inputs"); + + return (Value >> static_cast<T>(Offset)) & static_cast<T>(detail::mask(Bits)); + } + + // bitfieldInsert + template<typename genIUType> + GLM_FUNC_QUALIFIER genIUType bitfieldInsert(genIUType const& Base, genIUType const& Insert, int Offset, int Bits) + { + GLM_STATIC_ASSERT(std::numeric_limits<genIUType>::is_integer, "'bitfieldInsert' only accept integer values"); + + return bitfieldInsert(vec<1, genIUType>(Base), vec<1, genIUType>(Insert), Offset, Bits).x; + } + + template<length_t L, typename T, qualifier Q> + GLM_FUNC_QUALIFIER vec<L, T, Q> bitfieldInsert(vec<L, T, Q> const& Base, vec<L, T, Q> const& Insert, int Offset, int Bits) + { + GLM_STATIC_ASSERT(std::numeric_limits<T>::is_integer, "'bitfieldInsert' only accept integer values"); + + T const Mask = static_cast<T>(detail::mask(Bits) << Offset); + return (Base & ~Mask) | ((Insert << static_cast<T>(Offset)) & Mask); + } + + // bitfieldReverse + template<typename genIUType> + GLM_FUNC_QUALIFIER genIUType bitfieldReverse(genIUType x) + { + GLM_STATIC_ASSERT(std::numeric_limits<genIUType>::is_integer, "'bitfieldReverse' only accept integer values"); + + return bitfieldReverse(glm::vec<1, genIUType, glm::defaultp>(x)).x; + } + + template<length_t L, typename T, qualifier Q> + GLM_FUNC_QUALIFIER vec<L, T, Q> bitfieldReverse(vec<L, T, Q> const& v) + { + GLM_STATIC_ASSERT(std::numeric_limits<T>::is_integer, "'bitfieldReverse' only accept integer values"); + + vec<L, T, Q> x(v); + x = detail::compute_bitfieldReverseStep<L, T, Q, detail::is_aligned<Q>::value, sizeof(T) * 8>= 2>::call(x, static_cast<T>(0x5555555555555555ull), static_cast<T>( 1)); + x = detail::compute_bitfieldReverseStep<L, T, Q, detail::is_aligned<Q>::value, sizeof(T) * 8>= 4>::call(x, static_cast<T>(0x3333333333333333ull), static_cast<T>( 2)); + x = detail::compute_bitfieldReverseStep<L, T, Q, detail::is_aligned<Q>::value, sizeof(T) * 8>= 8>::call(x, static_cast<T>(0x0F0F0F0F0F0F0F0Full), static_cast<T>( 4)); + x = detail::compute_bitfieldReverseStep<L, T, Q, detail::is_aligned<Q>::value, sizeof(T) * 8>= 16>::call(x, static_cast<T>(0x00FF00FF00FF00FFull), static_cast<T>( 8)); + x = detail::compute_bitfieldReverseStep<L, T, Q, detail::is_aligned<Q>::value, sizeof(T) * 8>= 32>::call(x, static_cast<T>(0x0000FFFF0000FFFFull), static_cast<T>(16)); + x = detail::compute_bitfieldReverseStep<L, T, Q, detail::is_aligned<Q>::value, sizeof(T) * 8>= 64>::call(x, static_cast<T>(0x00000000FFFFFFFFull), static_cast<T>(32)); + return x; + } + + // bitCount + template<typename genIUType> + GLM_FUNC_QUALIFIER int bitCount(genIUType x) + { + GLM_STATIC_ASSERT(std::numeric_limits<genIUType>::is_integer, "'bitCount' only accept integer values"); + + return bitCount(glm::vec<1, genIUType, glm::defaultp>(x)).x; + } + + template<length_t L, typename T, qualifier Q> + GLM_FUNC_QUALIFIER vec<L, int, Q> bitCount(vec<L, T, Q> const& v) + { + GLM_STATIC_ASSERT(std::numeric_limits<T>::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<L, typename detail::make_unsigned<T>::type, Q> x(*reinterpret_cast<vec<L, typename detail::make_unsigned<T>::type, Q> const *>(&v)); + x = detail::compute_bitfieldBitCountStep<L, typename detail::make_unsigned<T>::type, Q, detail::is_aligned<Q>::value, sizeof(T) * 8>= 2>::call(x, typename detail::make_unsigned<T>::type(0x5555555555555555ull), typename detail::make_unsigned<T>::type( 1)); + x = detail::compute_bitfieldBitCountStep<L, typename detail::make_unsigned<T>::type, Q, detail::is_aligned<Q>::value, sizeof(T) * 8>= 4>::call(x, typename detail::make_unsigned<T>::type(0x3333333333333333ull), typename detail::make_unsigned<T>::type( 2)); + x = detail::compute_bitfieldBitCountStep<L, typename detail::make_unsigned<T>::type, Q, detail::is_aligned<Q>::value, sizeof(T) * 8>= 8>::call(x, typename detail::make_unsigned<T>::type(0x0F0F0F0F0F0F0F0Full), typename detail::make_unsigned<T>::type( 4)); + x = detail::compute_bitfieldBitCountStep<L, typename detail::make_unsigned<T>::type, Q, detail::is_aligned<Q>::value, sizeof(T) * 8>= 16>::call(x, typename detail::make_unsigned<T>::type(0x00FF00FF00FF00FFull), typename detail::make_unsigned<T>::type( 8)); + x = detail::compute_bitfieldBitCountStep<L, typename detail::make_unsigned<T>::type, Q, detail::is_aligned<Q>::value, sizeof(T) * 8>= 32>::call(x, typename detail::make_unsigned<T>::type(0x0000FFFF0000FFFFull), typename detail::make_unsigned<T>::type(16)); + x = detail::compute_bitfieldBitCountStep<L, typename detail::make_unsigned<T>::type, Q, detail::is_aligned<Q>::value, sizeof(T) * 8>= 64>::call(x, typename detail::make_unsigned<T>::type(0x00000000FFFFFFFFull), typename detail::make_unsigned<T>::type(32)); + return vec<L, int, Q>(x); + +# if GLM_COMPILER & GLM_COMPILER_VC +# pragma warning(pop) +# endif + } + + // findLSB + template<typename genIUType> + GLM_FUNC_QUALIFIER int findLSB(genIUType Value) + { + GLM_STATIC_ASSERT(std::numeric_limits<genIUType>::is_integer, "'findLSB' only accept integer values"); + + return detail::compute_findLSB<genIUType, sizeof(genIUType) * 8>::call(Value); + } + + template<length_t L, typename T, qualifier Q> + GLM_FUNC_QUALIFIER vec<L, int, Q> findLSB(vec<L, T, Q> const& x) + { + GLM_STATIC_ASSERT(std::numeric_limits<T>::is_integer, "'findLSB' only accept integer values"); + + return detail::functor1<vec, L, int, T, Q>::call(findLSB, x); + } + + // findMSB + template<typename genIUType> + GLM_FUNC_QUALIFIER int findMSB(genIUType v) + { + GLM_STATIC_ASSERT(std::numeric_limits<genIUType>::is_integer, "'findMSB' only accept integer values"); + + return findMSB(vec<1, genIUType>(v)).x; + } + + template<length_t L, typename T, qualifier Q> + GLM_FUNC_QUALIFIER vec<L, int, Q> findMSB(vec<L, T, Q> const& v) + { + GLM_STATIC_ASSERT(std::numeric_limits<T>::is_integer, "'findMSB' only accept integer values"); + + return detail::compute_findMSB_vec<L, T, Q, sizeof(T) * 8>::call(v); + } +}//namespace glm + +#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 0000000000000000000000000000000000000000..8be6c9ce4dc143cedd3565899b6c44b7fea3bde8 --- /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<qualifier Q> + 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<int>(Mask)); + __m128i const and1 = _mm_and_si128(set0, set1); + __m128i const sft1 = _mm_slli_epi32(and1, 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, Shift); + + __m128i const or0 = _mm_or_si128(sft1, sft2); + + return or0; + } + }; + + template<qualifier Q> + 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<int>(Mask)); + __m128i const and0 = _mm_and_si128(set0, set1); + __m128i const sft0 = _mm_slli_epi32(set0, 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<int>(_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 0000000000000000000000000000000000000000..d980c6d3888584d108f12f41def72c0ffda633ca --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/detail/func_matrix.inl @@ -0,0 +1,398 @@ +#include "../geometric.hpp" +#include <limits> + +namespace glm{ +namespace detail +{ + template<length_t C, length_t R, typename T, qualifier Q, bool Aligned> + struct compute_matrixCompMult + { + GLM_FUNC_QUALIFIER static mat<C, R, T, Q> call(mat<C, R, T, Q> const& x, mat<C, R, T, Q> const& y) + { + mat<C, R, T, Q> Result; + for(length_t i = 0; i < Result.length(); ++i) + Result[i] = x[i] * y[i]; + return Result; + } + }; + + template<length_t C, length_t R, typename T, qualifier Q, bool Aligned> + struct compute_transpose{}; + + template<typename T, qualifier Q, bool Aligned> + 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; + 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<typename T, qualifier Q, bool Aligned> + 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; + 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<typename T, qualifier Q, bool Aligned> + 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; + 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<typename T, qualifier Q, bool Aligned> + 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; + 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<typename T, qualifier Q, bool Aligned> + 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; + 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<typename T, qualifier Q, bool Aligned> + 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; + 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<typename T, qualifier Q, bool Aligned> + 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; + 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<typename T, qualifier Q, bool Aligned> + 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; + 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<typename T, qualifier Q, bool Aligned> + 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; + 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<length_t C, length_t R, typename T, qualifier Q, bool Aligned> + struct compute_determinant{}; + + template<typename T, qualifier Q, bool Aligned> + 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<typename T, qualifier Q, bool Aligned> + 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<typename T, qualifier Q, bool Aligned> + 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<length_t C, length_t R, typename T, qualifier Q, bool Aligned> + struct compute_inverse{}; + + template<typename T, qualifier Q, bool Aligned> + 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<T>(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<typename T, qualifier Q, bool Aligned> + 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<T>(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<typename T, qualifier Q, bool Aligned> + 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<T>(1) / Dot1; + + return Inverse * OneOverDeterminant; + } + }; +}//namespace detail + + template<length_t C, length_t R, typename T, qualifier Q> + GLM_FUNC_QUALIFIER mat<C, R, T, Q> matrixCompMult(mat<C, R, T, Q> const& x, mat<C, R, T, Q> const& y) + { + GLM_STATIC_ASSERT(std::numeric_limits<T>::is_iec559 || GLM_CONFIG_UNRESTRICTED_GENTYPE, "'matrixCompMult' only accept floating-point inputs"); + return detail::compute_matrixCompMult<C, R, T, Q, detail::is_aligned<Q>::value>::call(x, y); + } + + template<length_t DA, length_t DB, typename T, qualifier Q> + GLM_FUNC_QUALIFIER typename detail::outerProduct_trait<DA, DB, T, Q>::type outerProduct(vec<DA, T, Q> const& c, vec<DB, T, Q> const& r) + { + GLM_STATIC_ASSERT(std::numeric_limits<T>::is_iec559 || GLM_CONFIG_UNRESTRICTED_GENTYPE, "'outerProduct' only accept floating-point inputs"); + + typename detail::outerProduct_trait<DA, DB, T, Q>::type m; + for(length_t i = 0; i < m.length(); ++i) + m[i] = c * r[i]; + return m; + } + + template<length_t C, length_t R, typename T, qualifier Q> + GLM_FUNC_QUALIFIER typename mat<C, R, T, Q>::transpose_type transpose(mat<C, R, T, Q> const& m) + { + GLM_STATIC_ASSERT(std::numeric_limits<T>::is_iec559 || GLM_CONFIG_UNRESTRICTED_GENTYPE, "'transpose' only accept floating-point inputs"); + return detail::compute_transpose<C, R, T, Q, detail::is_aligned<Q>::value>::call(m); + } + + template<length_t C, length_t R, typename T, qualifier Q> + GLM_FUNC_QUALIFIER T determinant(mat<C, R, T, Q> const& m) + { + GLM_STATIC_ASSERT(std::numeric_limits<T>::is_iec559 || GLM_CONFIG_UNRESTRICTED_GENTYPE, "'determinant' only accept floating-point inputs"); + return detail::compute_determinant<C, R, T, Q, detail::is_aligned<Q>::value>::call(m); + } + + template<length_t C, length_t R, typename T, qualifier Q> + GLM_FUNC_QUALIFIER mat<C, R, T, Q> inverse(mat<C, R, T, Q> const& m) + { + GLM_STATIC_ASSERT(std::numeric_limits<T>::is_iec559 || GLM_CONFIG_UNRESTRICTED_GENTYPE, "'inverse' only accept floating-point inputs"); + return detail::compute_inverse<C, R, T, Q, detail::is_aligned<Q>::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 0000000000000000000000000000000000000000..f67ac66ae22176205c2a3df22463c1cac2b471d8 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/detail/func_matrix_simd.inl @@ -0,0 +1,249 @@ +#if GLM_ARCH & GLM_ARCH_SSE2_BIT + +#include "type_mat4x4.hpp" +#include "../geometric.hpp" +#include "../simd/matrix.h" +#include <cstring> + +namespace glm{ +namespace detail +{ +# if GLM_CONFIG_ALIGNED_GENTYPES == GLM_ENABLE + template<qualifier Q> + struct compute_matrixCompMult<4, 4, float, Q, true> + { + GLM_STATIC_ASSERT(detail::is_aligned<Q>::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( + *static_cast<glm_vec4 const (*)[4]>(&x[0].data), + *static_cast<glm_vec4 const (*)[4]>(&y[0].data), + *static_cast<glm_vec4(*)[4]>(&Result[0].data)); + return Result; + } + }; +# endif + + template<qualifier Q> + 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<qualifier Q> + 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<qualifier Q> + 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 <qualifier Q> + GLM_FUNC_QUALIFIER + typename std::enable_if<detail::is_aligned<Q>::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 + + template<qualifier Q> + struct detail::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 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 0000000000000000000000000000000000000000..234b093c081cc029ccf2094efbdb3d63b319431e --- /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 0000000000000000000000000000000000000000..fd0fe8b7d9b4a49f032fd678b7bd6a51624a6b53 --- /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 0000000000000000000000000000000000000000..e129dceac5cb2ae09dd4154cf3356173317b9801 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/detail/func_trigonometric.inl @@ -0,0 +1,197 @@ +#include "_vectorize.hpp" +#include <cmath> +#include <limits> + +namespace glm +{ + // radians + template<typename genType> + GLM_FUNC_QUALIFIER GLM_CONSTEXPR genType radians(genType degrees) + { + GLM_STATIC_ASSERT(std::numeric_limits<genType>::is_iec559, "'radians' only accept floating-point input"); + + return degrees * static_cast<genType>(0.01745329251994329576923690768489); + } + + template<length_t L, typename T, qualifier Q> + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<L, T, Q> radians(vec<L, T, Q> const& v) + { + return detail::functor1<vec, L, T, T, Q>::call(radians, v); + } + + // degrees + template<typename genType> + GLM_FUNC_QUALIFIER GLM_CONSTEXPR genType degrees(genType radians) + { + GLM_STATIC_ASSERT(std::numeric_limits<genType>::is_iec559, "'degrees' only accept floating-point input"); + + return radians * static_cast<genType>(57.295779513082320876798154814105); + } + + template<length_t L, typename T, qualifier Q> + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<L, T, Q> degrees(vec<L, T, Q> const& v) + { + return detail::functor1<vec, L, T, T, Q>::call(degrees, v); + } + + // sin + using ::std::sin; + + template<length_t L, typename T, qualifier Q> + GLM_FUNC_QUALIFIER vec<L, T, Q> sin(vec<L, T, Q> const& v) + { + return detail::functor1<vec, L, T, T, Q>::call(sin, v); + } + + // cos + using std::cos; + + template<length_t L, typename T, qualifier Q> + GLM_FUNC_QUALIFIER vec<L, T, Q> cos(vec<L, T, Q> const& v) + { + return detail::functor1<vec, L, T, T, Q>::call(cos, v); + } + + // tan + using std::tan; + + template<length_t L, typename T, qualifier Q> + GLM_FUNC_QUALIFIER vec<L, T, Q> tan(vec<L, T, Q> const& v) + { + return detail::functor1<vec, L, T, T, Q>::call(tan, v); + } + + // asin + using std::asin; + + template<length_t L, typename T, qualifier Q> + GLM_FUNC_QUALIFIER vec<L, T, Q> asin(vec<L, T, Q> const& v) + { + return detail::functor1<vec, L, T, T, Q>::call(asin, v); + } + + // acos + using std::acos; + + template<length_t L, typename T, qualifier Q> + GLM_FUNC_QUALIFIER vec<L, T, Q> acos(vec<L, T, Q> const& v) + { + return detail::functor1<vec, L, T, T, Q>::call(acos, v); + } + + // atan + template<typename genType> + GLM_FUNC_QUALIFIER genType atan(genType y, genType x) + { + GLM_STATIC_ASSERT(std::numeric_limits<genType>::is_iec559, "'atan' only accept floating-point input"); + + return ::std::atan2(y, x); + } + + template<length_t L, typename T, qualifier Q> + GLM_FUNC_QUALIFIER vec<L, T, Q> atan(vec<L, T, Q> const& a, vec<L, T, Q> const& b) + { + return detail::functor2<vec, L, T, Q>::call(::std::atan2, a, b); + } + + using std::atan; + + template<length_t L, typename T, qualifier Q> + GLM_FUNC_QUALIFIER vec<L, T, Q> atan(vec<L, T, Q> const& v) + { + return detail::functor1<vec, L, T, T, Q>::call(atan, v); + } + + // sinh + using std::sinh; + + template<length_t L, typename T, qualifier Q> + GLM_FUNC_QUALIFIER vec<L, T, Q> sinh(vec<L, T, Q> const& v) + { + return detail::functor1<vec, L, T, T, Q>::call(sinh, v); + } + + // cosh + using std::cosh; + + template<length_t L, typename T, qualifier Q> + GLM_FUNC_QUALIFIER vec<L, T, Q> cosh(vec<L, T, Q> const& v) + { + return detail::functor1<vec, L, T, T, Q>::call(cosh, v); + } + + // tanh + using std::tanh; + + template<length_t L, typename T, qualifier Q> + GLM_FUNC_QUALIFIER vec<L, T, Q> tanh(vec<L, T, Q> const& v) + { + return detail::functor1<vec, L, T, T, Q>::call(tanh, v); + } + + // asinh +# if GLM_HAS_CXX11_STL + using std::asinh; +# else + template<typename genType> + GLM_FUNC_QUALIFIER genType asinh(genType x) + { + GLM_STATIC_ASSERT(std::numeric_limits<genType>::is_iec559, "'asinh' only accept floating-point input"); + + return (x < static_cast<genType>(0) ? static_cast<genType>(-1) : (x > static_cast<genType>(0) ? static_cast<genType>(1) : static_cast<genType>(0))) * log(std::abs(x) + sqrt(static_cast<genType>(1) + x * x)); + } +# endif + + template<length_t L, typename T, qualifier Q> + GLM_FUNC_QUALIFIER vec<L, T, Q> asinh(vec<L, T, Q> const& v) + { + return detail::functor1<vec, L, T, T, Q>::call(asinh, v); + } + + // acosh +# if GLM_HAS_CXX11_STL + using std::acosh; +# else + template<typename genType> + GLM_FUNC_QUALIFIER genType acosh(genType x) + { + GLM_STATIC_ASSERT(std::numeric_limits<genType>::is_iec559, "'acosh' only accept floating-point input"); + + if(x < static_cast<genType>(1)) + return static_cast<genType>(0); + return log(x + sqrt(x * x - static_cast<genType>(1))); + } +# endif + + template<length_t L, typename T, qualifier Q> + GLM_FUNC_QUALIFIER vec<L, T, Q> acosh(vec<L, T, Q> const& v) + { + return detail::functor1<vec, L, T, T, Q>::call(acosh, v); + } + + // atanh +# if GLM_HAS_CXX11_STL + using std::atanh; +# else + template<typename genType> + GLM_FUNC_QUALIFIER genType atanh(genType x) + { + GLM_STATIC_ASSERT(std::numeric_limits<genType>::is_iec559, "'atanh' only accept floating-point input"); + + if(std::abs(x) >= static_cast<genType>(1)) + return 0; + return static_cast<genType>(0.5) * log((static_cast<genType>(1) + x) / (static_cast<genType>(1) - x)); + } +# endif + + template<length_t L, typename T, qualifier Q> + GLM_FUNC_QUALIFIER vec<L, T, Q> atanh(vec<L, T, Q> const& v) + { + return detail::functor1<vec, L, T, T, Q>::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 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 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 0000000000000000000000000000000000000000..80c9e87fcb97ea042c1aaf42fd6424ebc0bc6e32 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/detail/func_vector_relational.inl @@ -0,0 +1,87 @@ +namespace glm +{ + template<length_t L, typename T, qualifier Q> + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<L, bool, Q> lessThan(vec<L, T, Q> const& x, vec<L, T, Q> const& y) + { + vec<L, bool, Q> Result(true); + for(length_t i = 0; i < L; ++i) + Result[i] = x[i] < y[i]; + return Result; + } + + template<length_t L, typename T, qualifier Q> + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<L, bool, Q> lessThanEqual(vec<L, T, Q> const& x, vec<L, T, Q> const& y) + { + vec<L, bool, Q> Result(true); + for(length_t i = 0; i < L; ++i) + Result[i] = x[i] <= y[i]; + return Result; + } + + template<length_t L, typename T, qualifier Q> + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<L, bool, Q> greaterThan(vec<L, T, Q> const& x, vec<L, T, Q> const& y) + { + vec<L, bool, Q> Result(true); + for(length_t i = 0; i < L; ++i) + Result[i] = x[i] > y[i]; + return Result; + } + + template<length_t L, typename T, qualifier Q> + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<L, bool, Q> greaterThanEqual(vec<L, T, Q> const& x, vec<L, T, Q> const& y) + { + vec<L, bool, Q> Result(true); + for(length_t i = 0; i < L; ++i) + Result[i] = x[i] >= y[i]; + return Result; + } + + template<length_t L, typename T, qualifier Q> + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<L, bool, Q> equal(vec<L, T, Q> const& x, vec<L, T, Q> const& y) + { + vec<L, bool, Q> Result(true); + for(length_t i = 0; i < L; ++i) + Result[i] = x[i] == y[i]; + return Result; + } + + template<length_t L, typename T, qualifier Q> + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<L, bool, Q> notEqual(vec<L, T, Q> const& x, vec<L, T, Q> const& y) + { + vec<L, bool, Q> Result(true); + for(length_t i = 0; i < L; ++i) + Result[i] = x[i] != y[i]; + return Result; + } + + template<length_t L, qualifier Q> + GLM_FUNC_QUALIFIER GLM_CONSTEXPR bool any(vec<L, bool, Q> const& v) + { + bool Result = false; + for(length_t i = 0; i < L; ++i) + Result = Result || v[i]; + return Result; + } + + template<length_t L, qualifier Q> + GLM_FUNC_QUALIFIER GLM_CONSTEXPR bool all(vec<L, bool, Q> const& v) + { + bool Result = true; + for(length_t i = 0; i < L; ++i) + Result = Result && v[i]; + return Result; + } + + template<length_t L, qualifier Q> + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<L, bool, Q> not_(vec<L, bool, Q> const& v) + { + vec<L, bool, Q> 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 0000000000000000000000000000000000000000..fd0fe8b7d9b4a49f032fd678b7bd6a51624a6b53 --- /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 0000000000000000000000000000000000000000..e0755bd65d4675232490a4a9ff944506e632e5f5 --- /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 <glm/gtx/dual_quaternion.hpp> +#include <glm/gtc/vec1.hpp> +#include <glm/gtc/quaternion.hpp> +#include <glm/ext/scalar_int_sized.hpp> +#include <glm/ext/scalar_uint_sized.hpp> +#include <glm/glm.hpp> + +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<float32, lowp>; +template struct qua<float64, lowp>; + +template struct qua<float32, mediump>; +template struct qua<float64, mediump>; + +template struct qua<float32, highp>; +template struct qua<float64, highp>; + +//tdualquat type explicit instantiation +template struct tdualquat<float32, lowp>; +template struct tdualquat<float64, lowp>; + +template struct tdualquat<float32, mediump>; +template struct tdualquat<float64, mediump>; + +template struct tdualquat<float32, highp>; +template struct tdualquat<float64, highp>; + +}//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 0000000000000000000000000000000000000000..b6c9df0ce04c80d96d31d5191973f0c07a06de71 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/detail/qualifier.hpp @@ -0,0 +1,230 @@ +#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<length_t L, typename T, qualifier Q = defaultp> struct vec; + template<length_t C, length_t R, typename T, qualifier Q = defaultp> struct mat; + template<typename T, qualifier Q = defaultp> struct qua; + +# if GLM_HAS_TEMPLATE_ALIASES + template <typename T, qualifier Q = defaultp> using tvec1 = vec<1, T, Q>; + template <typename T, qualifier Q = defaultp> using tvec2 = vec<2, T, Q>; + template <typename T, qualifier Q = defaultp> using tvec3 = vec<3, T, Q>; + template <typename T, qualifier Q = defaultp> using tvec4 = vec<4, T, Q>; + template <typename T, qualifier Q = defaultp> using tmat2x2 = mat<2, 2, T, Q>; + template <typename T, qualifier Q = defaultp> using tmat2x3 = mat<2, 3, T, Q>; + template <typename T, qualifier Q = defaultp> using tmat2x4 = mat<2, 4, T, Q>; + template <typename T, qualifier Q = defaultp> using tmat3x2 = mat<3, 2, T, Q>; + template <typename T, qualifier Q = defaultp> using tmat3x3 = mat<3, 3, T, Q>; + template <typename T, qualifier Q = defaultp> using tmat3x4 = mat<3, 4, T, Q>; + template <typename T, qualifier Q = defaultp> using tmat4x2 = mat<4, 2, T, Q>; + template <typename T, qualifier Q = defaultp> using tmat4x3 = mat<4, 3, T, Q>; + template <typename T, qualifier Q = defaultp> using tmat4x4 = mat<4, 4, T, Q>; + template <typename T, qualifier Q = defaultp> using tquat = qua<T, Q>; +# endif + +namespace detail +{ + template<glm::qualifier P> + struct is_aligned + { + static const bool value = false; + }; + +# if GLM_CONFIG_ALIGNED_GENTYPES == GLM_ENABLE + template<> + struct is_aligned<glm::aligned_lowp> + { + static const bool value = true; + }; + + template<> + struct is_aligned<glm::aligned_mediump> + { + static const bool value = true; + }; + + template<> + struct is_aligned<glm::aligned_highp> + { + static const bool value = true; + }; +# endif + + template<length_t L, typename T, bool is_aligned> + struct storage + { + typedef struct type { + T data[L]; + } type; + }; + +# if GLM_HAS_ALIGNOF + template<length_t L, typename T> + struct storage<L, T, true> + { + typedef struct alignas(L * sizeof(T)) type { + T data[L]; + } type; + }; + + template<typename T> + 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 <typename genType> + struct genTypeTrait + {}; + + template <length_t C, length_t R, typename T> + struct genTypeTrait<mat<C, R, T> > + { + static const genTypeEnum GENTYPE = GENTYPE_MAT; + }; + + template<typename genType, genTypeEnum type> + struct init_gentype + { + }; + + template<typename genType> + struct init_gentype<genType, GENTYPE_QUAT> + { + GLM_FUNC_QUALIFIER GLM_CONSTEXPR static genType identity() + { + return genType(1, 0, 0, 0); + } + }; + + template<typename genType> + struct init_gentype<genType, GENTYPE_MAT> + { + 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 0000000000000000000000000000000000000000..2c01e02fb463b81996f3cdcb9fed1abb844e9e92 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/detail/setup.hpp @@ -0,0 +1,1135 @@ +#ifndef GLM_SETUP_INCLUDED + +#include <cassert> +#include <cstddef> + +#define GLM_VERSION_MAJOR 0 +#define GLM_VERSION_MINOR 9 +#define GLM_VERSION_PATCH 9 +#define GLM_VERSION_REVISION 8 +#define GLM_VERSION 998 +#define GLM_VERSION_MESSAGE "GLM: version 0.9.9.8" + +#define GLM_SETUP_INCLUDED GLM_VERSION + +/////////////////////////////////////////////////////////////////////////////////// +// 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_CXX2A_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_CXX2A (GLM_LANG_CXX17 | GLM_LANG_CXX2A_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_CXX2A) +# define GLM_LANG (GLM_LANG_CXX2A | 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_CXX2A | GLM_LANG_EXT) +# elif __cplusplus == 201703L || GLM_LANG_PLATFORM == 201703L +# define GLM_LANG (GLM_LANG_CXX17 | GLM_LANG_EXT) +# elif __cplusplus == 201402L || __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_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)))) +#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))) +#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)))) +#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))) +#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))) +#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)))) +#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)))) +#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)))) +#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)))) +#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)))) +#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 + +// +#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)))) +#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 + +/////////////////////////////////////////////////////////////////////////////////// +// 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 + +#if GLM_COMPILER & GLM_COMPILER_CUDA +# define GLM_CUDA_FUNC_DEF __device__ __host__ +# define GLM_CUDA_FUNC_DECL __device__ __host__ +#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 +# 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_FUNC_DECL GLM_CUDA_FUNC_DECL +#define GLM_FUNC_QUALIFIER GLM_CUDA_FUNC_DEF GLM_INLINE + +/////////////////////////////////////////////////////////////////////////////////// +// 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_FORCE_XYZW_ONLY) +# undef GLM_FORCE_SWIZZLE +#endif + +#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) +# 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 + +/////////////////////////////////////////////////////////////////////////////////// +// 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) +# define GLM_DEPRECATED __attribute__((__deprecated__)) +# define GLM_ALIGNED_TYPEDEF(type, name, alignment) typedef type name __attribute__((aligned(alignment))) +#elif GLM_COMPILER & GLM_COMPILER_CUDA +# 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 + +/////////////////////////////////////////////////////////////////////////////////// +// SYCL + +#if GLM_COMPILER==GLM_COMPILER_SYCL + +#include <CL/sycl.hpp> +#include <limits> + +namespace glm { +namespace std { + // Import SYCL's functions into the namespace glm::std to force their usages. + // It's important to use the math built-in function (sin, exp, ...) + // of SYCL instead the std ones. + using namespace cl::sycl; + + /////////////////////////////////////////////////////////////////////////////// + // Import some "harmless" std's stuffs used by glm into + // the new glm::std namespace. + template<typename T> + using numeric_limits = ::std::numeric_limits<T>; + + using ::std::size_t; + + using ::std::uint8_t; + using ::std::uint16_t; + using ::std::uint32_t; + using ::std::uint64_t; + + using ::std::int8_t; + using ::std::int16_t; + using ::std::int32_t; + using ::std::int64_t; + + using ::std::make_unsigned; + /////////////////////////////////////////////////////////////////////////////// +} //namespace std +} //namespace glm + +#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 +#else +# define GLM_CONFIG_LENGTH_TYPE GLM_LENGTH_INT +#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<typename T, std::size_t N> + 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<typename T> + struct is_int + { + enum test {value = 0}; + }; + + template<> + struct is_int<unsigned int> + { + enum test {value = ~0}; + }; + + template<> + struct is_int<signed int> + { + enum test {value = ~0}; + }; +}//namespace detail + + typedef unsigned int uint; +}//namespace glm + +/////////////////////////////////////////////////////////////////////////////////// +// 64-bit int + +#if GLM_HAS_EXTENDED_INTEGER_TYPE +# include <cstdint> +#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 <type_traits> + +namespace glm{ +namespace detail +{ + using std::make_unsigned; +}//namespace detail +}//namespace glm + +#else + +namespace glm{ +namespace detail +{ + template<typename genType> + struct make_unsigned + {}; + + template<> + struct make_unsigned<char> + { + typedef unsigned char type; + }; + + template<> + struct make_unsigned<signed char> + { + typedef unsigned char type; + }; + + template<> + struct make_unsigned<short> + { + typedef unsigned short type; + }; + + template<> + struct make_unsigned<int> + { + typedef unsigned int type; + }; + + template<> + struct make_unsigned<long> + { + typedef unsigned long type; + }; + + template<> + struct make_unsigned<int64> + { + typedef uint64 type; + }; + + template<> + struct make_unsigned<unsigned char> + { + typedef unsigned char type; + }; + + template<> + struct make_unsigned<unsigned short> + { + typedef unsigned short type; + }; + + template<> + struct make_unsigned<unsigned int> + { + typedef unsigned int type; + }; + + template<> + struct make_unsigned<unsigned long> + { + typedef unsigned long type; + }; + + template<> + struct make_unsigned<uint64> + { + 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 && GLM_CONFIG_CTOR_INIT == GLM_CTOR_INIT_DISABLE +# define GLM_CONFIG_DEFAULTED_FUNCTIONS GLM_ENABLE +# define GLM_DEFAULT = default +#else +# define GLM_CONFIG_DEFAULTED_FUNCTIONS GLM_DISABLE +# define GLM_DEFAULT +#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_SILENT_WARNINGS +# define GLM_SILENT_WARNINGS GLM_ENABLE +#else +# define GLM_SILENT_WARNINGS GLM_DISABLE +#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_CXX2A_FLAG) && (GLM_LANG & GLM_LANG_EXT) +# pragma message("GLM: C++ 2A with extensions") +# elif (GLM_LANG & GLM_LANG_CXX2A_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_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 0000000000000000000000000000000000000000..c8037ebd7aa265cb56e3b809cf19df8fa807bcf8 --- /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 <typename T> + union float_t + {}; + + // https://randomascii.wordpress.com/2012/02/25/comparing-floating-point-numbers-2012-edition/ + template <> + union float_t<float> + { + 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<double> + { + typedef detail::int64 int_type; + typedef double float_type; + + GLM_CONSTEXPR float_t(float_type Num = static_cast<float_type>(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 0000000000000000000000000000000000000000..40b8bec00d34143d2e1f0ff60a743aad9e30580f --- /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 0000000000000000000000000000000000000000..b0723e362d53ad724adee01a6fbb696162851e64 --- /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; // 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<unsigned int>(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<unsigned int>((s << 31) | 0x7f800000); + return result.f; + } + else + { + // + // Nan -- preserve sign and significand bits + // + + uif32 result; + result.i = static_cast<unsigned int>((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<unsigned int>((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<int>(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 0000000000000000000000000000000000000000..033908f4495b79a9061e79738049684981ccd7f3 --- /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 <limits> +#include <cstddef> + +namespace glm +{ + template<typename T, qualifier Q> + 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 col_type & operator[](length_type i); + GLM_FUNC_DECL GLM_CONSTEXPR col_type const& operator[](length_type i) const; + + // -- Constructors -- + + GLM_FUNC_DECL GLM_CONSTEXPR mat() GLM_DEFAULT; + template<qualifier P> + GLM_FUNC_DECL GLM_CONSTEXPR mat(mat<2, 2, T, P> const& m); + + GLM_FUNC_DECL explicit GLM_CONSTEXPR mat(T scalar); + GLM_FUNC_DECL GLM_CONSTEXPR mat( + T const& x1, T const& y1, + T const& x2, T const& y2); + GLM_FUNC_DECL GLM_CONSTEXPR mat( + col_type const& v1, + col_type const& v2); + + // -- Conversions -- + + template<typename U, typename V, typename M, typename N> + GLM_FUNC_DECL GLM_CONSTEXPR mat( + U const& x1, V const& y1, + M const& x2, N const& y2); + + template<typename U, typename V> + GLM_FUNC_DECL GLM_CONSTEXPR mat( + vec<2, U, Q> const& v1, + vec<2, V, Q> const& v2); + + // -- Matrix conversions -- + + template<typename U, qualifier P> + GLM_FUNC_DECL GLM_EXPLICIT GLM_CONSTEXPR mat(mat<2, 2, U, P> const& m); + + GLM_FUNC_DECL GLM_EXPLICIT GLM_CONSTEXPR mat(mat<3, 3, T, Q> const& x); + GLM_FUNC_DECL GLM_EXPLICIT GLM_CONSTEXPR mat(mat<4, 4, T, Q> const& x); + GLM_FUNC_DECL GLM_EXPLICIT GLM_CONSTEXPR mat(mat<2, 3, T, Q> const& x); + GLM_FUNC_DECL GLM_EXPLICIT GLM_CONSTEXPR mat(mat<3, 2, T, Q> const& x); + GLM_FUNC_DECL GLM_EXPLICIT GLM_CONSTEXPR mat(mat<2, 4, T, Q> const& x); + GLM_FUNC_DECL GLM_EXPLICIT GLM_CONSTEXPR mat(mat<4, 2, T, Q> const& x); + GLM_FUNC_DECL GLM_EXPLICIT GLM_CONSTEXPR mat(mat<3, 4, T, Q> const& x); + GLM_FUNC_DECL GLM_EXPLICIT GLM_CONSTEXPR mat(mat<4, 3, T, Q> const& x); + + // -- Unary arithmetic operators -- + + template<typename U> + GLM_FUNC_DECL mat<2, 2, T, Q> & operator=(mat<2, 2, U, Q> const& m); + template<typename U> + GLM_FUNC_DECL mat<2, 2, T, Q> & operator+=(U s); + template<typename U> + GLM_FUNC_DECL mat<2, 2, T, Q> & operator+=(mat<2, 2, U, Q> const& m); + template<typename U> + GLM_FUNC_DECL mat<2, 2, T, Q> & operator-=(U s); + template<typename U> + GLM_FUNC_DECL mat<2, 2, T, Q> & operator-=(mat<2, 2, U, Q> const& m); + template<typename U> + GLM_FUNC_DECL mat<2, 2, T, Q> & operator*=(U s); + template<typename U> + GLM_FUNC_DECL mat<2, 2, T, Q> & operator*=(mat<2, 2, U, Q> const& m); + template<typename U> + GLM_FUNC_DECL mat<2, 2, T, Q> & operator/=(U s); + template<typename U> + GLM_FUNC_DECL mat<2, 2, T, Q> & operator/=(mat<2, 2, U, Q> const& m); + + // -- Increment and decrement operators -- + + GLM_FUNC_DECL mat<2, 2, T, Q> & operator++ (); + GLM_FUNC_DECL mat<2, 2, T, Q> & operator-- (); + GLM_FUNC_DECL mat<2, 2, T, Q> operator++(int); + GLM_FUNC_DECL mat<2, 2, T, Q> operator--(int); + }; + + // -- Unary operators -- + + template<typename T, qualifier Q> + GLM_FUNC_DECL mat<2, 2, T, Q> operator+(mat<2, 2, T, Q> const& m); + + template<typename T, qualifier Q> + GLM_FUNC_DECL mat<2, 2, T, Q> operator-(mat<2, 2, T, Q> const& m); + + // -- Binary operators -- + + template<typename T, qualifier Q> + GLM_FUNC_DECL mat<2, 2, T, Q> operator+(mat<2, 2, T, Q> const& m, T scalar); + + template<typename T, qualifier Q> + GLM_FUNC_DECL mat<2, 2, T, Q> operator+(T scalar, mat<2, 2, T, Q> const& m); + + template<typename T, qualifier Q> + GLM_FUNC_DECL mat<2, 2, T, Q> operator+(mat<2, 2, T, Q> const& m1, mat<2, 2, T, Q> const& m2); + + template<typename T, qualifier Q> + GLM_FUNC_DECL mat<2, 2, T, Q> operator-(mat<2, 2, T, Q> const& m, T scalar); + + template<typename T, qualifier Q> + GLM_FUNC_DECL mat<2, 2, T, Q> operator-(T scalar, mat<2, 2, T, Q> const& m); + + template<typename T, qualifier Q> + GLM_FUNC_DECL mat<2, 2, T, Q> operator-(mat<2, 2, T, Q> const& m1, mat<2, 2, T, Q> const& m2); + + template<typename T, qualifier Q> + GLM_FUNC_DECL mat<2, 2, T, Q> operator*(mat<2, 2, T, Q> const& m, T scalar); + + template<typename T, qualifier Q> + GLM_FUNC_DECL mat<2, 2, T, Q> operator*(T scalar, mat<2, 2, T, Q> const& m); + + template<typename T, qualifier Q> + GLM_FUNC_DECL 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<typename T, qualifier Q> + GLM_FUNC_DECL 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<typename T, qualifier Q> + GLM_FUNC_DECL mat<2, 2, T, Q> operator*(mat<2, 2, T, Q> const& m1, mat<2, 2, T, Q> const& m2); + + template<typename T, qualifier Q> + GLM_FUNC_DECL mat<3, 2, T, Q> operator*(mat<2, 2, T, Q> const& m1, mat<3, 2, T, Q> const& m2); + + template<typename T, qualifier Q> + GLM_FUNC_DECL mat<4, 2, T, Q> operator*(mat<2, 2, T, Q> const& m1, mat<4, 2, T, Q> const& m2); + + template<typename T, qualifier Q> + GLM_FUNC_DECL mat<2, 2, T, Q> operator/(mat<2, 2, T, Q> const& m, T scalar); + + template<typename T, qualifier Q> + GLM_FUNC_DECL mat<2, 2, T, Q> operator/(T scalar, mat<2, 2, T, Q> const& m); + + template<typename T, qualifier Q> + GLM_FUNC_DECL 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<typename T, qualifier Q> + GLM_FUNC_DECL 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<typename T, qualifier Q> + GLM_FUNC_DECL mat<2, 2, T, Q> operator/(mat<2, 2, T, Q> const& m1, mat<2, 2, T, Q> const& m2); + + // -- Boolean operators -- + + template<typename T, qualifier Q> + GLM_FUNC_DECL bool operator==(mat<2, 2, T, Q> const& m1, mat<2, 2, T, Q> const& m2); + + template<typename T, qualifier Q> + GLM_FUNC_DECL 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 0000000000000000000000000000000000000000..fe5d1aa313339cc82bb2992ce9237761de8dd667 --- /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_FUNCTIONS == GLM_DISABLE + template<typename T, qualifier Q> + GLM_FUNC_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<typename T, qualifier Q> + template<qualifier P> + GLM_FUNC_QUALIFIER GLM_CONSTEXPR mat<2, 2, T, Q>::mat(mat<2, 2, T, P> const& m) +# if GLM_HAS_INITIALIZER_LISTS + : value{m[0], m[1]} +# endif + { +# if !GLM_HAS_INITIALIZER_LISTS + this->value[0] = m[0]; + this->value[1] = m[1]; +# endif + } + + template<typename T, qualifier Q> + 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<typename T, qualifier Q> + 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<typename T, qualifier Q> + 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<typename T, qualifier Q> + template<typename X1, typename Y1, typename X2, typename Y2> + 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<T>(x1), value_type(y1)), col_type(static_cast<T>(x2), value_type(y2)) } +# endif + { +# if !GLM_HAS_INITIALIZER_LISTS + this->value[0] = col_type(static_cast<T>(x1), value_type(y1)); + this->value[1] = col_type(static_cast<T>(x2), value_type(y2)); +# endif + } + + template<typename T, qualifier Q> + template<typename V1, typename V2> + 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<typename T, qualifier Q> + template<typename U, qualifier P> + 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<typename T, qualifier Q> + 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<typename T, qualifier Q> + 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<typename T, qualifier Q> + 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<typename T, qualifier Q> + 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<typename T, qualifier Q> + 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<typename T, qualifier Q> + 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<typename T, qualifier Q> + 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<typename T, qualifier Q> + 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<typename T, qualifier Q> + GLM_FUNC_QUALIFIER typename mat<2, 2, T, Q>::col_type& mat<2, 2, T, Q>::operator[](typename mat<2, 2, T, Q>::length_type i) + { + assert(i < this->length()); + return this->value[i]; + } + + template<typename T, qualifier Q> + 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 + { + assert(i < this->length()); + return this->value[i]; + } + + // -- Unary updatable operators -- + + template<typename T, qualifier Q> + template<typename U> + GLM_FUNC_QUALIFIER 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<typename T, qualifier Q> + template<typename U> + GLM_FUNC_QUALIFIER mat<2, 2, T, Q>& mat<2, 2, T, Q>::operator+=(U scalar) + { + this->value[0] += scalar; + this->value[1] += scalar; + return *this; + } + + template<typename T, qualifier Q> + template<typename U> + GLM_FUNC_QUALIFIER 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<typename T, qualifier Q> + template<typename U> + GLM_FUNC_QUALIFIER mat<2, 2, T, Q>& mat<2, 2, T, Q>::operator-=(U scalar) + { + this->value[0] -= scalar; + this->value[1] -= scalar; + return *this; + } + + template<typename T, qualifier Q> + template<typename U> + GLM_FUNC_QUALIFIER 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<typename T, qualifier Q> + template<typename U> + GLM_FUNC_QUALIFIER mat<2, 2, T, Q>& mat<2, 2, T, Q>::operator*=(U scalar) + { + this->value[0] *= scalar; + this->value[1] *= scalar; + return *this; + } + + template<typename T, qualifier Q> + template<typename U> + GLM_FUNC_QUALIFIER mat<2, 2, T, Q>& mat<2, 2, T, Q>::operator*=(mat<2, 2, U, Q> const& m) + { + return (*this = *this * m); + } + + template<typename T, qualifier Q> + template<typename U> + GLM_FUNC_QUALIFIER mat<2, 2, T, Q>& mat<2, 2, T, Q>::operator/=(U scalar) + { + this->value[0] /= scalar; + this->value[1] /= scalar; + return *this; + } + + template<typename T, qualifier Q> + template<typename U> + GLM_FUNC_QUALIFIER 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<typename T, qualifier Q> + GLM_FUNC_QUALIFIER mat<2, 2, T, Q>& mat<2, 2, T, Q>::operator++() + { + ++this->value[0]; + ++this->value[1]; + return *this; + } + + template<typename T, qualifier Q> + GLM_FUNC_QUALIFIER mat<2, 2, T, Q>& mat<2, 2, T, Q>::operator--() + { + --this->value[0]; + --this->value[1]; + return *this; + } + + template<typename T, qualifier Q> + GLM_FUNC_QUALIFIER mat<2, 2, T, Q> mat<2, 2, T, Q>::operator++(int) + { + mat<2, 2, T, Q> Result(*this); + ++*this; + return Result; + } + + template<typename T, qualifier Q> + GLM_FUNC_QUALIFIER 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<typename T, qualifier Q> + GLM_FUNC_QUALIFIER mat<2, 2, T, Q> operator+(mat<2, 2, T, Q> const& m) + { + return m; + } + + template<typename T, qualifier Q> + GLM_FUNC_QUALIFIER 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<typename T, qualifier Q> + GLM_FUNC_QUALIFIER 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<typename T, qualifier Q> + GLM_FUNC_QUALIFIER 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<typename T, qualifier Q> + GLM_FUNC_QUALIFIER 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<typename T, qualifier Q> + GLM_FUNC_QUALIFIER 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<typename T, qualifier Q> + GLM_FUNC_QUALIFIER 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<typename T, qualifier Q> + GLM_FUNC_QUALIFIER 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<typename T, qualifier Q> + GLM_FUNC_QUALIFIER 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<typename T, qualifier Q> + GLM_FUNC_QUALIFIER 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<typename T, qualifier Q> + GLM_FUNC_QUALIFIER 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<typename T, qualifier Q> + GLM_FUNC_QUALIFIER 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<typename T, qualifier Q> + GLM_FUNC_QUALIFIER 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<typename T, qualifier Q> + GLM_FUNC_QUALIFIER 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<typename T, qualifier Q> + GLM_FUNC_QUALIFIER 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<typename T, qualifier Q> + GLM_FUNC_QUALIFIER 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<typename T, qualifier Q> + GLM_FUNC_QUALIFIER 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<typename T, qualifier Q> + GLM_FUNC_QUALIFIER 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<typename T, qualifier Q> + GLM_FUNC_QUALIFIER 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<typename T, qualifier Q> + GLM_FUNC_QUALIFIER 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<typename T, qualifier Q> + GLM_FUNC_QUALIFIER 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<typename T, qualifier Q> + GLM_FUNC_QUALIFIER 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 0000000000000000000000000000000000000000..d6596e469b8445cafd61b8b19971a60ef3b82ee8 --- /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 <limits> +#include <cstddef> + +namespace glm +{ + template<typename T, qualifier Q> + 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 col_type & operator[](length_type i); + GLM_FUNC_DECL GLM_CONSTEXPR col_type const& operator[](length_type i) const; + + // -- Constructors -- + + GLM_FUNC_DECL GLM_CONSTEXPR mat() GLM_DEFAULT; + template<qualifier P> + GLM_FUNC_DECL GLM_CONSTEXPR mat(mat<2, 3, T, P> const& m); + + GLM_FUNC_DECL explicit GLM_CONSTEXPR mat(T scalar); + GLM_FUNC_DECL GLM_CONSTEXPR mat( + T x0, T y0, T z0, + T x1, T y1, T z1); + GLM_FUNC_DECL GLM_CONSTEXPR mat( + col_type const& v0, + col_type const& v1); + + // -- Conversions -- + + template<typename X1, typename Y1, typename Z1, typename X2, typename Y2, typename Z2> + GLM_FUNC_DECL GLM_CONSTEXPR mat( + X1 x1, Y1 y1, Z1 z1, + X2 x2, Y2 y2, Z2 z2); + + template<typename U, typename V> + GLM_FUNC_DECL GLM_CONSTEXPR mat( + vec<3, U, Q> const& v1, + vec<3, V, Q> const& v2); + + // -- Matrix conversions -- + + template<typename U, qualifier P> + GLM_FUNC_DECL GLM_EXPLICIT GLM_CONSTEXPR mat(mat<2, 3, U, P> const& m); + + GLM_FUNC_DECL GLM_EXPLICIT GLM_CONSTEXPR mat(mat<2, 2, T, Q> const& x); + GLM_FUNC_DECL GLM_EXPLICIT GLM_CONSTEXPR mat(mat<3, 3, T, Q> const& x); + GLM_FUNC_DECL GLM_EXPLICIT GLM_CONSTEXPR mat(mat<4, 4, T, Q> const& x); + GLM_FUNC_DECL GLM_EXPLICIT GLM_CONSTEXPR mat(mat<2, 4, T, Q> const& x); + GLM_FUNC_DECL GLM_EXPLICIT GLM_CONSTEXPR mat(mat<3, 2, T, Q> const& x); + GLM_FUNC_DECL GLM_EXPLICIT GLM_CONSTEXPR mat(mat<3, 4, T, Q> const& x); + GLM_FUNC_DECL GLM_EXPLICIT GLM_CONSTEXPR mat(mat<4, 2, T, Q> const& x); + GLM_FUNC_DECL GLM_EXPLICIT GLM_CONSTEXPR mat(mat<4, 3, T, Q> const& x); + + // -- Unary arithmetic operators -- + + template<typename U> + GLM_FUNC_DECL mat<2, 3, T, Q> & operator=(mat<2, 3, U, Q> const& m); + template<typename U> + GLM_FUNC_DECL mat<2, 3, T, Q> & operator+=(U s); + template<typename U> + GLM_FUNC_DECL mat<2, 3, T, Q> & operator+=(mat<2, 3, U, Q> const& m); + template<typename U> + GLM_FUNC_DECL mat<2, 3, T, Q> & operator-=(U s); + template<typename U> + GLM_FUNC_DECL mat<2, 3, T, Q> & operator-=(mat<2, 3, U, Q> const& m); + template<typename U> + GLM_FUNC_DECL mat<2, 3, T, Q> & operator*=(U s); + template<typename U> + GLM_FUNC_DECL mat<2, 3, T, Q> & operator/=(U s); + + // -- Increment and decrement operators -- + + GLM_FUNC_DECL mat<2, 3, T, Q> & operator++ (); + GLM_FUNC_DECL mat<2, 3, T, Q> & operator-- (); + GLM_FUNC_DECL mat<2, 3, T, Q> operator++(int); + GLM_FUNC_DECL mat<2, 3, T, Q> operator--(int); + }; + + // -- Unary operators -- + + template<typename T, qualifier Q> + GLM_FUNC_DECL mat<2, 3, T, Q> operator+(mat<2, 3, T, Q> const& m); + + template<typename T, qualifier Q> + GLM_FUNC_DECL mat<2, 3, T, Q> operator-(mat<2, 3, T, Q> const& m); + + // -- Binary operators -- + + template<typename T, qualifier Q> + GLM_FUNC_DECL mat<2, 3, T, Q> operator+(mat<2, 3, T, Q> const& m, T scalar); + + template<typename T, qualifier Q> + GLM_FUNC_DECL mat<2, 3, T, Q> operator+(mat<2, 3, T, Q> const& m1, mat<2, 3, T, Q> const& m2); + + template<typename T, qualifier Q> + GLM_FUNC_DECL mat<2, 3, T, Q> operator-(mat<2, 3, T, Q> const& m, T scalar); + + template<typename T, qualifier Q> + GLM_FUNC_DECL mat<2, 3, T, Q> operator-(mat<2, 3, T, Q> const& m1, mat<2, 3, T, Q> const& m2); + + template<typename T, qualifier Q> + GLM_FUNC_DECL mat<2, 3, T, Q> operator*(mat<2, 3, T, Q> const& m, T scalar); + + template<typename T, qualifier Q> + GLM_FUNC_DECL mat<2, 3, T, Q> operator*(T scalar, mat<2, 3, T, Q> const& m); + + template<typename T, qualifier Q> + GLM_FUNC_DECL 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<typename T, qualifier Q> + GLM_FUNC_DECL 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<typename T, qualifier Q> + GLM_FUNC_DECL mat<2, 3, T, Q> operator*(mat<2, 3, T, Q> const& m1, mat<2, 2, T, Q> const& m2); + + template<typename T, qualifier Q> + GLM_FUNC_DECL mat<3, 3, T, Q> operator*(mat<2, 3, T, Q> const& m1, mat<3, 2, T, Q> const& m2); + + template<typename T, qualifier Q> + GLM_FUNC_DECL mat<4, 3, T, Q> operator*(mat<2, 3, T, Q> const& m1, mat<4, 2, T, Q> const& m2); + + template<typename T, qualifier Q> + GLM_FUNC_DECL mat<2, 3, T, Q> operator/(mat<2, 3, T, Q> const& m, T scalar); + + template<typename T, qualifier Q> + GLM_FUNC_DECL mat<2, 3, T, Q> operator/(T scalar, mat<2, 3, T, Q> const& m); + + // -- Boolean operators -- + + template<typename T, qualifier Q> + GLM_FUNC_DECL bool operator==(mat<2, 3, T, Q> const& m1, mat<2, 3, T, Q> const& m2); + + template<typename T, qualifier Q> + GLM_FUNC_DECL 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 0000000000000000000000000000000000000000..5fec17e5dbbc7b021628543715bda2a8e6bc70f3 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/detail/type_mat2x3.inl @@ -0,0 +1,510 @@ +namespace glm +{ + // -- Constructors -- + +# if GLM_CONFIG_DEFAULTED_FUNCTIONS == GLM_DISABLE + template<typename T, qualifier Q> + GLM_FUNC_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<typename T, qualifier Q> + template<qualifier P> + GLM_FUNC_QUALIFIER GLM_CONSTEXPR mat<2, 3, T, Q>::mat(mat<2, 3, T, P> const& m) +# if GLM_HAS_INITIALIZER_LISTS + : value{m.value[0], m.value[1]} +# endif + { +# if !GLM_HAS_INITIALIZER_LISTS + this->value[0] = m.value[0]; + this->value[1] = m.value[1]; +# endif + } + + template<typename T, qualifier Q> + 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<typename T, qualifier Q> + 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<typename T, qualifier Q> + 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<typename T, qualifier Q> + 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<typename T, qualifier Q> + template<typename V1, typename V2> + 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<typename T, qualifier Q> + template<typename U, qualifier P> + 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<typename T, qualifier Q> + 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<typename T, qualifier Q> + 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<typename T, qualifier Q> + 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<typename T, qualifier Q> + 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<typename T, qualifier Q> + 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<typename T, qualifier Q> + 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<typename T, qualifier Q> + 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<typename T, qualifier Q> + 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<typename T, qualifier Q> + GLM_FUNC_QUALIFIER typename mat<2, 3, T, Q>::col_type & mat<2, 3, T, Q>::operator[](typename mat<2, 3, T, Q>::length_type i) + { + assert(i < this->length()); + return this->value[i]; + } + + template<typename T, qualifier Q> + 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 + { + assert(i < this->length()); + return this->value[i]; + } + + // -- Unary updatable operators -- + + template<typename T, qualifier Q> + template<typename U> + GLM_FUNC_QUALIFIER 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<typename T, qualifier Q> + template<typename U> + GLM_FUNC_QUALIFIER mat<2, 3, T, Q> & mat<2, 3, T, Q>::operator+=(U s) + { + this->value[0] += s; + this->value[1] += s; + return *this; + } + + template<typename T, qualifier Q> + template<typename U> + GLM_FUNC_QUALIFIER 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<typename T, qualifier Q> + template<typename U> + GLM_FUNC_QUALIFIER mat<2, 3, T, Q>& mat<2, 3, T, Q>::operator-=(U s) + { + this->value[0] -= s; + this->value[1] -= s; + return *this; + } + + template<typename T, qualifier Q> + template<typename U> + GLM_FUNC_QUALIFIER 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<typename T, qualifier Q> + template<typename U> + GLM_FUNC_QUALIFIER mat<2, 3, T, Q>& mat<2, 3, T, Q>::operator*=(U s) + { + this->value[0] *= s; + this->value[1] *= s; + return *this; + } + + template<typename T, qualifier Q> + template<typename U> + GLM_FUNC_QUALIFIER 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<typename T, qualifier Q> + GLM_FUNC_QUALIFIER mat<2, 3, T, Q> & mat<2, 3, T, Q>::operator++() + { + ++this->value[0]; + ++this->value[1]; + return *this; + } + + template<typename T, qualifier Q> + GLM_FUNC_QUALIFIER mat<2, 3, T, Q> & mat<2, 3, T, Q>::operator--() + { + --this->value[0]; + --this->value[1]; + return *this; + } + + template<typename T, qualifier Q> + GLM_FUNC_QUALIFIER mat<2, 3, T, Q> mat<2, 3, T, Q>::operator++(int) + { + mat<2, 3, T, Q> Result(*this); + ++*this; + return Result; + } + + template<typename T, qualifier Q> + GLM_FUNC_QUALIFIER 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<typename T, qualifier Q> + GLM_FUNC_QUALIFIER mat<2, 3, T, Q> operator+(mat<2, 3, T, Q> const& m) + { + return m; + } + + template<typename T, qualifier Q> + GLM_FUNC_QUALIFIER 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<typename T, qualifier Q> + GLM_FUNC_QUALIFIER 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<typename T, qualifier Q> + GLM_FUNC_QUALIFIER 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<typename T, qualifier Q> + GLM_FUNC_QUALIFIER 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<typename T, qualifier Q> + GLM_FUNC_QUALIFIER 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<typename T, qualifier Q> + GLM_FUNC_QUALIFIER 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<typename T, qualifier Q> + GLM_FUNC_QUALIFIER 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<typename T, qualifier Q> + GLM_FUNC_QUALIFIER 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<typename T, qualifier Q> + GLM_FUNC_QUALIFIER 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<typename T, qualifier Q> + GLM_FUNC_QUALIFIER 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<typename T, qualifier Q> + GLM_FUNC_QUALIFIER 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<typename T, qualifier Q> + GLM_FUNC_QUALIFIER 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<typename T, qualifier Q> + GLM_FUNC_QUALIFIER 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<typename T, qualifier Q> + GLM_FUNC_QUALIFIER 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<typename T, qualifier Q> + GLM_FUNC_QUALIFIER 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<typename T, qualifier Q> + GLM_FUNC_QUALIFIER 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 0000000000000000000000000000000000000000..ff03e215e5e4da0d190c514461fd57c902643bbf --- /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 <limits> +#include <cstddef> + +namespace glm +{ + template<typename T, qualifier Q> + 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 col_type & operator[](length_type i); + GLM_FUNC_DECL GLM_CONSTEXPR col_type const& operator[](length_type i) const; + + // -- Constructors -- + + GLM_FUNC_DECL GLM_CONSTEXPR mat() GLM_DEFAULT; + template<qualifier P> + GLM_FUNC_DECL GLM_CONSTEXPR mat(mat<2, 4, T, P> const& m); + + GLM_FUNC_DECL explicit GLM_CONSTEXPR mat(T scalar); + GLM_FUNC_DECL GLM_CONSTEXPR mat( + T x0, T y0, T z0, T w0, + T x1, T y1, T z1, T w1); + GLM_FUNC_DECL GLM_CONSTEXPR 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_FUNC_DECL GLM_CONSTEXPR mat( + X1 x1, Y1 y1, Z1 z1, W1 w1, + X2 x2, Y2 y2, Z2 z2, W2 w2); + + template<typename U, typename V> + GLM_FUNC_DECL GLM_CONSTEXPR mat( + vec<4, U, Q> const& v1, + vec<4, V, Q> const& v2); + + // -- Matrix conversions -- + + template<typename U, qualifier P> + GLM_FUNC_DECL GLM_EXPLICIT GLM_CONSTEXPR mat(mat<2, 4, U, P> const& m); + + GLM_FUNC_DECL GLM_EXPLICIT GLM_CONSTEXPR mat(mat<2, 2, T, Q> const& x); + GLM_FUNC_DECL GLM_EXPLICIT GLM_CONSTEXPR mat(mat<3, 3, T, Q> const& x); + GLM_FUNC_DECL GLM_EXPLICIT GLM_CONSTEXPR mat(mat<4, 4, T, Q> const& x); + GLM_FUNC_DECL GLM_EXPLICIT GLM_CONSTEXPR mat(mat<2, 3, T, Q> const& x); + GLM_FUNC_DECL GLM_EXPLICIT GLM_CONSTEXPR mat(mat<3, 2, T, Q> const& x); + GLM_FUNC_DECL GLM_EXPLICIT GLM_CONSTEXPR mat(mat<3, 4, T, Q> const& x); + GLM_FUNC_DECL GLM_EXPLICIT GLM_CONSTEXPR mat(mat<4, 2, T, Q> const& x); + GLM_FUNC_DECL GLM_EXPLICIT GLM_CONSTEXPR mat(mat<4, 3, T, Q> const& x); + + // -- Unary arithmetic operators -- + + template<typename U> + GLM_FUNC_DECL mat<2, 4, T, Q> & operator=(mat<2, 4, U, Q> const& m); + template<typename U> + GLM_FUNC_DECL mat<2, 4, T, Q> & operator+=(U s); + template<typename U> + GLM_FUNC_DECL mat<2, 4, T, Q> & operator+=(mat<2, 4, U, Q> const& m); + template<typename U> + GLM_FUNC_DECL mat<2, 4, T, Q> & operator-=(U s); + template<typename U> + GLM_FUNC_DECL mat<2, 4, T, Q> & operator-=(mat<2, 4, U, Q> const& m); + template<typename U> + GLM_FUNC_DECL mat<2, 4, T, Q> & operator*=(U s); + template<typename U> + GLM_FUNC_DECL mat<2, 4, T, Q> & operator/=(U s); + + // -- Increment and decrement operators -- + + GLM_FUNC_DECL mat<2, 4, T, Q> & operator++ (); + GLM_FUNC_DECL mat<2, 4, T, Q> & operator-- (); + GLM_FUNC_DECL mat<2, 4, T, Q> operator++(int); + GLM_FUNC_DECL mat<2, 4, T, Q> operator--(int); + }; + + // -- Unary operators -- + + template<typename T, qualifier Q> + GLM_FUNC_DECL mat<2, 4, T, Q> operator+(mat<2, 4, T, Q> const& m); + + template<typename T, qualifier Q> + GLM_FUNC_DECL mat<2, 4, T, Q> operator-(mat<2, 4, T, Q> const& m); + + // -- Binary operators -- + + template<typename T, qualifier Q> + GLM_FUNC_DECL mat<2, 4, T, Q> operator+(mat<2, 4, T, Q> const& m, T scalar); + + template<typename T, qualifier Q> + GLM_FUNC_DECL mat<2, 4, T, Q> operator+(mat<2, 4, T, Q> const& m1, mat<2, 4, T, Q> const& m2); + + template<typename T, qualifier Q> + GLM_FUNC_DECL mat<2, 4, T, Q> operator-(mat<2, 4, T, Q> const& m, T scalar); + + template<typename T, qualifier Q> + GLM_FUNC_DECL mat<2, 4, T, Q> operator-(mat<2, 4, T, Q> const& m1, mat<2, 4, T, Q> const& m2); + + template<typename T, qualifier Q> + GLM_FUNC_DECL mat<2, 4, T, Q> operator*(mat<2, 4, T, Q> const& m, T scalar); + + template<typename T, qualifier Q> + GLM_FUNC_DECL mat<2, 4, T, Q> operator*(T scalar, mat<2, 4, T, Q> const& m); + + template<typename T, qualifier Q> + GLM_FUNC_DECL 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<typename T, qualifier Q> + GLM_FUNC_DECL 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<typename T, qualifier Q> + GLM_FUNC_DECL mat<4, 4, T, Q> operator*(mat<2, 4, T, Q> const& m1, mat<4, 2, T, Q> const& m2); + + template<typename T, qualifier Q> + GLM_FUNC_DECL mat<2, 4, T, Q> operator*(mat<2, 4, T, Q> const& m1, mat<2, 2, T, Q> const& m2); + + template<typename T, qualifier Q> + GLM_FUNC_DECL mat<3, 4, T, Q> operator*(mat<2, 4, T, Q> const& m1, mat<3, 2, T, Q> const& m2); + + template<typename T, qualifier Q> + GLM_FUNC_DECL mat<2, 4, T, Q> operator/(mat<2, 4, T, Q> const& m, T scalar); + + template<typename T, qualifier Q> + GLM_FUNC_DECL mat<2, 4, T, Q> operator/(T scalar, mat<2, 4, T, Q> const& m); + + // -- Boolean operators -- + + template<typename T, qualifier Q> + GLM_FUNC_DECL bool operator==(mat<2, 4, T, Q> const& m1, mat<2, 4, T, Q> const& m2); + + template<typename T, qualifier Q> + GLM_FUNC_DECL 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 0000000000000000000000000000000000000000..b6d2b9ddfd13e42f12fa462d7be77b32aa2d8e8a --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/detail/type_mat2x4.inl @@ -0,0 +1,520 @@ +namespace glm +{ + // -- Constructors -- + +# if GLM_CONFIG_DEFAULTED_FUNCTIONS == GLM_DISABLE + template<typename T, qualifier Q> + GLM_FUNC_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<typename T, qualifier Q> + template<qualifier P> + GLM_FUNC_QUALIFIER GLM_CONSTEXPR mat<2, 4, T, Q>::mat(mat<2, 4, T, P> const& m) +# if GLM_HAS_INITIALIZER_LISTS + : value{m[0], m[1]} +# endif + { +# if !GLM_HAS_INITIALIZER_LISTS + this->value[0] = m[0]; + this->value[1] = m[1]; +# endif + } + + template<typename T, qualifier Q> + 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<typename T, qualifier Q> + 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<typename T, qualifier Q> + 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<typename T, qualifier Q> + 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<typename T, qualifier Q> + template<typename V1, typename V2> + 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<typename T, qualifier Q> + template<typename U, qualifier P> + 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<typename T, qualifier Q> + 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<typename T, qualifier Q> + 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<typename T, qualifier Q> + 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<typename T, qualifier Q> + 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<typename T, qualifier Q> + 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<typename T, qualifier Q> + 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<typename T, qualifier Q> + 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<typename T, qualifier Q> + 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<typename T, qualifier Q> + GLM_FUNC_QUALIFIER typename mat<2, 4, T, Q>::col_type & mat<2, 4, T, Q>::operator[](typename mat<2, 4, T, Q>::length_type i) + { + assert(i < this->length()); + return this->value[i]; + } + + template<typename T, qualifier Q> + 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 + { + assert(i < this->length()); + return this->value[i]; + } + + // -- Unary updatable operators -- + + template<typename T, qualifier Q> + template<typename U> + GLM_FUNC_QUALIFIER 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<typename T, qualifier Q> + template<typename U> + GLM_FUNC_QUALIFIER mat<2, 4, T, Q>& mat<2, 4, T, Q>::operator+=(U s) + { + this->value[0] += s; + this->value[1] += s; + return *this; + } + + template<typename T, qualifier Q> + template<typename U> + GLM_FUNC_QUALIFIER 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<typename T, qualifier Q> + template<typename U> + GLM_FUNC_QUALIFIER mat<2, 4, T, Q>& mat<2, 4, T, Q>::operator-=(U s) + { + this->value[0] -= s; + this->value[1] -= s; + return *this; + } + + template<typename T, qualifier Q> + template<typename U> + GLM_FUNC_QUALIFIER 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<typename T, qualifier Q> + template<typename U> + GLM_FUNC_QUALIFIER mat<2, 4, T, Q>& mat<2, 4, T, Q>::operator*=(U s) + { + this->value[0] *= s; + this->value[1] *= s; + return *this; + } + + template<typename T, qualifier Q> + template<typename U> + GLM_FUNC_QUALIFIER 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<typename T, qualifier Q> + GLM_FUNC_QUALIFIER mat<2, 4, T, Q>& mat<2, 4, T, Q>::operator++() + { + ++this->value[0]; + ++this->value[1]; + return *this; + } + + template<typename T, qualifier Q> + GLM_FUNC_QUALIFIER mat<2, 4, T, Q>& mat<2, 4, T, Q>::operator--() + { + --this->value[0]; + --this->value[1]; + return *this; + } + + template<typename T, qualifier Q> + GLM_FUNC_QUALIFIER mat<2, 4, T, Q> mat<2, 4, T, Q>::operator++(int) + { + mat<2, 4, T, Q> Result(*this); + ++*this; + return Result; + } + + template<typename T, qualifier Q> + GLM_FUNC_QUALIFIER 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<typename T, qualifier Q> + GLM_FUNC_QUALIFIER mat<2, 4, T, Q> operator+(mat<2, 4, T, Q> const& m) + { + return m; + } + + template<typename T, qualifier Q> + GLM_FUNC_QUALIFIER 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<typename T, qualifier Q> + GLM_FUNC_QUALIFIER 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<typename T, qualifier Q> + GLM_FUNC_QUALIFIER 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<typename T, qualifier Q> + GLM_FUNC_QUALIFIER 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<typename T, qualifier Q> + GLM_FUNC_QUALIFIER 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<typename T, qualifier Q> + GLM_FUNC_QUALIFIER 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<typename T, qualifier Q> + GLM_FUNC_QUALIFIER 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<typename T, qualifier Q> + GLM_FUNC_QUALIFIER 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<typename T, qualifier Q> + GLM_FUNC_QUALIFIER 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<typename T, qualifier Q> + GLM_FUNC_QUALIFIER 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<typename T, qualifier Q> + GLM_FUNC_QUALIFIER 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<typename T, qualifier Q> + GLM_FUNC_QUALIFIER 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<typename T, qualifier Q> + GLM_FUNC_QUALIFIER 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<typename T, qualifier Q> + GLM_FUNC_QUALIFIER 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<typename T, qualifier Q> + GLM_FUNC_QUALIFIER 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<typename T, qualifier Q> + GLM_FUNC_QUALIFIER 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 0000000000000000000000000000000000000000..e16658131fd6400fde34299313a9ac92c2db4f7f --- /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 <limits> +#include <cstddef> + +namespace glm +{ + template<typename T, qualifier Q> + 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 col_type & operator[](length_type i); + GLM_FUNC_DECL GLM_CONSTEXPR col_type const& operator[](length_type i) const; + + // -- Constructors -- + + GLM_FUNC_DECL GLM_CONSTEXPR mat() GLM_DEFAULT; + template<qualifier P> + GLM_FUNC_DECL GLM_CONSTEXPR mat(mat<3, 2, T, P> const& m); + + GLM_FUNC_DECL explicit GLM_CONSTEXPR mat(T scalar); + GLM_FUNC_DECL GLM_CONSTEXPR mat( + T x0, T y0, + T x1, T y1, + T x2, T y2); + GLM_FUNC_DECL GLM_CONSTEXPR 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_FUNC_DECL GLM_CONSTEXPR mat( + X1 x1, Y1 y1, + X2 x2, Y2 y2, + X3 x3, Y3 y3); + + template<typename V1, typename V2, typename V3> + GLM_FUNC_DECL GLM_CONSTEXPR mat( + vec<2, V1, Q> const& v1, + vec<2, V2, Q> const& v2, + vec<2, V3, Q> const& v3); + + // -- Matrix conversions -- + + template<typename U, qualifier P> + GLM_FUNC_DECL GLM_EXPLICIT GLM_CONSTEXPR mat(mat<3, 2, U, P> const& m); + + GLM_FUNC_DECL GLM_EXPLICIT GLM_CONSTEXPR mat(mat<2, 2, T, Q> const& x); + GLM_FUNC_DECL GLM_EXPLICIT GLM_CONSTEXPR mat(mat<3, 3, T, Q> const& x); + GLM_FUNC_DECL GLM_EXPLICIT GLM_CONSTEXPR mat(mat<4, 4, T, Q> const& x); + GLM_FUNC_DECL GLM_EXPLICIT GLM_CONSTEXPR mat(mat<2, 3, T, Q> const& x); + GLM_FUNC_DECL GLM_EXPLICIT GLM_CONSTEXPR mat(mat<2, 4, T, Q> const& x); + GLM_FUNC_DECL GLM_EXPLICIT GLM_CONSTEXPR mat(mat<3, 4, T, Q> const& x); + GLM_FUNC_DECL GLM_EXPLICIT GLM_CONSTEXPR mat(mat<4, 2, T, Q> const& x); + GLM_FUNC_DECL GLM_EXPLICIT GLM_CONSTEXPR mat(mat<4, 3, T, Q> const& x); + + // -- Unary arithmetic operators -- + + template<typename U> + GLM_FUNC_DECL mat<3, 2, T, Q> & operator=(mat<3, 2, U, Q> const& m); + template<typename U> + GLM_FUNC_DECL mat<3, 2, T, Q> & operator+=(U s); + template<typename U> + GLM_FUNC_DECL mat<3, 2, T, Q> & operator+=(mat<3, 2, U, Q> const& m); + template<typename U> + GLM_FUNC_DECL mat<3, 2, T, Q> & operator-=(U s); + template<typename U> + GLM_FUNC_DECL mat<3, 2, T, Q> & operator-=(mat<3, 2, U, Q> const& m); + template<typename U> + GLM_FUNC_DECL mat<3, 2, T, Q> & operator*=(U s); + template<typename U> + GLM_FUNC_DECL mat<3, 2, T, Q> & operator/=(U s); + + // -- Increment and decrement operators -- + + GLM_FUNC_DECL mat<3, 2, T, Q> & operator++ (); + GLM_FUNC_DECL mat<3, 2, T, Q> & operator-- (); + GLM_FUNC_DECL mat<3, 2, T, Q> operator++(int); + GLM_FUNC_DECL mat<3, 2, T, Q> operator--(int); + }; + + // -- Unary operators -- + + template<typename T, qualifier Q> + GLM_FUNC_DECL mat<3, 2, T, Q> operator+(mat<3, 2, T, Q> const& m); + + template<typename T, qualifier Q> + GLM_FUNC_DECL mat<3, 2, T, Q> operator-(mat<3, 2, T, Q> const& m); + + // -- Binary operators -- + + template<typename T, qualifier Q> + GLM_FUNC_DECL mat<3, 2, T, Q> operator+(mat<3, 2, T, Q> const& m, T scalar); + + template<typename T, qualifier Q> + GLM_FUNC_DECL mat<3, 2, T, Q> operator+(mat<3, 2, T, Q> const& m1, mat<3, 2, T, Q> const& m2); + + template<typename T, qualifier Q> + GLM_FUNC_DECL mat<3, 2, T, Q> operator-(mat<3, 2, T, Q> const& m, T scalar); + + template<typename T, qualifier Q> + GLM_FUNC_DECL mat<3, 2, T, Q> operator-(mat<3, 2, T, Q> const& m1, mat<3, 2, T, Q> const& m2); + + template<typename T, qualifier Q> + GLM_FUNC_DECL mat<3, 2, T, Q> operator*(mat<3, 2, T, Q> const& m, T scalar); + + template<typename T, qualifier Q> + GLM_FUNC_DECL mat<3, 2, T, Q> operator*(T scalar, mat<3, 2, T, Q> const& m); + + template<typename T, qualifier Q> + GLM_FUNC_DECL 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<typename T, qualifier Q> + GLM_FUNC_DECL 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<typename T, qualifier Q> + GLM_FUNC_DECL mat<2, 2, T, Q> operator*(mat<3, 2, T, Q> const& m1, mat<2, 3, T, Q> const& m2); + + template<typename T, qualifier Q> + GLM_FUNC_DECL mat<3, 2, T, Q> operator*(mat<3, 2, T, Q> const& m1, mat<3, 3, T, Q> const& m2); + + template<typename T, qualifier Q> + GLM_FUNC_DECL mat<4, 2, T, Q> operator*(mat<3, 2, T, Q> const& m1, mat<4, 3, T, Q> const& m2); + + template<typename T, qualifier Q> + GLM_FUNC_DECL mat<3, 2, T, Q> operator/(mat<3, 2, T, Q> const& m, T scalar); + + template<typename T, qualifier Q> + GLM_FUNC_DECL mat<3, 2, T, Q> operator/(T scalar, mat<3, 2, T, Q> const& m); + + // -- Boolean operators -- + + template<typename T, qualifier Q> + GLM_FUNC_DECL bool operator==(mat<3, 2, T, Q> const& m1, mat<3, 2, T, Q> const& m2); + + template<typename T, qualifier Q> + GLM_FUNC_DECL 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 0000000000000000000000000000000000000000..b4b948b72613eb48253a5e5543ac977ab90d44da --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/detail/type_mat3x2.inl @@ -0,0 +1,532 @@ +namespace glm +{ + // -- Constructors -- + +# if GLM_CONFIG_DEFAULTED_FUNCTIONS == GLM_DISABLE + template<typename T, qualifier Q> + GLM_FUNC_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<typename T, qualifier Q> + template<qualifier P> + 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<typename T, qualifier Q> + 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<typename T, qualifier Q> + 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<typename T, qualifier Q> + 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<typename T, qualifier Q> + 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<typename T, qualifier Q> + template<typename V0, typename V1, typename V2> + 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<typename T, qualifier Q> + template<typename U, qualifier P> + 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<typename T, qualifier Q> + 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<typename T, qualifier Q> + 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<typename T, qualifier Q> + 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<typename T, qualifier Q> + 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<typename T, qualifier Q> + 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<typename T, qualifier Q> + 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<typename T, qualifier Q> + 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<typename T, qualifier Q> + 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<typename T, qualifier Q> + GLM_FUNC_QUALIFIER typename mat<3, 2, T, Q>::col_type & mat<3, 2, T, Q>::operator[](typename mat<3, 2, T, Q>::length_type i) + { + assert(i < this->length()); + return this->value[i]; + } + + template<typename T, qualifier Q> + 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 + { + assert(i < this->length()); + return this->value[i]; + } + + // -- Unary updatable operators -- + + template<typename T, qualifier Q> + template<typename U> + GLM_FUNC_QUALIFIER 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<typename T, qualifier Q> + template<typename U> + GLM_FUNC_QUALIFIER 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<typename T, qualifier Q> + template<typename U> + GLM_FUNC_QUALIFIER 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<typename T, qualifier Q> + template<typename U> + GLM_FUNC_QUALIFIER 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<typename T, qualifier Q> + template<typename U> + GLM_FUNC_QUALIFIER 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<typename T, qualifier Q> + template<typename U> + GLM_FUNC_QUALIFIER 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<typename T, qualifier Q> + template<typename U> + GLM_FUNC_QUALIFIER 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<typename T, qualifier Q> + GLM_FUNC_QUALIFIER mat<3, 2, T, Q>& mat<3, 2, T, Q>::operator++() + { + ++this->value[0]; + ++this->value[1]; + ++this->value[2]; + return *this; + } + + template<typename T, qualifier Q> + GLM_FUNC_QUALIFIER mat<3, 2, T, Q>& mat<3, 2, T, Q>::operator--() + { + --this->value[0]; + --this->value[1]; + --this->value[2]; + return *this; + } + + template<typename T, qualifier Q> + GLM_FUNC_QUALIFIER mat<3, 2, T, Q> mat<3, 2, T, Q>::operator++(int) + { + mat<3, 2, T, Q> Result(*this); + ++*this; + return Result; + } + + template<typename T, qualifier Q> + GLM_FUNC_QUALIFIER 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<typename T, qualifier Q> + GLM_FUNC_QUALIFIER mat<3, 2, T, Q> operator+(mat<3, 2, T, Q> const& m) + { + return m; + } + + template<typename T, qualifier Q> + GLM_FUNC_QUALIFIER 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<typename T, qualifier Q> + GLM_FUNC_QUALIFIER 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<typename T, qualifier Q> + GLM_FUNC_QUALIFIER 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<typename T, qualifier Q> + GLM_FUNC_QUALIFIER 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<typename T, qualifier Q> + GLM_FUNC_QUALIFIER 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<typename T, qualifier Q> + GLM_FUNC_QUALIFIER 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<typename T, qualifier Q> + GLM_FUNC_QUALIFIER 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<typename T, qualifier Q> + GLM_FUNC_QUALIFIER 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<typename T, qualifier Q> + GLM_FUNC_QUALIFIER 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<typename T, qualifier Q> + GLM_FUNC_QUALIFIER 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<typename T, qualifier Q> + GLM_FUNC_QUALIFIER 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<typename T, qualifier Q> + GLM_FUNC_QUALIFIER 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<typename T, qualifier Q> + GLM_FUNC_QUALIFIER 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<typename T, qualifier Q> + GLM_FUNC_QUALIFIER 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<typename T, qualifier Q> + GLM_FUNC_QUALIFIER 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<typename T, qualifier Q> + GLM_FUNC_QUALIFIER 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 0000000000000000000000000000000000000000..3174872eb7c1b93f7a10b5fd0d653a814c1ccf64 --- /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 <limits> +#include <cstddef> + +namespace glm +{ + template<typename T, qualifier Q> + 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 col_type & operator[](length_type i); + GLM_FUNC_DECL GLM_CONSTEXPR col_type const& operator[](length_type i) const; + + // -- Constructors -- + + GLM_FUNC_DECL GLM_CONSTEXPR mat() GLM_DEFAULT; + template<qualifier P> + GLM_FUNC_DECL GLM_CONSTEXPR mat(mat<3, 3, T, P> const& m); + + GLM_FUNC_DECL explicit GLM_CONSTEXPR mat(T scalar); + GLM_FUNC_DECL GLM_CONSTEXPR mat( + T x0, T y0, T z0, + T x1, T y1, T z1, + T x2, T y2, T z2); + GLM_FUNC_DECL GLM_CONSTEXPR 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_FUNC_DECL GLM_CONSTEXPR mat( + X1 x1, Y1 y1, Z1 z1, + X2 x2, Y2 y2, Z2 z2, + X3 x3, Y3 y3, Z3 z3); + + template<typename V1, typename V2, typename V3> + GLM_FUNC_DECL GLM_CONSTEXPR mat( + vec<3, V1, Q> const& v1, + vec<3, V2, Q> const& v2, + vec<3, V3, Q> const& v3); + + // -- Matrix conversions -- + + template<typename U, qualifier P> + GLM_FUNC_DECL GLM_EXPLICIT GLM_CONSTEXPR mat(mat<3, 3, U, P> const& m); + + GLM_FUNC_DECL GLM_EXPLICIT GLM_CONSTEXPR mat(mat<2, 2, T, Q> const& x); + GLM_FUNC_DECL GLM_EXPLICIT GLM_CONSTEXPR mat(mat<4, 4, T, Q> const& x); + GLM_FUNC_DECL GLM_EXPLICIT GLM_CONSTEXPR mat(mat<2, 3, T, Q> const& x); + GLM_FUNC_DECL GLM_EXPLICIT GLM_CONSTEXPR mat(mat<3, 2, T, Q> const& x); + GLM_FUNC_DECL GLM_EXPLICIT GLM_CONSTEXPR mat(mat<2, 4, T, Q> const& x); + GLM_FUNC_DECL GLM_EXPLICIT GLM_CONSTEXPR mat(mat<4, 2, T, Q> const& x); + GLM_FUNC_DECL GLM_EXPLICIT GLM_CONSTEXPR mat(mat<3, 4, T, Q> const& x); + GLM_FUNC_DECL GLM_EXPLICIT GLM_CONSTEXPR mat(mat<4, 3, T, Q> const& x); + + // -- Unary arithmetic operators -- + + template<typename U> + GLM_FUNC_DECL mat<3, 3, T, Q> & operator=(mat<3, 3, U, Q> const& m); + template<typename U> + GLM_FUNC_DECL mat<3, 3, T, Q> & operator+=(U s); + template<typename U> + GLM_FUNC_DECL mat<3, 3, T, Q> & operator+=(mat<3, 3, U, Q> const& m); + template<typename U> + GLM_FUNC_DECL mat<3, 3, T, Q> & operator-=(U s); + template<typename U> + GLM_FUNC_DECL mat<3, 3, T, Q> & operator-=(mat<3, 3, U, Q> const& m); + template<typename U> + GLM_FUNC_DECL mat<3, 3, T, Q> & operator*=(U s); + template<typename U> + GLM_FUNC_DECL mat<3, 3, T, Q> & operator*=(mat<3, 3, U, Q> const& m); + template<typename U> + GLM_FUNC_DECL mat<3, 3, T, Q> & operator/=(U s); + template<typename U> + GLM_FUNC_DECL mat<3, 3, T, Q> & operator/=(mat<3, 3, U, Q> const& m); + + // -- Increment and decrement operators -- + + GLM_FUNC_DECL mat<3, 3, T, Q> & operator++(); + GLM_FUNC_DECL mat<3, 3, T, Q> & operator--(); + GLM_FUNC_DECL mat<3, 3, T, Q> operator++(int); + GLM_FUNC_DECL mat<3, 3, T, Q> operator--(int); + }; + + // -- Unary operators -- + + template<typename T, qualifier Q> + GLM_FUNC_DECL mat<3, 3, T, Q> operator+(mat<3, 3, T, Q> const& m); + + template<typename T, qualifier Q> + GLM_FUNC_DECL mat<3, 3, T, Q> operator-(mat<3, 3, T, Q> const& m); + + // -- Binary operators -- + + template<typename T, qualifier Q> + GLM_FUNC_DECL mat<3, 3, T, Q> operator+(mat<3, 3, T, Q> const& m, T scalar); + + template<typename T, qualifier Q> + GLM_FUNC_DECL mat<3, 3, T, Q> operator+(T scalar, mat<3, 3, T, Q> const& m); + + template<typename T, qualifier Q> + GLM_FUNC_DECL mat<3, 3, T, Q> operator+(mat<3, 3, T, Q> const& m1, mat<3, 3, T, Q> const& m2); + + template<typename T, qualifier Q> + GLM_FUNC_DECL mat<3, 3, T, Q> operator-(mat<3, 3, T, Q> const& m, T scalar); + + template<typename T, qualifier Q> + GLM_FUNC_DECL mat<3, 3, T, Q> operator-(T scalar, mat<3, 3, T, Q> const& m); + + template<typename T, qualifier Q> + GLM_FUNC_DECL mat<3, 3, T, Q> operator-(mat<3, 3, T, Q> const& m1, mat<3, 3, T, Q> const& m2); + + template<typename T, qualifier Q> + GLM_FUNC_DECL mat<3, 3, T, Q> operator*(mat<3, 3, T, Q> const& m, T scalar); + + template<typename T, qualifier Q> + GLM_FUNC_DECL mat<3, 3, T, Q> operator*(T scalar, mat<3, 3, T, Q> const& m); + + template<typename T, qualifier Q> + GLM_FUNC_DECL 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<typename T, qualifier Q> + GLM_FUNC_DECL 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<typename T, qualifier Q> + GLM_FUNC_DECL mat<3, 3, T, Q> operator*(mat<3, 3, T, Q> const& m1, mat<3, 3, T, Q> const& m2); + + template<typename T, qualifier Q> + GLM_FUNC_DECL mat<2, 3, T, Q> operator*(mat<3, 3, T, Q> const& m1, mat<2, 3, T, Q> const& m2); + + template<typename T, qualifier Q> + GLM_FUNC_DECL mat<4, 3, T, Q> operator*(mat<3, 3, T, Q> const& m1, mat<4, 3, T, Q> const& m2); + + template<typename T, qualifier Q> + GLM_FUNC_DECL mat<3, 3, T, Q> operator/(mat<3, 3, T, Q> const& m, T scalar); + + template<typename T, qualifier Q> + GLM_FUNC_DECL mat<3, 3, T, Q> operator/(T scalar, mat<3, 3, T, Q> const& m); + + template<typename T, qualifier Q> + GLM_FUNC_DECL 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<typename T, qualifier Q> + GLM_FUNC_DECL 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<typename T, qualifier Q> + GLM_FUNC_DECL mat<3, 3, T, Q> operator/(mat<3, 3, T, Q> const& m1, mat<3, 3, T, Q> const& m2); + + // -- Boolean operators -- + + template<typename T, qualifier Q> + GLM_FUNC_DECL GLM_CONSTEXPR bool operator==(mat<3, 3, T, Q> const& m1, mat<3, 3, T, Q> const& m2); + + template<typename T, qualifier Q> + GLM_FUNC_DECL 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 0000000000000000000000000000000000000000..1ddaf99d5819c18df1809a046c1b7c87402a0ea4 --- /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_FUNCTIONS == GLM_DISABLE + template<typename T, qualifier Q> + GLM_FUNC_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<typename T, qualifier Q> + template<qualifier P> + 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<typename T, qualifier Q> + 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<typename T, qualifier Q> + 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<typename T, qualifier Q> + 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<typename T, qualifier Q> + 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<typename T, qualifier Q> + template<typename V1, typename V2, typename V3> + 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<typename T, qualifier Q> + template<typename U, qualifier P> + 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<typename T, qualifier Q> + 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<typename T, qualifier Q> + 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<typename T, qualifier Q> + 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<typename T, qualifier Q> + 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<typename T, qualifier Q> + 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<typename T, qualifier Q> + 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<typename T, qualifier Q> + 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<typename T, qualifier Q> + 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<typename T, qualifier Q> + GLM_FUNC_QUALIFIER typename mat<3, 3, T, Q>::col_type & mat<3, 3, T, Q>::operator[](typename mat<3, 3, T, Q>::length_type i) + { + assert(i < this->length()); + return this->value[i]; + } + + template<typename T, qualifier Q> + 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 + { + assert(i < this->length()); + return this->value[i]; + } + + // -- Unary updatable operators -- + + template<typename T, qualifier Q> + template<typename U> + GLM_FUNC_QUALIFIER 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<typename T, qualifier Q> + template<typename U> + GLM_FUNC_QUALIFIER 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<typename T, qualifier Q> + template<typename U> + GLM_FUNC_QUALIFIER 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<typename T, qualifier Q> + template<typename U> + GLM_FUNC_QUALIFIER 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<typename T, qualifier Q> + template<typename U> + GLM_FUNC_QUALIFIER 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<typename T, qualifier Q> + template<typename U> + GLM_FUNC_QUALIFIER 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<typename T, qualifier Q> + template<typename U> + GLM_FUNC_QUALIFIER mat<3, 3, T, Q> & mat<3, 3, T, Q>::operator*=(mat<3, 3, U, Q> const& m) + { + return (*this = *this * m); + } + + template<typename T, qualifier Q> + template<typename U> + GLM_FUNC_QUALIFIER 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<typename T, qualifier Q> + template<typename U> + GLM_FUNC_QUALIFIER 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<typename T, qualifier Q> + GLM_FUNC_QUALIFIER mat<3, 3, T, Q> & mat<3, 3, T, Q>::operator++() + { + ++this->value[0]; + ++this->value[1]; + ++this->value[2]; + return *this; + } + + template<typename T, qualifier Q> + GLM_FUNC_QUALIFIER mat<3, 3, T, Q> & mat<3, 3, T, Q>::operator--() + { + --this->value[0]; + --this->value[1]; + --this->value[2]; + return *this; + } + + template<typename T, qualifier Q> + GLM_FUNC_QUALIFIER mat<3, 3, T, Q> mat<3, 3, T, Q>::operator++(int) + { + mat<3, 3, T, Q> Result(*this); + ++*this; + return Result; + } + + template<typename T, qualifier Q> + GLM_FUNC_QUALIFIER 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<typename T, qualifier Q> + GLM_FUNC_QUALIFIER mat<3, 3, T, Q> operator+(mat<3, 3, T, Q> const& m) + { + return m; + } + + template<typename T, qualifier Q> + GLM_FUNC_QUALIFIER 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<typename T, qualifier Q> + GLM_FUNC_QUALIFIER 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<typename T, qualifier Q> + GLM_FUNC_QUALIFIER 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<typename T, qualifier Q> + GLM_FUNC_QUALIFIER 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<typename T, qualifier Q> + GLM_FUNC_QUALIFIER 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<typename T, qualifier Q> + GLM_FUNC_QUALIFIER 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<typename T, qualifier Q> + GLM_FUNC_QUALIFIER 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<typename T, qualifier Q> + GLM_FUNC_QUALIFIER 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<typename T, qualifier Q> + GLM_FUNC_QUALIFIER 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<typename T, qualifier Q> + GLM_FUNC_QUALIFIER 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<typename T, qualifier Q> + GLM_FUNC_QUALIFIER 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<typename T, qualifier Q> + GLM_FUNC_QUALIFIER 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<typename T, qualifier Q> + GLM_FUNC_QUALIFIER 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<typename T, qualifier Q> + GLM_FUNC_QUALIFIER 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<typename T, qualifier Q> + GLM_FUNC_QUALIFIER 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<typename T, qualifier Q> + GLM_FUNC_QUALIFIER 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<typename T, qualifier Q> + GLM_FUNC_QUALIFIER 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<typename T, qualifier Q> + GLM_FUNC_QUALIFIER 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<typename T, qualifier Q> + GLM_FUNC_QUALIFIER 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<typename T, qualifier Q> + 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<typename T, qualifier Q> + GLM_FUNC_QUALIFIER 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 0000000000000000000000000000000000000000..6e40b90305eb2bf55c5bac3f5b77f8cc33f2f538 --- /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 <limits> +#include <cstddef> + +namespace glm +{ + template<typename T, qualifier Q> + 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 col_type & operator[](length_type i); + GLM_FUNC_DECL GLM_CONSTEXPR col_type const& operator[](length_type i) const; + + // -- Constructors -- + + GLM_FUNC_DECL GLM_CONSTEXPR mat() GLM_DEFAULT; + template<qualifier P> + GLM_FUNC_DECL GLM_CONSTEXPR mat(mat<3, 4, T, P> const& m); + + GLM_FUNC_DECL explicit GLM_CONSTEXPR mat(T scalar); + GLM_FUNC_DECL GLM_CONSTEXPR 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_FUNC_DECL GLM_CONSTEXPR 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_FUNC_DECL GLM_CONSTEXPR 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<typename V1, typename V2, typename V3> + GLM_FUNC_DECL GLM_CONSTEXPR mat( + vec<4, V1, Q> const& v1, + vec<4, V2, Q> const& v2, + vec<4, V3, Q> const& v3); + + // -- Matrix conversions -- + + template<typename U, qualifier P> + GLM_FUNC_DECL GLM_EXPLICIT GLM_CONSTEXPR mat(mat<3, 4, U, P> const& m); + + GLM_FUNC_DECL GLM_EXPLICIT GLM_CONSTEXPR mat(mat<2, 2, T, Q> const& x); + GLM_FUNC_DECL GLM_EXPLICIT GLM_CONSTEXPR mat(mat<3, 3, T, Q> const& x); + GLM_FUNC_DECL GLM_EXPLICIT GLM_CONSTEXPR mat(mat<4, 4, T, Q> const& x); + GLM_FUNC_DECL GLM_EXPLICIT GLM_CONSTEXPR mat(mat<2, 3, T, Q> const& x); + GLM_FUNC_DECL GLM_EXPLICIT GLM_CONSTEXPR mat(mat<3, 2, T, Q> const& x); + GLM_FUNC_DECL GLM_EXPLICIT GLM_CONSTEXPR mat(mat<2, 4, T, Q> const& x); + GLM_FUNC_DECL GLM_EXPLICIT GLM_CONSTEXPR mat(mat<4, 2, T, Q> const& x); + GLM_FUNC_DECL GLM_EXPLICIT GLM_CONSTEXPR mat(mat<4, 3, T, Q> const& x); + + // -- Unary arithmetic operators -- + + template<typename U> + GLM_FUNC_DECL mat<3, 4, T, Q> & operator=(mat<3, 4, U, Q> const& m); + template<typename U> + GLM_FUNC_DECL mat<3, 4, T, Q> & operator+=(U s); + template<typename U> + GLM_FUNC_DECL mat<3, 4, T, Q> & operator+=(mat<3, 4, U, Q> const& m); + template<typename U> + GLM_FUNC_DECL mat<3, 4, T, Q> & operator-=(U s); + template<typename U> + GLM_FUNC_DECL mat<3, 4, T, Q> & operator-=(mat<3, 4, U, Q> const& m); + template<typename U> + GLM_FUNC_DECL mat<3, 4, T, Q> & operator*=(U s); + template<typename U> + GLM_FUNC_DECL mat<3, 4, T, Q> & operator/=(U s); + + // -- Increment and decrement operators -- + + GLM_FUNC_DECL mat<3, 4, T, Q> & operator++(); + GLM_FUNC_DECL mat<3, 4, T, Q> & operator--(); + GLM_FUNC_DECL mat<3, 4, T, Q> operator++(int); + GLM_FUNC_DECL mat<3, 4, T, Q> operator--(int); + }; + + // -- Unary operators -- + + template<typename T, qualifier Q> + GLM_FUNC_DECL mat<3, 4, T, Q> operator+(mat<3, 4, T, Q> const& m); + + template<typename T, qualifier Q> + GLM_FUNC_DECL mat<3, 4, T, Q> operator-(mat<3, 4, T, Q> const& m); + + // -- Binary operators -- + + template<typename T, qualifier Q> + GLM_FUNC_DECL mat<3, 4, T, Q> operator+(mat<3, 4, T, Q> const& m, T scalar); + + template<typename T, qualifier Q> + GLM_FUNC_DECL mat<3, 4, T, Q> operator+(mat<3, 4, T, Q> const& m1, mat<3, 4, T, Q> const& m2); + + template<typename T, qualifier Q> + GLM_FUNC_DECL mat<3, 4, T, Q> operator-(mat<3, 4, T, Q> const& m, T scalar); + + template<typename T, qualifier Q> + GLM_FUNC_DECL mat<3, 4, T, Q> operator-(mat<3, 4, T, Q> const& m1, mat<3, 4, T, Q> const& m2); + + template<typename T, qualifier Q> + GLM_FUNC_DECL mat<3, 4, T, Q> operator*(mat<3, 4, T, Q> const& m, T scalar); + + template<typename T, qualifier Q> + GLM_FUNC_DECL mat<3, 4, T, Q> operator*(T scalar, mat<3, 4, T, Q> const& m); + + template<typename T, qualifier Q> + GLM_FUNC_DECL 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<typename T, qualifier Q> + GLM_FUNC_DECL 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<typename T, qualifier Q> + GLM_FUNC_DECL mat<4, 4, T, Q> operator*(mat<3, 4, T, Q> const& m1, mat<4, 3, T, Q> const& m2); + + template<typename T, qualifier Q> + GLM_FUNC_DECL mat<2, 4, T, Q> operator*(mat<3, 4, T, Q> const& m1, mat<2, 3, T, Q> const& m2); + + template<typename T, qualifier Q> + GLM_FUNC_DECL mat<3, 4, T, Q> operator*(mat<3, 4, T, Q> const& m1, mat<3, 3, T, Q> const& m2); + + template<typename T, qualifier Q> + GLM_FUNC_DECL mat<3, 4, T, Q> operator/(mat<3, 4, T, Q> const& m, T scalar); + + template<typename T, qualifier Q> + GLM_FUNC_DECL mat<3, 4, T, Q> operator/(T scalar, mat<3, 4, T, Q> const& m); + + // -- Boolean operators -- + + template<typename T, qualifier Q> + GLM_FUNC_DECL bool operator==(mat<3, 4, T, Q> const& m1, mat<3, 4, T, Q> const& m2); + + template<typename T, qualifier Q> + GLM_FUNC_DECL 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 0000000000000000000000000000000000000000..6ee416cfd657f7e9ed1bcf27e4cddbac641f4979 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/detail/type_mat3x4.inl @@ -0,0 +1,578 @@ +namespace glm +{ + // -- Constructors -- + +# if GLM_CONFIG_DEFAULTED_FUNCTIONS == GLM_DISABLE + template<typename T, qualifier Q> + GLM_FUNC_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<typename T, qualifier Q> + template<qualifier P> + 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<typename T, qualifier Q> + 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<typename T, qualifier Q> + 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<typename T, qualifier Q> + 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<typename T, qualifier Q> + 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<typename T, qualifier Q> + template<typename V1, typename V2, typename V3> + 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<typename T, qualifier Q> + template<typename U, qualifier P> + 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<typename T, qualifier Q> + 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<typename T, qualifier Q> + 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<typename T, qualifier Q> + 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<typename T, qualifier Q> + 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<typename T, qualifier Q> + 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<typename T, qualifier Q> + 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<typename T, qualifier Q> + 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<typename T, qualifier Q> + 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<typename T, qualifier Q> + GLM_FUNC_QUALIFIER typename mat<3, 4, T, Q>::col_type & mat<3, 4, T, Q>::operator[](typename mat<3, 4, T, Q>::length_type i) + { + assert(i < this->length()); + return this->value[i]; + } + + template<typename T, qualifier Q> + 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 + { + assert(i < this->length()); + return this->value[i]; + } + + // -- Unary updatable operators -- + + template<typename T, qualifier Q> + template<typename U> + GLM_FUNC_QUALIFIER 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<typename T, qualifier Q> + template<typename U> + GLM_FUNC_QUALIFIER 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<typename T, qualifier Q> + template<typename U> + GLM_FUNC_QUALIFIER 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<typename T, qualifier Q> + template<typename U> + GLM_FUNC_QUALIFIER 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<typename T, qualifier Q> + template<typename U> + GLM_FUNC_QUALIFIER 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<typename T, qualifier Q> + template<typename U> + GLM_FUNC_QUALIFIER 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<typename T, qualifier Q> + template<typename U> + GLM_FUNC_QUALIFIER 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<typename T, qualifier Q> + GLM_FUNC_QUALIFIER mat<3, 4, T, Q>& mat<3, 4, T, Q>::operator++() + { + ++this->value[0]; + ++this->value[1]; + ++this->value[2]; + return *this; + } + + template<typename T, qualifier Q> + GLM_FUNC_QUALIFIER mat<3, 4, T, Q>& mat<3, 4, T, Q>::operator--() + { + --this->value[0]; + --this->value[1]; + --this->value[2]; + return *this; + } + + template<typename T, qualifier Q> + GLM_FUNC_QUALIFIER mat<3, 4, T, Q> mat<3, 4, T, Q>::operator++(int) + { + mat<3, 4, T, Q> Result(*this); + ++*this; + return Result; + } + + template<typename T, qualifier Q> + GLM_FUNC_QUALIFIER 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<typename T, qualifier Q> + GLM_FUNC_QUALIFIER mat<3, 4, T, Q> operator+(mat<3, 4, T, Q> const& m) + { + return m; + } + + template<typename T, qualifier Q> + GLM_FUNC_QUALIFIER 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<typename T, qualifier Q> + GLM_FUNC_QUALIFIER 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<typename T, qualifier Q> + GLM_FUNC_QUALIFIER 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<typename T, qualifier Q> + GLM_FUNC_QUALIFIER 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<typename T, qualifier Q> + GLM_FUNC_QUALIFIER 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<typename T, qualifier Q> + GLM_FUNC_QUALIFIER 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<typename T, qualifier Q> + GLM_FUNC_QUALIFIER 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<typename T, qualifier Q> + GLM_FUNC_QUALIFIER 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<typename T, qualifier Q> + GLM_FUNC_QUALIFIER 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<typename T, qualifier Q> + GLM_FUNC_QUALIFIER 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<typename T, qualifier Q> + GLM_FUNC_QUALIFIER 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<typename T, qualifier Q> + GLM_FUNC_QUALIFIER 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<typename T, qualifier Q> + GLM_FUNC_QUALIFIER 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<typename T, qualifier Q> + GLM_FUNC_QUALIFIER 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<typename T, qualifier Q> + GLM_FUNC_QUALIFIER 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<typename T, qualifier Q> + GLM_FUNC_QUALIFIER 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 0000000000000000000000000000000000000000..8d3435271114988183d12ae39c1a8577e0da3327 --- /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 <limits> +#include <cstddef> + +namespace glm +{ + template<typename T, qualifier Q> + 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 col_type & operator[](length_type i); + GLM_FUNC_DECL GLM_CONSTEXPR col_type const& operator[](length_type i) const; + + // -- Constructors -- + + GLM_FUNC_DECL GLM_CONSTEXPR mat() GLM_DEFAULT; + template<qualifier P> + GLM_FUNC_DECL GLM_CONSTEXPR mat(mat<4, 2, T, P> const& m); + + GLM_FUNC_DECL explicit GLM_CONSTEXPR mat(T scalar); + GLM_FUNC_DECL GLM_CONSTEXPR mat( + T x0, T y0, + T x1, T y1, + T x2, T y2, + T x3, T y3); + GLM_FUNC_DECL GLM_CONSTEXPR 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_FUNC_DECL GLM_CONSTEXPR mat( + X0 x0, Y0 y0, + X1 x1, Y1 y1, + X2 x2, Y2 y2, + X3 x3, Y3 y3); + + template<typename V1, typename V2, typename V3, typename V4> + GLM_FUNC_DECL GLM_CONSTEXPR 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<typename U, qualifier P> + GLM_FUNC_DECL GLM_EXPLICIT GLM_CONSTEXPR mat(mat<4, 2, U, P> const& m); + + GLM_FUNC_DECL GLM_EXPLICIT GLM_CONSTEXPR mat(mat<2, 2, T, Q> const& x); + GLM_FUNC_DECL GLM_EXPLICIT GLM_CONSTEXPR mat(mat<3, 3, T, Q> const& x); + GLM_FUNC_DECL GLM_EXPLICIT GLM_CONSTEXPR mat(mat<4, 4, T, Q> const& x); + GLM_FUNC_DECL GLM_EXPLICIT GLM_CONSTEXPR mat(mat<2, 3, T, Q> const& x); + GLM_FUNC_DECL GLM_EXPLICIT GLM_CONSTEXPR mat(mat<3, 2, T, Q> const& x); + GLM_FUNC_DECL GLM_EXPLICIT GLM_CONSTEXPR mat(mat<2, 4, T, Q> const& x); + GLM_FUNC_DECL GLM_EXPLICIT GLM_CONSTEXPR mat(mat<4, 3, T, Q> const& x); + GLM_FUNC_DECL GLM_EXPLICIT GLM_CONSTEXPR mat(mat<3, 4, T, Q> const& x); + + // -- Unary arithmetic operators -- + + template<typename U> + GLM_FUNC_DECL mat<4, 2, T, Q> & operator=(mat<4, 2, U, Q> const& m); + template<typename U> + GLM_FUNC_DECL mat<4, 2, T, Q> & operator+=(U s); + template<typename U> + GLM_FUNC_DECL mat<4, 2, T, Q> & operator+=(mat<4, 2, U, Q> const& m); + template<typename U> + GLM_FUNC_DECL mat<4, 2, T, Q> & operator-=(U s); + template<typename U> + GLM_FUNC_DECL mat<4, 2, T, Q> & operator-=(mat<4, 2, U, Q> const& m); + template<typename U> + GLM_FUNC_DECL mat<4, 2, T, Q> & operator*=(U s); + template<typename U> + GLM_FUNC_DECL mat<4, 2, T, Q> & operator/=(U s); + + // -- Increment and decrement operators -- + + GLM_FUNC_DECL mat<4, 2, T, Q> & operator++ (); + GLM_FUNC_DECL mat<4, 2, T, Q> & operator-- (); + GLM_FUNC_DECL mat<4, 2, T, Q> operator++(int); + GLM_FUNC_DECL mat<4, 2, T, Q> operator--(int); + }; + + // -- Unary operators -- + + template<typename T, qualifier Q> + GLM_FUNC_DECL mat<4, 2, T, Q> operator+(mat<4, 2, T, Q> const& m); + + template<typename T, qualifier Q> + GLM_FUNC_DECL mat<4, 2, T, Q> operator-(mat<4, 2, T, Q> const& m); + + // -- Binary operators -- + + template<typename T, qualifier Q> + GLM_FUNC_DECL mat<4, 2, T, Q> operator+(mat<4, 2, T, Q> const& m, T scalar); + + template<typename T, qualifier Q> + GLM_FUNC_DECL mat<4, 2, T, Q> operator+(mat<4, 2, T, Q> const& m1, mat<4, 2, T, Q> const& m2); + + template<typename T, qualifier Q> + GLM_FUNC_DECL mat<4, 2, T, Q> operator-(mat<4, 2, T, Q> const& m, T scalar); + + template<typename T, qualifier Q> + GLM_FUNC_DECL mat<4, 2, T, Q> operator-(mat<4, 2, T, Q> const& m1, mat<4, 2, T, Q> const& m2); + + template<typename T, qualifier Q> + GLM_FUNC_DECL mat<4, 2, T, Q> operator*(mat<4, 2, T, Q> const& m, T scalar); + + template<typename T, qualifier Q> + GLM_FUNC_DECL mat<4, 2, T, Q> operator*(T scalar, mat<4, 2, T, Q> const& m); + + template<typename T, qualifier Q> + GLM_FUNC_DECL 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<typename T, qualifier Q> + GLM_FUNC_DECL 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<typename T, qualifier Q> + GLM_FUNC_DECL mat<2, 2, T, Q> operator*(mat<4, 2, T, Q> const& m1, mat<2, 4, T, Q> const& m2); + + template<typename T, qualifier Q> + GLM_FUNC_DECL mat<3, 2, T, Q> operator*(mat<4, 2, T, Q> const& m1, mat<3, 4, T, Q> const& m2); + + template<typename T, qualifier Q> + GLM_FUNC_DECL mat<4, 2, T, Q> operator*(mat<4, 2, T, Q> const& m1, mat<4, 4, T, Q> const& m2); + + template<typename T, qualifier Q> + GLM_FUNC_DECL mat<4, 2, T, Q> operator/(mat<4, 2, T, Q> const& m, T scalar); + + template<typename T, qualifier Q> + GLM_FUNC_DECL mat<4, 2, T, Q> operator/(T scalar, mat<4, 2, T, Q> const& m); + + // -- Boolean operators -- + + template<typename T, qualifier Q> + GLM_FUNC_DECL bool operator==(mat<4, 2, T, Q> const& m1, mat<4, 2, T, Q> const& m2); + + template<typename T, qualifier Q> + GLM_FUNC_DECL 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 0000000000000000000000000000000000000000..419c80c42cf105be007160d38ce37a81b60b833c --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/detail/type_mat4x2.inl @@ -0,0 +1,574 @@ +namespace glm +{ + // -- Constructors -- + +# if GLM_CONFIG_DEFAULTED_FUNCTIONS == GLM_DISABLE + template<typename T, qualifier Q> + GLM_FUNC_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<typename T, qualifier Q> + template<qualifier P> + 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<typename T, qualifier Q> + 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<typename T, qualifier Q> + 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<typename T, qualifier Q> + 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<typename T, qualifier Q> + 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<typename T, qualifier Q> + template<typename V0, typename V1, typename V2, typename V3> + 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<typename T, qualifier Q> + template<typename U, qualifier P> + 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<typename T, qualifier Q> + 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<typename T, qualifier Q> + 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<typename T, qualifier Q> + 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<typename T, qualifier Q> + 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<typename T, qualifier Q> + 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<typename T, qualifier Q> + 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<typename T, qualifier Q> + 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<typename T, qualifier Q> + 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<typename T, qualifier Q> + GLM_FUNC_QUALIFIER typename mat<4, 2, T, Q>::col_type & mat<4, 2, T, Q>::operator[](typename mat<4, 2, T, Q>::length_type i) + { + assert(i < this->length()); + return this->value[i]; + } + + template<typename T, qualifier Q> + 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 + { + assert(i < this->length()); + return this->value[i]; + } + + // -- Unary updatable operators -- + + template<typename T, qualifier Q> + template<typename U> + GLM_FUNC_QUALIFIER 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<typename T, qualifier Q> + template<typename U> + GLM_FUNC_QUALIFIER 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<typename T, qualifier Q> + template<typename U> + GLM_FUNC_QUALIFIER 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<typename T, qualifier Q> + template<typename U> + GLM_FUNC_QUALIFIER 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<typename T, qualifier Q> + template<typename U> + GLM_FUNC_QUALIFIER 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<typename T, qualifier Q> + template<typename U> + GLM_FUNC_QUALIFIER 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<typename T, qualifier Q> + template<typename U> + GLM_FUNC_QUALIFIER 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<typename T, qualifier Q> + GLM_FUNC_QUALIFIER 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<typename T, qualifier Q> + GLM_FUNC_QUALIFIER 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<typename T, qualifier Q> + GLM_FUNC_QUALIFIER mat<4, 2, T, Q> mat<4, 2, T, Q>::operator++(int) + { + mat<4, 2, T, Q> Result(*this); + ++*this; + return Result; + } + + template<typename T, qualifier Q> + GLM_FUNC_QUALIFIER 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<typename T, qualifier Q> + GLM_FUNC_QUALIFIER mat<4, 2, T, Q> operator+(mat<4, 2, T, Q> const& m) + { + return m; + } + + template<typename T, qualifier Q> + GLM_FUNC_QUALIFIER 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<typename T, qualifier Q> + GLM_FUNC_QUALIFIER 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<typename T, qualifier Q> + GLM_FUNC_QUALIFIER 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<typename T, qualifier Q> + GLM_FUNC_QUALIFIER 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<typename T, qualifier Q> + GLM_FUNC_QUALIFIER 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<typename T, qualifier Q> + GLM_FUNC_QUALIFIER 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<typename T, qualifier Q> + GLM_FUNC_QUALIFIER 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<typename T, qualifier Q> + GLM_FUNC_QUALIFIER 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<typename T, qualifier Q> + GLM_FUNC_QUALIFIER 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<typename T, qualifier Q> + GLM_FUNC_QUALIFIER 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<typename T, qualifier Q> + GLM_FUNC_QUALIFIER 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<typename T, qualifier Q> + GLM_FUNC_QUALIFIER 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<typename T, qualifier Q> + GLM_FUNC_QUALIFIER 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<typename T, qualifier Q> + GLM_FUNC_QUALIFIER 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<typename T, qualifier Q> + GLM_FUNC_QUALIFIER 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<typename T, qualifier Q> + GLM_FUNC_QUALIFIER 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 0000000000000000000000000000000000000000..16e42705185bccd57d5de38b57f0505666aa7031 --- /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 <limits> +#include <cstddef> + +namespace glm +{ + template<typename T, qualifier Q> + 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 col_type & operator[](length_type i); + GLM_FUNC_DECL GLM_CONSTEXPR col_type const& operator[](length_type i) const; + + // -- Constructors -- + + GLM_FUNC_DECL GLM_CONSTEXPR mat() GLM_DEFAULT; + template<qualifier P> + GLM_FUNC_DECL GLM_CONSTEXPR mat(mat<4, 3, T, P> const& m); + + GLM_FUNC_DECL explicit GLM_CONSTEXPR mat(T const& x); + GLM_FUNC_DECL GLM_CONSTEXPR 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_FUNC_DECL GLM_CONSTEXPR 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_FUNC_DECL GLM_CONSTEXPR 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<typename V1, typename V2, typename V3, typename V4> + GLM_FUNC_DECL GLM_CONSTEXPR 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<typename U, qualifier P> + GLM_FUNC_DECL GLM_EXPLICIT GLM_CONSTEXPR mat(mat<4, 3, U, P> const& m); + + GLM_FUNC_DECL GLM_EXPLICIT GLM_CONSTEXPR mat(mat<2, 2, T, Q> const& x); + GLM_FUNC_DECL GLM_EXPLICIT GLM_CONSTEXPR mat(mat<3, 3, T, Q> const& x); + GLM_FUNC_DECL GLM_EXPLICIT GLM_CONSTEXPR mat(mat<4, 4, T, Q> const& x); + GLM_FUNC_DECL GLM_EXPLICIT GLM_CONSTEXPR mat(mat<2, 3, T, Q> const& x); + GLM_FUNC_DECL GLM_EXPLICIT GLM_CONSTEXPR mat(mat<3, 2, T, Q> const& x); + GLM_FUNC_DECL GLM_EXPLICIT GLM_CONSTEXPR mat(mat<2, 4, T, Q> const& x); + GLM_FUNC_DECL GLM_EXPLICIT GLM_CONSTEXPR mat(mat<4, 2, T, Q> const& x); + GLM_FUNC_DECL GLM_EXPLICIT GLM_CONSTEXPR mat(mat<3, 4, T, Q> const& x); + + // -- Unary arithmetic operators -- + + template<typename U> + GLM_FUNC_DECL mat<4, 3, T, Q> & operator=(mat<4, 3, U, Q> const& m); + template<typename U> + GLM_FUNC_DECL mat<4, 3, T, Q> & operator+=(U s); + template<typename U> + GLM_FUNC_DECL mat<4, 3, T, Q> & operator+=(mat<4, 3, U, Q> const& m); + template<typename U> + GLM_FUNC_DECL mat<4, 3, T, Q> & operator-=(U s); + template<typename U> + GLM_FUNC_DECL mat<4, 3, T, Q> & operator-=(mat<4, 3, U, Q> const& m); + template<typename U> + GLM_FUNC_DECL mat<4, 3, T, Q> & operator*=(U s); + template<typename U> + GLM_FUNC_DECL mat<4, 3, T, Q> & operator/=(U s); + + // -- Increment and decrement operators -- + + GLM_FUNC_DECL mat<4, 3, T, Q>& operator++(); + GLM_FUNC_DECL mat<4, 3, T, Q>& operator--(); + GLM_FUNC_DECL mat<4, 3, T, Q> operator++(int); + GLM_FUNC_DECL mat<4, 3, T, Q> operator--(int); + }; + + // -- Unary operators -- + + template<typename T, qualifier Q> + GLM_FUNC_DECL mat<4, 3, T, Q> operator+(mat<4, 3, T, Q> const& m); + + template<typename T, qualifier Q> + GLM_FUNC_DECL mat<4, 3, T, Q> operator-(mat<4, 3, T, Q> const& m); + + // -- Binary operators -- + + template<typename T, qualifier Q> + GLM_FUNC_DECL mat<4, 3, T, Q> operator+(mat<4, 3, T, Q> const& m, T const& s); + + template<typename T, qualifier Q> + GLM_FUNC_DECL mat<4, 3, T, Q> operator+(mat<4, 3, T, Q> const& m1, mat<4, 3, T, Q> const& m2); + + template<typename T, qualifier Q> + GLM_FUNC_DECL mat<4, 3, T, Q> operator-(mat<4, 3, T, Q> const& m, T const& s); + + template<typename T, qualifier Q> + GLM_FUNC_DECL mat<4, 3, T, Q> operator-(mat<4, 3, T, Q> const& m1, mat<4, 3, T, Q> const& m2); + + template<typename T, qualifier Q> + GLM_FUNC_DECL mat<4, 3, T, Q> operator*(mat<4, 3, T, Q> const& m, T const& s); + + template<typename T, qualifier Q> + GLM_FUNC_DECL mat<4, 3, T, Q> operator*(T const& s, mat<4, 3, T, Q> const& m); + + template<typename T, qualifier Q> + GLM_FUNC_DECL 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<typename T, qualifier Q> + GLM_FUNC_DECL 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<typename T, qualifier Q> + GLM_FUNC_DECL mat<2, 3, T, Q> operator*(mat<4, 3, T, Q> const& m1, mat<2, 4, T, Q> const& m2); + + template<typename T, qualifier Q> + GLM_FUNC_DECL mat<3, 3, T, Q> operator*(mat<4, 3, T, Q> const& m1, mat<3, 4, T, Q> const& m2); + + template<typename T, qualifier Q> + GLM_FUNC_DECL mat<4, 3, T, Q> operator*(mat<4, 3, T, Q> const& m1, mat<4, 4, T, Q> const& m2); + + template<typename T, qualifier Q> + GLM_FUNC_DECL mat<4, 3, T, Q> operator/(mat<4, 3, T, Q> const& m, T const& s); + + template<typename T, qualifier Q> + GLM_FUNC_DECL mat<4, 3, T, Q> operator/(T const& s, mat<4, 3, T, Q> const& m); + + // -- Boolean operators -- + + template<typename T, qualifier Q> + GLM_FUNC_DECL bool operator==(mat<4, 3, T, Q> const& m1, mat<4, 3, T, Q> const& m2); + + template<typename T, qualifier Q> + GLM_FUNC_DECL 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 0000000000000000000000000000000000000000..11b1ee35d8a2d5a1d81f73eedc0b98c1456508d5 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/detail/type_mat4x3.inl @@ -0,0 +1,598 @@ +namespace glm +{ + // -- Constructors -- + +# if GLM_CONFIG_DEFAULTED_FUNCTIONS == GLM_DISABLE + template<typename T, qualifier Q> + GLM_FUNC_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<typename T, qualifier Q> + template<qualifier P> + 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<typename T, qualifier Q> + GLM_FUNC_QUALIFIER GLM_CONSTEXPR mat<4, 3, T, Q>::mat(T const& 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<typename T, qualifier Q> + 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<typename T, qualifier Q> + 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<typename T, qualifier Q> + 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<typename T, qualifier Q> + template<typename V1, typename V2, typename V3, typename V4> + 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<typename T, qualifier Q> + template<typename U, qualifier P> + 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<typename T, qualifier Q> + 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<typename T, qualifier Q> + 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<typename T, qualifier Q> + 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<typename T, qualifier Q> + 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<typename T, qualifier Q> + 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<typename T, qualifier Q> + 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<typename T, qualifier Q> + 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<typename T, qualifier Q> + 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<typename T, qualifier Q> + GLM_FUNC_QUALIFIER typename mat<4, 3, T, Q>::col_type & mat<4, 3, T, Q>::operator[](typename mat<4, 3, T, Q>::length_type i) + { + assert(i < this->length()); + return this->value[i]; + } + + template<typename T, qualifier Q> + 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 + { + assert(i < this->length()); + return this->value[i]; + } + + // -- Unary updatable operators -- + + template<typename T, qualifier Q> + template<typename U> + GLM_FUNC_QUALIFIER 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<typename T, qualifier Q> + template<typename U> + GLM_FUNC_QUALIFIER 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<typename T, qualifier Q> + template<typename U> + GLM_FUNC_QUALIFIER 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<typename T, qualifier Q> + template<typename U> + GLM_FUNC_QUALIFIER 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<typename T, qualifier Q> + template<typename U> + GLM_FUNC_QUALIFIER 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<typename T, qualifier Q> + template<typename U> + GLM_FUNC_QUALIFIER 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<typename T, qualifier Q> + template<typename U> + GLM_FUNC_QUALIFIER 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<typename T, qualifier Q> + GLM_FUNC_QUALIFIER 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<typename T, qualifier Q> + GLM_FUNC_QUALIFIER 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<typename T, qualifier Q> + GLM_FUNC_QUALIFIER mat<4, 3, T, Q> mat<4, 3, T, Q>::operator++(int) + { + mat<4, 3, T, Q> Result(*this); + ++*this; + return Result; + } + + template<typename T, qualifier Q> + GLM_FUNC_QUALIFIER 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<typename T, qualifier Q> + GLM_FUNC_QUALIFIER mat<4, 3, T, Q> operator+(mat<4, 3, T, Q> const& m) + { + return m; + } + + template<typename T, qualifier Q> + GLM_FUNC_QUALIFIER 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<typename T, qualifier Q> + GLM_FUNC_QUALIFIER mat<4, 3, T, Q> operator+(mat<4, 3, T, Q> const& m, T const& s) + { + return mat<4, 3, T, Q>( + m[0] + s, + m[1] + s, + m[2] + s, + m[3] + s); + } + + template<typename T, qualifier Q> + GLM_FUNC_QUALIFIER 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<typename T, qualifier Q> + GLM_FUNC_QUALIFIER mat<4, 3, T, Q> operator-(mat<4, 3, T, Q> const& m, T const& s) + { + return mat<4, 3, T, Q>( + m[0] - s, + m[1] - s, + m[2] - s, + m[3] - s); + } + + template<typename T, qualifier Q> + GLM_FUNC_QUALIFIER 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<typename T, qualifier Q> + GLM_FUNC_QUALIFIER mat<4, 3, T, Q> operator*(mat<4, 3, T, Q> const& m, T const& s) + { + return mat<4, 3, T, Q>( + m[0] * s, + m[1] * s, + m[2] * s, + m[3] * s); + } + + template<typename T, qualifier Q> + GLM_FUNC_QUALIFIER mat<4, 3, T, Q> operator*(T const& s, mat<4, 3, T, Q> const& m) + { + return mat<4, 3, T, Q>( + m[0] * s, + m[1] * s, + m[2] * s, + m[3] * s); + } + + template<typename T, qualifier Q> + GLM_FUNC_QUALIFIER 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<typename T, qualifier Q> + GLM_FUNC_QUALIFIER 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<typename T, qualifier Q> + GLM_FUNC_QUALIFIER 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<typename T, qualifier Q> + GLM_FUNC_QUALIFIER 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<typename T, qualifier Q> + GLM_FUNC_QUALIFIER 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<typename T, qualifier Q> + GLM_FUNC_QUALIFIER mat<4, 3, T, Q> operator/(mat<4, 3, T, Q> const& m, T const& s) + { + return mat<4, 3, T, Q>( + m[0] / s, + m[1] / s, + m[2] / s, + m[3] / s); + } + + template<typename T, qualifier Q> + GLM_FUNC_QUALIFIER mat<4, 3, T, Q> operator/(T const& s, mat<4, 3, T, Q> const& m) + { + return mat<4, 3, T, Q>( + s / m[0], + s / m[1], + s / m[2], + s / m[3]); + } + + // -- Boolean operators -- + + template<typename T, qualifier Q> + GLM_FUNC_QUALIFIER 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<typename T, qualifier Q> + GLM_FUNC_QUALIFIER 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 0000000000000000000000000000000000000000..3517f9f527de3eef38076c3f991284699359017c --- /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 <limits> +#include <cstddef> + +namespace glm +{ + template<typename T, qualifier Q> + 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 col_type & operator[](length_type i); + GLM_FUNC_DECL GLM_CONSTEXPR col_type const& operator[](length_type i) const; + + // -- Constructors -- + + GLM_FUNC_DECL GLM_CONSTEXPR mat() GLM_DEFAULT; + template<qualifier P> + GLM_FUNC_DECL GLM_CONSTEXPR mat(mat<4, 4, T, P> const& m); + + GLM_FUNC_DECL explicit GLM_CONSTEXPR mat(T const& x); + GLM_FUNC_DECL GLM_CONSTEXPR 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_FUNC_DECL GLM_CONSTEXPR 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_FUNC_DECL GLM_CONSTEXPR 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<typename V1, typename V2, typename V3, typename V4> + GLM_FUNC_DECL GLM_CONSTEXPR 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<typename U, qualifier P> + GLM_FUNC_DECL GLM_EXPLICIT GLM_CONSTEXPR mat(mat<4, 4, U, P> const& m); + + GLM_FUNC_DECL GLM_EXPLICIT GLM_CONSTEXPR mat(mat<2, 2, T, Q> const& x); + GLM_FUNC_DECL GLM_EXPLICIT GLM_CONSTEXPR mat(mat<3, 3, T, Q> const& x); + GLM_FUNC_DECL GLM_EXPLICIT GLM_CONSTEXPR mat(mat<2, 3, T, Q> const& x); + GLM_FUNC_DECL GLM_EXPLICIT GLM_CONSTEXPR mat(mat<3, 2, T, Q> const& x); + GLM_FUNC_DECL GLM_EXPLICIT GLM_CONSTEXPR mat(mat<2, 4, T, Q> const& x); + GLM_FUNC_DECL GLM_EXPLICIT GLM_CONSTEXPR mat(mat<4, 2, T, Q> const& x); + GLM_FUNC_DECL GLM_EXPLICIT GLM_CONSTEXPR mat(mat<3, 4, T, Q> const& x); + GLM_FUNC_DECL GLM_EXPLICIT GLM_CONSTEXPR mat(mat<4, 3, T, Q> const& x); + + // -- Unary arithmetic operators -- + + template<typename U> + GLM_FUNC_DECL mat<4, 4, T, Q> & operator=(mat<4, 4, U, Q> const& m); + template<typename U> + GLM_FUNC_DECL mat<4, 4, T, Q> & operator+=(U s); + template<typename U> + GLM_FUNC_DECL mat<4, 4, T, Q> & operator+=(mat<4, 4, U, Q> const& m); + template<typename U> + GLM_FUNC_DECL mat<4, 4, T, Q> & operator-=(U s); + template<typename U> + GLM_FUNC_DECL mat<4, 4, T, Q> & operator-=(mat<4, 4, U, Q> const& m); + template<typename U> + GLM_FUNC_DECL mat<4, 4, T, Q> & operator*=(U s); + template<typename U> + GLM_FUNC_DECL mat<4, 4, T, Q> & operator*=(mat<4, 4, U, Q> const& m); + template<typename U> + GLM_FUNC_DECL mat<4, 4, T, Q> & operator/=(U s); + template<typename U> + GLM_FUNC_DECL mat<4, 4, T, Q> & operator/=(mat<4, 4, U, Q> const& m); + + // -- Increment and decrement operators -- + + GLM_FUNC_DECL mat<4, 4, T, Q> & operator++(); + GLM_FUNC_DECL mat<4, 4, T, Q> & operator--(); + GLM_FUNC_DECL mat<4, 4, T, Q> operator++(int); + GLM_FUNC_DECL mat<4, 4, T, Q> operator--(int); + }; + + // -- Unary operators -- + + template<typename T, qualifier Q> + GLM_FUNC_DECL mat<4, 4, T, Q> operator+(mat<4, 4, T, Q> const& m); + + template<typename T, qualifier Q> + GLM_FUNC_DECL mat<4, 4, T, Q> operator-(mat<4, 4, T, Q> const& m); + + // -- Binary operators -- + + template<typename T, qualifier Q> + GLM_FUNC_DECL mat<4, 4, T, Q> operator+(mat<4, 4, T, Q> const& m, T const& s); + + template<typename T, qualifier Q> + GLM_FUNC_DECL mat<4, 4, T, Q> operator+(T const& s, mat<4, 4, T, Q> const& m); + + template<typename T, qualifier Q> + GLM_FUNC_DECL mat<4, 4, T, Q> operator+(mat<4, 4, T, Q> const& m1, mat<4, 4, T, Q> const& m2); + + template<typename T, qualifier Q> + GLM_FUNC_DECL mat<4, 4, T, Q> operator-(mat<4, 4, T, Q> const& m, T const& s); + + template<typename T, qualifier Q> + GLM_FUNC_DECL mat<4, 4, T, Q> operator-(T const& s, mat<4, 4, T, Q> const& m); + + template<typename T, qualifier Q> + GLM_FUNC_DECL mat<4, 4, T, Q> operator-(mat<4, 4, T, Q> const& m1, mat<4, 4, T, Q> const& m2); + + template<typename T, qualifier Q> + GLM_FUNC_DECL mat<4, 4, T, Q> operator*(mat<4, 4, T, Q> const& m, T const& s); + + template<typename T, qualifier Q> + GLM_FUNC_DECL mat<4, 4, T, Q> operator*(T const& s, mat<4, 4, T, Q> const& m); + + template<typename T, qualifier Q> + GLM_FUNC_DECL 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<typename T, qualifier Q> + GLM_FUNC_DECL 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<typename T, qualifier Q> + GLM_FUNC_DECL mat<2, 4, T, Q> operator*(mat<4, 4, T, Q> const& m1, mat<2, 4, T, Q> const& m2); + + template<typename T, qualifier Q> + GLM_FUNC_DECL mat<3, 4, T, Q> operator*(mat<4, 4, T, Q> const& m1, mat<3, 4, T, Q> const& m2); + + template<typename T, qualifier Q> + GLM_FUNC_DECL mat<4, 4, T, Q> operator*(mat<4, 4, T, Q> const& m1, mat<4, 4, T, Q> const& m2); + + template<typename T, qualifier Q> + GLM_FUNC_DECL mat<4, 4, T, Q> operator/(mat<4, 4, T, Q> const& m, T const& s); + + template<typename T, qualifier Q> + GLM_FUNC_DECL mat<4, 4, T, Q> operator/(T const& s, mat<4, 4, T, Q> const& m); + + template<typename T, qualifier Q> + GLM_FUNC_DECL 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<typename T, qualifier Q> + GLM_FUNC_DECL 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<typename T, qualifier Q> + GLM_FUNC_DECL mat<4, 4, T, Q> operator/(mat<4, 4, T, Q> const& m1, mat<4, 4, T, Q> const& m2); + + // -- Boolean operators -- + + template<typename T, qualifier Q> + GLM_FUNC_DECL bool operator==(mat<4, 4, T, Q> const& m1, mat<4, 4, T, Q> const& m2); + + template<typename T, qualifier Q> + GLM_FUNC_DECL 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 0000000000000000000000000000000000000000..e38b87f77e73a3cd731a18baa9ce4a3dfcfa99a2 --- /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_FUNCTIONS == GLM_DISABLE + template<typename T, qualifier Q> + GLM_FUNC_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<typename T, qualifier Q> + template<qualifier P> + 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<typename T, qualifier Q> + GLM_FUNC_QUALIFIER GLM_CONSTEXPR mat<4, 4, T, Q>::mat(T const& 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<typename T, qualifier Q> + 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<typename T, qualifier Q> + 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<typename T, qualifier Q> + template<typename U, qualifier P> + 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<typename T, qualifier Q> + 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<X1>::is_iec559 || std::numeric_limits<X1>::is_integer || GLM_CONFIG_UNRESTRICTED_GENTYPE, "*mat4x4 constructor only takes float and integer types, 1st parameter type invalid."); + GLM_STATIC_ASSERT(std::numeric_limits<Y1>::is_iec559 || std::numeric_limits<Y1>::is_integer || GLM_CONFIG_UNRESTRICTED_GENTYPE, "*mat4x4 constructor only takes float and integer types, 2nd parameter type invalid."); + GLM_STATIC_ASSERT(std::numeric_limits<Z1>::is_iec559 || std::numeric_limits<Z1>::is_integer || GLM_CONFIG_UNRESTRICTED_GENTYPE, "*mat4x4 constructor only takes float and integer types, 3rd parameter type invalid."); + GLM_STATIC_ASSERT(std::numeric_limits<W1>::is_iec559 || std::numeric_limits<W1>::is_integer || GLM_CONFIG_UNRESTRICTED_GENTYPE, "*mat4x4 constructor only takes float and integer types, 4th parameter type invalid."); + + GLM_STATIC_ASSERT(std::numeric_limits<X2>::is_iec559 || std::numeric_limits<X2>::is_integer || GLM_CONFIG_UNRESTRICTED_GENTYPE, "*mat4x4 constructor only takes float and integer types, 5th parameter type invalid."); + GLM_STATIC_ASSERT(std::numeric_limits<Y2>::is_iec559 || std::numeric_limits<Y2>::is_integer || GLM_CONFIG_UNRESTRICTED_GENTYPE, "*mat4x4 constructor only takes float and integer types, 6th parameter type invalid."); + GLM_STATIC_ASSERT(std::numeric_limits<Z2>::is_iec559 || std::numeric_limits<Z2>::is_integer || GLM_CONFIG_UNRESTRICTED_GENTYPE, "*mat4x4 constructor only takes float and integer types, 7th parameter type invalid."); + GLM_STATIC_ASSERT(std::numeric_limits<W2>::is_iec559 || std::numeric_limits<W2>::is_integer || GLM_CONFIG_UNRESTRICTED_GENTYPE, "*mat4x4 constructor only takes float and integer types, 8th parameter type invalid."); + + GLM_STATIC_ASSERT(std::numeric_limits<X3>::is_iec559 || std::numeric_limits<X3>::is_integer || GLM_CONFIG_UNRESTRICTED_GENTYPE, "*mat4x4 constructor only takes float and integer types, 9th parameter type invalid."); + GLM_STATIC_ASSERT(std::numeric_limits<Y3>::is_iec559 || std::numeric_limits<Y3>::is_integer || GLM_CONFIG_UNRESTRICTED_GENTYPE, "*mat4x4 constructor only takes float and integer types, 10th parameter type invalid."); + GLM_STATIC_ASSERT(std::numeric_limits<Z3>::is_iec559 || std::numeric_limits<Z3>::is_integer || GLM_CONFIG_UNRESTRICTED_GENTYPE, "*mat4x4 constructor only takes float and integer types, 11th parameter type invalid."); + GLM_STATIC_ASSERT(std::numeric_limits<W3>::is_iec559 || std::numeric_limits<W3>::is_integer || GLM_CONFIG_UNRESTRICTED_GENTYPE, "*mat4x4 constructor only takes float and integer types, 12th parameter type invalid."); + + GLM_STATIC_ASSERT(std::numeric_limits<X4>::is_iec559 || std::numeric_limits<X4>::is_integer || GLM_CONFIG_UNRESTRICTED_GENTYPE, "*mat4x4 constructor only takes float and integer types, 13th parameter type invalid."); + GLM_STATIC_ASSERT(std::numeric_limits<Y4>::is_iec559 || std::numeric_limits<Y4>::is_integer || GLM_CONFIG_UNRESTRICTED_GENTYPE, "*mat4x4 constructor only takes float and integer types, 14th parameter type invalid."); + GLM_STATIC_ASSERT(std::numeric_limits<Z4>::is_iec559 || std::numeric_limits<Z4>::is_integer || GLM_CONFIG_UNRESTRICTED_GENTYPE, "*mat4x4 constructor only takes float and integer types, 15th parameter type invalid."); + GLM_STATIC_ASSERT(std::numeric_limits<W4>::is_iec559 || std::numeric_limits<W4>::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<typename T, qualifier Q> + template<typename V1, typename V2, typename V3, typename V4> + 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<V1>::is_iec559 || std::numeric_limits<V1>::is_integer || GLM_CONFIG_UNRESTRICTED_GENTYPE, "*mat4x4 constructor only takes float and integer types, 1st parameter type invalid."); + GLM_STATIC_ASSERT(std::numeric_limits<V2>::is_iec559 || std::numeric_limits<V2>::is_integer || GLM_CONFIG_UNRESTRICTED_GENTYPE, "*mat4x4 constructor only takes float and integer types, 2nd parameter type invalid."); + GLM_STATIC_ASSERT(std::numeric_limits<V3>::is_iec559 || std::numeric_limits<V3>::is_integer || GLM_CONFIG_UNRESTRICTED_GENTYPE, "*mat4x4 constructor only takes float and integer types, 3rd parameter type invalid."); + GLM_STATIC_ASSERT(std::numeric_limits<V4>::is_iec559 || std::numeric_limits<V4>::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<typename T, qualifier Q> + 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<typename T, qualifier Q> + 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<typename T, qualifier Q> + 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<typename T, qualifier Q> + 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<typename T, qualifier Q> + 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<typename T, qualifier Q> + 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<typename T, qualifier Q> + 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<typename T, qualifier Q> + 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<typename T, qualifier Q> + GLM_FUNC_QUALIFIER typename mat<4, 4, T, Q>::col_type & mat<4, 4, T, Q>::operator[](typename mat<4, 4, T, Q>::length_type i) + { + assert(i < this->length()); + return this->value[i]; + } + + template<typename T, qualifier Q> + 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 + { + assert(i < this->length()); + return this->value[i]; + } + + // -- Unary arithmetic operators -- + + template<typename T, qualifier Q> + template<typename U> + GLM_FUNC_QUALIFIER 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<typename T, qualifier Q> + template<typename U> + GLM_FUNC_QUALIFIER 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<typename T, qualifier Q> + template<typename U> + GLM_FUNC_QUALIFIER 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<typename T, qualifier Q> + template<typename U> + GLM_FUNC_QUALIFIER 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<typename T, qualifier Q> + template<typename U> + GLM_FUNC_QUALIFIER 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<typename T, qualifier Q> + template<typename U> + GLM_FUNC_QUALIFIER 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<typename T, qualifier Q> + template<typename U> + GLM_FUNC_QUALIFIER mat<4, 4, T, Q> & mat<4, 4, T, Q>::operator*=(mat<4, 4, U, Q> const& m) + { + return (*this = *this * m); + } + + template<typename T, qualifier Q> + template<typename U> + GLM_FUNC_QUALIFIER 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<typename T, qualifier Q> + template<typename U> + GLM_FUNC_QUALIFIER 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<typename T, qualifier Q> + GLM_FUNC_QUALIFIER 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<typename T, qualifier Q> + GLM_FUNC_QUALIFIER 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<typename T, qualifier Q> + GLM_FUNC_QUALIFIER mat<4, 4, T, Q> mat<4, 4, T, Q>::operator++(int) + { + mat<4, 4, T, Q> Result(*this); + ++*this; + return Result; + } + + template<typename T, qualifier Q> + GLM_FUNC_QUALIFIER 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<typename T, qualifier Q> + GLM_FUNC_QUALIFIER mat<4, 4, T, Q> operator+(mat<4, 4, T, Q> const& m) + { + return m; + } + + template<typename T, qualifier Q> + GLM_FUNC_QUALIFIER 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<typename T, qualifier Q> + GLM_FUNC_QUALIFIER mat<4, 4, T, Q> operator+(mat<4, 4, T, Q> const& m, T const& s) + { + return mat<4, 4, T, Q>( + m[0] + s, + m[1] + s, + m[2] + s, + m[3] + s); + } + + template<typename T, qualifier Q> + GLM_FUNC_QUALIFIER mat<4, 4, T, Q> operator+(T const& s, mat<4, 4, T, Q> const& m) + { + return mat<4, 4, T, Q>( + m[0] + s, + m[1] + s, + m[2] + s, + m[3] + s); + } + + template<typename T, qualifier Q> + GLM_FUNC_QUALIFIER 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<typename T, qualifier Q> + GLM_FUNC_QUALIFIER mat<4, 4, T, Q> operator-(mat<4, 4, T, Q> const& m, T const& s) + { + return mat<4, 4, T, Q>( + m[0] - s, + m[1] - s, + m[2] - s, + m[3] - s); + } + + template<typename T, qualifier Q> + GLM_FUNC_QUALIFIER mat<4, 4, T, Q> operator-(T const& s, mat<4, 4, T, Q> const& m) + { + return mat<4, 4, T, Q>( + s - m[0], + s - m[1], + s - m[2], + s - m[3]); + } + + template<typename T, qualifier Q> + GLM_FUNC_QUALIFIER 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<typename T, qualifier Q> + GLM_FUNC_QUALIFIER mat<4, 4, T, Q> operator*(mat<4, 4, T, Q> const& m, T const & s) + { + return mat<4, 4, T, Q>( + m[0] * s, + m[1] * s, + m[2] * s, + m[3] * s); + } + + template<typename T, qualifier Q> + GLM_FUNC_QUALIFIER mat<4, 4, T, Q> operator*(T const& s, mat<4, 4, T, Q> const& m) + { + return mat<4, 4, T, Q>( + m[0] * s, + m[1] * s, + m[2] * s, + m[3] * s); + } + + template<typename T, qualifier Q> + GLM_FUNC_QUALIFIER 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<typename T, qualifier Q> + GLM_FUNC_QUALIFIER 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<typename T, qualifier Q> + GLM_FUNC_QUALIFIER 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<typename T, qualifier Q> + GLM_FUNC_QUALIFIER 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<typename T, qualifier Q> + GLM_FUNC_QUALIFIER 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<typename T, qualifier Q> + GLM_FUNC_QUALIFIER mat<4, 4, T, Q> operator/(mat<4, 4, T, Q> const& m, T const& s) + { + return mat<4, 4, T, Q>( + m[0] / s, + m[1] / s, + m[2] / s, + m[3] / s); + } + + template<typename T, qualifier Q> + GLM_FUNC_QUALIFIER mat<4, 4, T, Q> operator/(T const& s, mat<4, 4, T, Q> const& m) + { + return mat<4, 4, T, Q>( + s / m[0], + s / m[1], + s / m[2], + s / m[3]); + } + + template<typename T, qualifier Q> + GLM_FUNC_QUALIFIER 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<typename T, qualifier Q> + GLM_FUNC_QUALIFIER 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<typename T, qualifier Q> + GLM_FUNC_QUALIFIER 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<typename T, qualifier Q> + GLM_FUNC_QUALIFIER 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<typename T, qualifier Q> + GLM_FUNC_QUALIFIER 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 0000000000000000000000000000000000000000..fb3a16f062901d31b8ed8c493efd17e1cf87468f --- /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 0000000000000000000000000000000000000000..0e60bc33c4894ae3cbd6c8fdaf04c09ae98aa033 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/detail/type_quat.hpp @@ -0,0 +1,186 @@ +/// @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 +{ + template<typename T, qualifier Q> + struct qua + { + // -- Implementation detail -- + + typedef qua<T, Q> type; + typedef T value_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_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<Q>::value>::type data; + }; +# else +# ifdef GLM_FORCE_QUAT_DATA_WXYZ + T w, x, y, z; +# else + T x, y, z, w; +# 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 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_FUNC_DECL GLM_CONSTEXPR qua() GLM_DEFAULT; + GLM_FUNC_DECL GLM_CONSTEXPR qua(qua<T, Q> const& q) GLM_DEFAULT; + template<qualifier P> + GLM_FUNC_DECL GLM_CONSTEXPR qua(qua<T, P> const& q); + + // -- Explicit basic constructors -- + + GLM_FUNC_DECL GLM_CONSTEXPR qua(T s, vec<3, T, Q> const& v); + GLM_FUNC_DECL GLM_CONSTEXPR qua(T w, T x, T y, T z); + + // -- Conversion constructors -- + + template<typename U, qualifier P> + GLM_FUNC_DECL GLM_CONSTEXPR GLM_EXPLICIT qua(qua<U, P> 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_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_FUNC_DECL GLM_CONSTEXPR GLM_EXPLICIT qua(vec<3, T, Q> const& eulerAngles); + GLM_FUNC_DECL GLM_EXPLICIT qua(mat<3, 3, T, Q> const& q); + GLM_FUNC_DECL GLM_EXPLICIT qua(mat<4, 4, T, Q> const& q); + + // -- Unary arithmetic operators -- + + GLM_FUNC_DECL GLM_CONSTEXPR qua<T, Q>& operator=(qua<T, Q> const& q) GLM_DEFAULT; + + template<typename U> + GLM_FUNC_DECL GLM_CONSTEXPR qua<T, Q>& operator=(qua<U, Q> const& q); + template<typename U> + GLM_FUNC_DECL GLM_CONSTEXPR qua<T, Q>& operator+=(qua<U, Q> const& q); + template<typename U> + GLM_FUNC_DECL GLM_CONSTEXPR qua<T, Q>& operator-=(qua<U, Q> const& q); + template<typename U> + GLM_FUNC_DECL GLM_CONSTEXPR qua<T, Q>& operator*=(qua<U, Q> const& q); + template<typename U> + GLM_FUNC_DECL GLM_CONSTEXPR qua<T, Q>& operator*=(U s); + template<typename U> + GLM_FUNC_DECL GLM_CONSTEXPR qua<T, Q>& operator/=(U s); + }; + + // -- Unary bit operators -- + + template<typename T, qualifier Q> + GLM_FUNC_DECL GLM_CONSTEXPR qua<T, Q> operator+(qua<T, Q> const& q); + + template<typename T, qualifier Q> + GLM_FUNC_DECL GLM_CONSTEXPR qua<T, Q> operator-(qua<T, Q> const& q); + + // -- Binary operators -- + + template<typename T, qualifier Q> + GLM_FUNC_DECL GLM_CONSTEXPR qua<T, Q> operator+(qua<T, Q> const& q, qua<T, Q> const& p); + + template<typename T, qualifier Q> + GLM_FUNC_DECL GLM_CONSTEXPR qua<T, Q> operator-(qua<T, Q> const& q, qua<T, Q> const& p); + + template<typename T, qualifier Q> + GLM_FUNC_DECL GLM_CONSTEXPR qua<T, Q> operator*(qua<T, Q> const& q, qua<T, Q> const& p); + + template<typename T, qualifier Q> + GLM_FUNC_DECL GLM_CONSTEXPR vec<3, T, Q> operator*(qua<T, Q> const& q, vec<3, T, Q> const& v); + + template<typename T, qualifier Q> + GLM_FUNC_DECL GLM_CONSTEXPR vec<3, T, Q> operator*(vec<3, T, Q> const& v, qua<T, Q> const& q); + + template<typename T, qualifier Q> + GLM_FUNC_DECL GLM_CONSTEXPR vec<4, T, Q> operator*(qua<T, Q> const& q, vec<4, T, Q> const& v); + + template<typename T, qualifier Q> + GLM_FUNC_DECL GLM_CONSTEXPR vec<4, T, Q> operator*(vec<4, T, Q> const& v, qua<T, Q> const& q); + + template<typename T, qualifier Q> + GLM_FUNC_DECL GLM_CONSTEXPR qua<T, Q> operator*(qua<T, Q> const& q, T const& s); + + template<typename T, qualifier Q> + GLM_FUNC_DECL GLM_CONSTEXPR qua<T, Q> operator*(T const& s, qua<T, Q> const& q); + + template<typename T, qualifier Q> + GLM_FUNC_DECL GLM_CONSTEXPR qua<T, Q> operator/(qua<T, Q> const& q, T const& s); + + // -- Boolean operators -- + + template<typename T, qualifier Q> + GLM_FUNC_DECL GLM_CONSTEXPR bool operator==(qua<T, Q> const& q1, qua<T, Q> const& q2); + + template<typename T, qualifier Q> + GLM_FUNC_DECL GLM_CONSTEXPR bool operator!=(qua<T, Q> const& q1, qua<T, Q> 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 0000000000000000000000000000000000000000..67b9310ac2ce2ea49dd683f560d968c7ed74826f --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/detail/type_quat.inl @@ -0,0 +1,408 @@ +#include "../trigonometric.hpp" +#include "../exponential.hpp" +#include "../ext/quaternion_geometric.hpp" +#include <limits> + +namespace glm{ +namespace detail +{ + template <typename T> + struct genTypeTrait<qua<T> > + { + static const genTypeEnum GENTYPE = GENTYPE_QUAT; + }; + + template<typename T, qualifier Q, bool Aligned> + struct compute_dot<qua<T, Q>, T, Aligned> + { + GLM_FUNC_QUALIFIER GLM_CONSTEXPR static T call(qua<T, Q> const& a, qua<T, Q> 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<typename T, qualifier Q, bool Aligned> + struct compute_quat_add + { + GLM_FUNC_QUALIFIER GLM_CONSTEXPR static qua<T, Q> call(qua<T, Q> const& q, qua<T, Q> const& p) + { + return qua<T, Q>(q.w + p.w, q.x + p.x, q.y + p.y, q.z + p.z); + } + }; + + template<typename T, qualifier Q, bool Aligned> + struct compute_quat_sub + { + GLM_FUNC_QUALIFIER GLM_CONSTEXPR static qua<T, Q> call(qua<T, Q> const& q, qua<T, Q> const& p) + { + return qua<T, Q>(q.w - p.w, q.x - p.x, q.y - p.y, q.z - p.z); + } + }; + + template<typename T, qualifier Q, bool Aligned> + struct compute_quat_mul_scalar + { + GLM_FUNC_QUALIFIER GLM_CONSTEXPR static qua<T, Q> call(qua<T, Q> const& q, T s) + { + return qua<T, Q>(q.w * s, q.x * s, q.y * s, q.z * s); + } + }; + + template<typename T, qualifier Q, bool Aligned> + struct compute_quat_div_scalar + { + GLM_FUNC_QUALIFIER GLM_CONSTEXPR static qua<T, Q> call(qua<T, Q> const& q, T s) + { + return qua<T, Q>(q.w / s, q.x / s, q.y / s, q.z / s); + } + }; + + template<typename T, qualifier Q, bool Aligned> + struct compute_quat_mul_vec4 + { + GLM_FUNC_QUALIFIER GLM_CONSTEXPR static vec<4, T, Q> call(qua<T, Q> 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<typename T, qualifier Q> + GLM_FUNC_QUALIFIER GLM_CONSTEXPR T & qua<T, Q>::operator[](typename qua<T, Q>::length_type i) + { + assert(i >= 0 && i < this->length()); +# ifdef GLM_FORCE_QUAT_DATA_WXYZ + return (&w)[i]; +# else + return (&x)[i]; +# endif + } + + template<typename T, qualifier Q> + GLM_FUNC_QUALIFIER GLM_CONSTEXPR T const& qua<T, Q>::operator[](typename qua<T, Q>::length_type i) const + { + assert(i >= 0 && i < this->length()); +# ifdef GLM_FORCE_QUAT_DATA_WXYZ + return (&w)[i]; +# else + return (&x)[i]; +# endif + } + + // -- Implicit basic constructors -- + +# if GLM_CONFIG_DEFAULTED_FUNCTIONS == GLM_DISABLE + template<typename T, qualifier Q> + GLM_FUNC_QUALIFIER GLM_CONSTEXPR qua<T, Q>::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 + {} + + template<typename T, qualifier Q> + GLM_FUNC_QUALIFIER GLM_CONSTEXPR qua<T, Q>::qua(qua<T, Q> 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<typename T, qualifier Q> + template<qualifier P> + GLM_FUNC_QUALIFIER GLM_CONSTEXPR qua<T, Q>::qua(qua<T, P> 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<typename T, qualifier Q> + GLM_FUNC_QUALIFIER GLM_CONSTEXPR qua<T, Q>::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 <typename T, qualifier Q> + GLM_FUNC_QUALIFIER GLM_CONSTEXPR qua<T, Q>::qua(T _w, T _x, T _y, T _z) +# ifdef GLM_FORCE_QUAT_DATA_WXYZ + : w(_w), x(_x), y(_y), z(_z) +# else + : x(_x), y(_y), z(_z), w(_w) +# endif + {} + + // -- Conversion constructors -- + + template<typename T, qualifier Q> + template<typename U, qualifier P> + GLM_FUNC_QUALIFIER GLM_CONSTEXPR qua<T, Q>::qua(qua<U, P> const& q) +# ifdef GLM_FORCE_QUAT_DATA_WXYZ + : w(static_cast<T>(q.w)), x(static_cast<T>(q.x)), y(static_cast<T>(q.y)), z(static_cast<T>(q.z)) +# else + : x(static_cast<T>(q.x)), y(static_cast<T>(q.y)), z(static_cast<T>(q.z)), w(static_cast<T>(q.w)) +# endif + {} + + //template<typename valType> + //GLM_FUNC_QUALIFIER qua<valType>::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<typename T, qualifier Q> + GLM_FUNC_QUALIFIER qua<T, Q>::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<T>(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<T>(0); + t = abs(u.x) > abs(u.z) ? vec<3, T, Q>(-u.y, u.x, static_cast<T>(0)) : vec<3, T, Q>(static_cast<T>(0), -u.z, u.y); + } + else + { + // Otherwise, build quaternion the standard way. + t = cross(u, v); + } + + *this = normalize(qua<T, Q>(real_part, t.x, t.y, t.z)); + } + + template<typename T, qualifier Q> + GLM_FUNC_QUALIFIER GLM_CONSTEXPR qua<T, Q>::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<typename T, qualifier Q> + GLM_FUNC_QUALIFIER qua<T, Q>::qua(mat<3, 3, T, Q> const& m) + { + *this = quat_cast(m); + } + + template<typename T, qualifier Q> + GLM_FUNC_QUALIFIER qua<T, Q>::qua(mat<4, 4, T, Q> const& m) + { + *this = quat_cast(m); + } + +# if GLM_HAS_EXPLICIT_CONVERSION_OPERATORS + template<typename T, qualifier Q> + GLM_FUNC_QUALIFIER qua<T, Q>::operator mat<3, 3, T, Q>() const + { + return mat3_cast(*this); + } + + template<typename T, qualifier Q> + GLM_FUNC_QUALIFIER qua<T, Q>::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<typename T, qualifier Q> + GLM_FUNC_QUALIFIER GLM_CONSTEXPR qua<T, Q> & qua<T, Q>::operator=(qua<T, Q> const& q) + { + this->w = q.w; + this->x = q.x; + this->y = q.y; + this->z = q.z; + return *this; + } +# endif + + template<typename T, qualifier Q> + template<typename U> + GLM_FUNC_QUALIFIER GLM_CONSTEXPR qua<T, Q> & qua<T, Q>::operator=(qua<U, Q> const& q) + { + this->w = static_cast<T>(q.w); + this->x = static_cast<T>(q.x); + this->y = static_cast<T>(q.y); + this->z = static_cast<T>(q.z); + return *this; + } + + template<typename T, qualifier Q> + template<typename U> + GLM_FUNC_QUALIFIER GLM_CONSTEXPR qua<T, Q> & qua<T, Q>::operator+=(qua<U, Q> const& q) + { + return (*this = detail::compute_quat_add<T, Q, detail::is_aligned<Q>::value>::call(*this, qua<T, Q>(q))); + } + + template<typename T, qualifier Q> + template<typename U> + GLM_FUNC_QUALIFIER GLM_CONSTEXPR qua<T, Q> & qua<T, Q>::operator-=(qua<U, Q> const& q) + { + return (*this = detail::compute_quat_sub<T, Q, detail::is_aligned<Q>::value>::call(*this, qua<T, Q>(q))); + } + + template<typename T, qualifier Q> + template<typename U> + GLM_FUNC_QUALIFIER GLM_CONSTEXPR qua<T, Q> & qua<T, Q>::operator*=(qua<U, Q> const& r) + { + qua<T, Q> const p(*this); + qua<T, Q> 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<typename T, qualifier Q> + template<typename U> + GLM_FUNC_QUALIFIER GLM_CONSTEXPR qua<T, Q> & qua<T, Q>::operator*=(U s) + { + return (*this = detail::compute_quat_mul_scalar<T, Q, detail::is_aligned<Q>::value>::call(*this, static_cast<U>(s))); + } + + template<typename T, qualifier Q> + template<typename U> + GLM_FUNC_QUALIFIER GLM_CONSTEXPR qua<T, Q> & qua<T, Q>::operator/=(U s) + { + return (*this = detail::compute_quat_div_scalar<T, Q, detail::is_aligned<Q>::value>::call(*this, static_cast<U>(s))); + } + + // -- Unary bit operators -- + + template<typename T, qualifier Q> + GLM_FUNC_QUALIFIER GLM_CONSTEXPR qua<T, Q> operator+(qua<T, Q> const& q) + { + return q; + } + + template<typename T, qualifier Q> + GLM_FUNC_QUALIFIER GLM_CONSTEXPR qua<T, Q> operator-(qua<T, Q> const& q) + { + return qua<T, Q>(-q.w, -q.x, -q.y, -q.z); + } + + // -- Binary operators -- + + template<typename T, qualifier Q> + GLM_FUNC_QUALIFIER GLM_CONSTEXPR qua<T, Q> operator+(qua<T, Q> const& q, qua<T, Q> const& p) + { + return qua<T, Q>(q) += p; + } + + template<typename T, qualifier Q> + GLM_FUNC_QUALIFIER GLM_CONSTEXPR qua<T, Q> operator-(qua<T, Q> const& q, qua<T, Q> const& p) + { + return qua<T, Q>(q) -= p; + } + + template<typename T, qualifier Q> + GLM_FUNC_QUALIFIER GLM_CONSTEXPR qua<T, Q> operator*(qua<T, Q> const& q, qua<T, Q> const& p) + { + return qua<T, Q>(q) *= p; + } + + template<typename T, qualifier Q> + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<3, T, Q> operator*(qua<T, Q> 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<T>(2); + } + + template<typename T, qualifier Q> + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<3, T, Q> operator*(vec<3, T, Q> const& v, qua<T, Q> const& q) + { + return glm::inverse(q) * v; + } + + template<typename T, qualifier Q> + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<4, T, Q> operator*(qua<T, Q> const& q, vec<4, T, Q> const& v) + { + return detail::compute_quat_mul_vec4<T, Q, detail::is_aligned<Q>::value>::call(q, v); + } + + template<typename T, qualifier Q> + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<4, T, Q> operator*(vec<4, T, Q> const& v, qua<T, Q> const& q) + { + return glm::inverse(q) * v; + } + + template<typename T, qualifier Q> + GLM_FUNC_QUALIFIER GLM_CONSTEXPR qua<T, Q> operator*(qua<T, Q> const& q, T const& s) + { + return qua<T, Q>( + q.w * s, q.x * s, q.y * s, q.z * s); + } + + template<typename T, qualifier Q> + GLM_FUNC_QUALIFIER GLM_CONSTEXPR qua<T, Q> operator*(T const& s, qua<T, Q> const& q) + { + return q * s; + } + + template<typename T, qualifier Q> + GLM_FUNC_QUALIFIER GLM_CONSTEXPR qua<T, Q> operator/(qua<T, Q> const& q, T const& s) + { + return qua<T, Q>( + q.w / s, q.x / s, q.y / s, q.z / s); + } + + // -- Boolean operators -- + + template<typename T, qualifier Q> + GLM_FUNC_QUALIFIER GLM_CONSTEXPR bool operator==(qua<T, Q> const& q1, qua<T, Q> const& q2) + { + return q1.x == q2.x && q1.y == q2.y && q1.z == q2.z && q1.w == q2.w; + } + + template<typename T, qualifier Q> + GLM_FUNC_QUALIFIER GLM_CONSTEXPR bool operator!=(qua<T, Q> const& q1, qua<T, Q> 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 0000000000000000000000000000000000000000..3333e59f1c7e2626b292d3100909027e400a0f16 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/detail/type_quat_simd.inl @@ -0,0 +1,188 @@ +/// @ref core + +#if GLM_ARCH & GLM_ARCH_SSE2_BIT + +namespace glm{ +namespace detail +{ +/* + template<qualifier Q> + struct compute_quat_mul<float, Q, true> + { + static qua<float, Q> call(qua<float, Q> const& q1, qua<float, Q> 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<float, Q> 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<qualifier Q> + struct compute_quat_add<float, Q, true> + { + static qua<float, Q> call(qua<float, Q> const& q, qua<float, Q> const& p) + { + qua<float, Q> Result; + Result.data = _mm_add_ps(q.data, p.data); + return Result; + } + }; + +# if GLM_ARCH & GLM_ARCH_AVX_BIT + template<qualifier Q> + struct compute_quat_add<double, Q, true> + { + static qua<double, Q> call(qua<double, Q> const& a, qua<double, Q> const& b) + { + qua<double, Q> Result; + Result.data = _mm256_add_pd(a.data, b.data); + return Result; + } + }; +# endif + + template<qualifier Q> + struct compute_quat_sub<float, Q, true> + { + static qua<float, Q> call(qua<float, Q> const& q, qua<float, Q> const& p) + { + vec<4, float, Q> Result; + Result.data = _mm_sub_ps(q.data, p.data); + return Result; + } + }; + +# if GLM_ARCH & GLM_ARCH_AVX_BIT + template<qualifier Q> + struct compute_quat_sub<double, Q, true> + { + static qua<double, Q> call(qua<double, Q> const& a, qua<double, Q> const& b) + { + qua<double, Q> Result; + Result.data = _mm256_sub_pd(a.data, b.data); + return Result; + } + }; +# endif + + template<qualifier Q> + struct compute_quat_mul_scalar<float, Q, true> + { + static qua<float, Q> call(qua<float, Q> 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<qualifier Q> + struct compute_quat_mul_scalar<double, Q, true> + { + static qua<double, Q> call(qua<double, Q> const& q, double s) + { + qua<double, Q> Result; + Result.data = _mm256_mul_pd(q.data, _mm_set_ps1(s)); + return Result; + } + }; +# endif + + template<qualifier Q> + struct compute_quat_div_scalar<float, Q, true> + { + static qua<float, Q> call(qua<float, Q> 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<qualifier Q> + struct compute_quat_div_scalar<double, Q, true> + { + static qua<double, Q> call(qua<double, Q> const& q, double s) + { + qua<double, Q> Result; + Result.data = _mm256_div_pd(q.data, _mm_set_ps1(s)); + return Result; + } + }; +# endif + + template<qualifier Q> + struct compute_quat_mul_vec4<float, Q, true> + { + static vec<4, float, Q> call(qua<float, Q> const& q, vec<4, float, Q> const& v) + { + __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; + } + }; +}//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 0000000000000000000000000000000000000000..51163f14bc88aeb1c3ad4ba3449de0dc38e5266e --- /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 <cstddef> + +namespace glm +{ + template<typename T, qualifier Q> + 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<Q>::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_FUNC_DECL GLM_CONSTEXPR vec() GLM_DEFAULT; + GLM_FUNC_DECL GLM_CONSTEXPR vec(vec const& v) GLM_DEFAULT; + template<qualifier P> + GLM_FUNC_DECL GLM_CONSTEXPR vec(vec<1, T, P> const& v); + + // -- Explicit basic constructors -- + + GLM_FUNC_DECL GLM_CONSTEXPR 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<typename U, qualifier P> + GLM_FUNC_DECL GLM_CONSTEXPR 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<typename U, qualifier P> + GLM_FUNC_DECL GLM_CONSTEXPR 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<typename U, qualifier P> + GLM_FUNC_DECL GLM_CONSTEXPR 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<typename U, qualifier P> + GLM_FUNC_DECL GLM_CONSTEXPR GLM_EXPLICIT vec(vec<1, U, P> const& v); + + // -- Swizzle constructors -- +/* +# if GLM_CONFIG_SWIZZLE == GLM_SWIZZLE_OPERATOR + template<int E0> + GLM_FUNC_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_FUNC_DECL GLM_CONSTEXPR vec<1, T, Q> & operator=(vec const& v) GLM_DEFAULT; + + template<typename U> + GLM_FUNC_DECL GLM_CONSTEXPR vec<1, T, Q> & operator=(vec<1, U, Q> const& v); + template<typename U> + GLM_FUNC_DECL GLM_CONSTEXPR vec<1, T, Q> & operator+=(U scalar); + template<typename U> + GLM_FUNC_DECL GLM_CONSTEXPR vec<1, T, Q> & operator+=(vec<1, U, Q> const& v); + template<typename U> + GLM_FUNC_DECL GLM_CONSTEXPR vec<1, T, Q> & operator-=(U scalar); + template<typename U> + GLM_FUNC_DECL GLM_CONSTEXPR vec<1, T, Q> & operator-=(vec<1, U, Q> const& v); + template<typename U> + GLM_FUNC_DECL GLM_CONSTEXPR vec<1, T, Q> & operator*=(U scalar); + template<typename U> + GLM_FUNC_DECL GLM_CONSTEXPR vec<1, T, Q> & operator*=(vec<1, U, Q> const& v); + template<typename U> + GLM_FUNC_DECL GLM_CONSTEXPR vec<1, T, Q> & operator/=(U scalar); + template<typename U> + GLM_FUNC_DECL GLM_CONSTEXPR vec<1, T, Q> & operator/=(vec<1, U, Q> const& v); + + // -- Increment and decrement operators -- + + GLM_FUNC_DECL GLM_CONSTEXPR vec<1, T, Q> & operator++(); + GLM_FUNC_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<typename U> + GLM_FUNC_DECL GLM_CONSTEXPR vec<1, T, Q> & operator%=(U scalar); + template<typename U> + GLM_FUNC_DECL GLM_CONSTEXPR vec<1, T, Q> & operator%=(vec<1, U, Q> const& v); + template<typename U> + GLM_FUNC_DECL GLM_CONSTEXPR vec<1, T, Q> & operator&=(U scalar); + template<typename U> + GLM_FUNC_DECL GLM_CONSTEXPR vec<1, T, Q> & operator&=(vec<1, U, Q> const& v); + template<typename U> + GLM_FUNC_DECL GLM_CONSTEXPR vec<1, T, Q> & operator|=(U scalar); + template<typename U> + GLM_FUNC_DECL GLM_CONSTEXPR vec<1, T, Q> & operator|=(vec<1, U, Q> const& v); + template<typename U> + GLM_FUNC_DECL GLM_CONSTEXPR vec<1, T, Q> & operator^=(U scalar); + template<typename U> + GLM_FUNC_DECL GLM_CONSTEXPR vec<1, T, Q> & operator^=(vec<1, U, Q> const& v); + template<typename U> + GLM_FUNC_DECL GLM_CONSTEXPR vec<1, T, Q> & operator<<=(U scalar); + template<typename U> + GLM_FUNC_DECL GLM_CONSTEXPR vec<1, T, Q> & operator<<=(vec<1, U, Q> const& v); + template<typename U> + GLM_FUNC_DECL GLM_CONSTEXPR vec<1, T, Q> & operator>>=(U scalar); + template<typename U> + GLM_FUNC_DECL GLM_CONSTEXPR vec<1, T, Q> & operator>>=(vec<1, U, Q> const& v); + }; + + // -- Unary operators -- + + template<typename T, qualifier Q> + GLM_FUNC_DECL GLM_CONSTEXPR vec<1, T, Q> operator+(vec<1, T, Q> const& v); + + template<typename T, qualifier Q> + GLM_FUNC_DECL GLM_CONSTEXPR vec<1, T, Q> operator-(vec<1, T, Q> const& v); + + // -- Binary operators -- + + template<typename T, qualifier Q> + GLM_FUNC_DECL GLM_CONSTEXPR vec<1, T, Q> operator+(vec<1, T, Q> const& v, T scalar); + + template<typename T, qualifier Q> + GLM_FUNC_DECL GLM_CONSTEXPR vec<1, T, Q> operator+(T scalar, vec<1, T, Q> const& v); + + template<typename T, qualifier Q> + GLM_FUNC_DECL GLM_CONSTEXPR vec<1, T, Q> operator+(vec<1, T, Q> const& v1, vec<1, T, Q> const& v2); + + template<typename T, qualifier Q> + GLM_FUNC_DECL GLM_CONSTEXPR vec<1, T, Q> operator-(vec<1, T, Q> const& v, T scalar); + + template<typename T, qualifier Q> + GLM_FUNC_DECL GLM_CONSTEXPR vec<1, T, Q> operator-(T scalar, vec<1, T, Q> const& v); + + template<typename T, qualifier Q> + GLM_FUNC_DECL GLM_CONSTEXPR vec<1, T, Q> operator-(vec<1, T, Q> const& v1, vec<1, T, Q> const& v2); + + template<typename T, qualifier Q> + GLM_FUNC_DECL GLM_CONSTEXPR vec<1, T, Q> operator*(vec<1, T, Q> const& v, T scalar); + + template<typename T, qualifier Q> + GLM_FUNC_DECL GLM_CONSTEXPR vec<1, T, Q> operator*(T scalar, vec<1, T, Q> const& v); + + template<typename T, qualifier Q> + GLM_FUNC_DECL GLM_CONSTEXPR vec<1, T, Q> operator*(vec<1, T, Q> const& v1, vec<1, T, Q> const& v2); + + template<typename T, qualifier Q> + GLM_FUNC_DECL GLM_CONSTEXPR vec<1, T, Q> operator/(vec<1, T, Q> const& v, T scalar); + + template<typename T, qualifier Q> + GLM_FUNC_DECL GLM_CONSTEXPR vec<1, T, Q> operator/(T scalar, vec<1, T, Q> const& v); + + template<typename T, qualifier Q> + GLM_FUNC_DECL GLM_CONSTEXPR vec<1, T, Q> operator/(vec<1, T, Q> const& v1, vec<1, T, Q> const& v2); + + template<typename T, qualifier Q> + GLM_FUNC_DECL GLM_CONSTEXPR vec<1, T, Q> operator%(vec<1, T, Q> const& v, T scalar); + + template<typename T, qualifier Q> + GLM_FUNC_DECL GLM_CONSTEXPR vec<1, T, Q> operator%(T scalar, vec<1, T, Q> const& v); + + template<typename T, qualifier Q> + GLM_FUNC_DECL GLM_CONSTEXPR vec<1, T, Q> operator%(vec<1, T, Q> const& v1, vec<1, T, Q> const& v2); + + template<typename T, qualifier Q> + GLM_FUNC_DECL GLM_CONSTEXPR vec<1, T, Q> operator&(vec<1, T, Q> const& v, T scalar); + + template<typename T, qualifier Q> + GLM_FUNC_DECL GLM_CONSTEXPR vec<1, T, Q> operator&(T scalar, vec<1, T, Q> const& v); + + template<typename T, qualifier Q> + GLM_FUNC_DECL GLM_CONSTEXPR vec<1, T, Q> operator&(vec<1, T, Q> const& v1, vec<1, T, Q> const& v2); + + template<typename T, qualifier Q> + GLM_FUNC_DECL GLM_CONSTEXPR vec<1, T, Q> operator|(vec<1, T, Q> const& v, T scalar); + + template<typename T, qualifier Q> + GLM_FUNC_DECL GLM_CONSTEXPR vec<1, T, Q> operator|(T scalar, vec<1, T, Q> const& v); + + template<typename T, qualifier Q> + GLM_FUNC_DECL GLM_CONSTEXPR vec<1, T, Q> operator|(vec<1, T, Q> const& v1, vec<1, T, Q> const& v2); + + template<typename T, qualifier Q> + GLM_FUNC_DECL GLM_CONSTEXPR vec<1, T, Q> operator^(vec<1, T, Q> const& v, T scalar); + + template<typename T, qualifier Q> + GLM_FUNC_DECL GLM_CONSTEXPR vec<1, T, Q> operator^(T scalar, vec<1, T, Q> const& v); + + template<typename T, qualifier Q> + GLM_FUNC_DECL GLM_CONSTEXPR vec<1, T, Q> operator^(vec<1, T, Q> const& v1, vec<1, T, Q> const& v2); + + template<typename T, qualifier Q> + GLM_FUNC_DECL GLM_CONSTEXPR vec<1, T, Q> operator<<(vec<1, T, Q> const& v, T scalar); + + template<typename T, qualifier Q> + GLM_FUNC_DECL GLM_CONSTEXPR vec<1, T, Q> operator<<(T scalar, vec<1, T, Q> const& v); + + template<typename T, qualifier Q> + GLM_FUNC_DECL GLM_CONSTEXPR vec<1, T, Q> operator<<(vec<1, T, Q> const& v1, vec<1, T, Q> const& v2); + + template<typename T, qualifier Q> + GLM_FUNC_DECL GLM_CONSTEXPR vec<1, T, Q> operator>>(vec<1, T, Q> const& v, T scalar); + + template<typename T, qualifier Q> + GLM_FUNC_DECL GLM_CONSTEXPR vec<1, T, Q> operator>>(T scalar, vec<1, T, Q> const& v); + + template<typename T, qualifier Q> + GLM_FUNC_DECL GLM_CONSTEXPR vec<1, T, Q> operator>>(vec<1, T, Q> const& v1, vec<1, T, Q> const& v2); + + template<typename T, qualifier Q> + GLM_FUNC_DECL GLM_CONSTEXPR vec<1, T, Q> operator~(vec<1, T, Q> const& v); + + // -- Boolean operators -- + + template<typename T, qualifier Q> + GLM_FUNC_DECL GLM_CONSTEXPR bool operator==(vec<1, T, Q> const& v1, vec<1, T, Q> const& v2); + + template<typename T, qualifier Q> + GLM_FUNC_DECL GLM_CONSTEXPR bool operator!=(vec<1, T, Q> const& v1, vec<1, T, Q> const& v2); + + template<qualifier Q> + GLM_FUNC_DECL GLM_CONSTEXPR vec<1, bool, Q> operator&&(vec<1, bool, Q> const& v1, vec<1, bool, Q> const& v2); + + template<qualifier Q> + 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 0000000000000000000000000000000000000000..c5883cebc96c258af9c21e0e33059412b30db384 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/detail/type_vec1.inl @@ -0,0 +1,551 @@ +/// @ref core + +#include "./compute_vector_relational.hpp" + +namespace glm +{ + // -- Implicit basic constructors -- + +# if GLM_CONFIG_DEFAULTED_FUNCTIONS == GLM_DISABLE + template<typename T, qualifier Q> + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<1, T, Q>::vec() +# if GLM_CONFIG_CTOR_INIT != GLM_CTOR_INIT_DISABLE + : x(0) +# endif + {} + + template<typename T, qualifier Q> + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<1, T, Q>::vec(vec<1, T, Q> const& v) + : x(v.x) + {} +# endif + + template<typename T, qualifier Q> + template<qualifier P> + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<1, T, Q>::vec(vec<1, T, P> const& v) + : x(v.x) + {} + + // -- Explicit basic constructors -- + + template<typename T, qualifier Q> + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<1, T, Q>::vec(T scalar) + : x(scalar) + {} + + // -- Conversion vector constructors -- + + template<typename T, qualifier Q> + template<typename U, qualifier P> + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<1, T, Q>::vec(vec<1, U, P> const& v) + : x(static_cast<T>(v.x)) + {} + + template<typename T, qualifier Q> + template<typename U, qualifier P> + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<1, T, Q>::vec(vec<2, U, P> const& v) + : x(static_cast<T>(v.x)) + {} + + template<typename T, qualifier Q> + template<typename U, qualifier P> + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<1, T, Q>::vec(vec<3, U, P> const& v) + : x(static_cast<T>(v.x)) + {} + + template<typename T, qualifier Q> + template<typename U, qualifier P> + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<1, T, Q>::vec(vec<4, U, P> const& v) + : x(static_cast<T>(v.x)) + {} + + // -- Component accesses -- + + template<typename T, qualifier Q> + GLM_FUNC_QUALIFIER GLM_CONSTEXPR T & vec<1, T, Q>::operator[](typename vec<1, T, Q>::length_type) + { + return x; + } + + template<typename T, qualifier Q> + 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<typename T, qualifier Q> + GLM_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<typename T, qualifier Q> + template<typename U> + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<1, T, Q> & vec<1, T, Q>::operator=(vec<1, U, Q> const& v) + { + this->x = static_cast<T>(v.x); + return *this; + } + + template<typename T, qualifier Q> + template<typename U> + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<1, T, Q> & vec<1, T, Q>::operator+=(U scalar) + { + this->x += static_cast<T>(scalar); + return *this; + } + + template<typename T, qualifier Q> + template<typename U> + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<1, T, Q> & vec<1, T, Q>::operator+=(vec<1, U, Q> const& v) + { + this->x += static_cast<T>(v.x); + return *this; + } + + template<typename T, qualifier Q> + template<typename U> + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<1, T, Q> & vec<1, T, Q>::operator-=(U scalar) + { + this->x -= static_cast<T>(scalar); + return *this; + } + + template<typename T, qualifier Q> + template<typename U> + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<1, T, Q> & vec<1, T, Q>::operator-=(vec<1, U, Q> const& v) + { + this->x -= static_cast<T>(v.x); + return *this; + } + + template<typename T, qualifier Q> + template<typename U> + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<1, T, Q> & vec<1, T, Q>::operator*=(U scalar) + { + this->x *= static_cast<T>(scalar); + return *this; + } + + template<typename T, qualifier Q> + template<typename U> + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<1, T, Q> & vec<1, T, Q>::operator*=(vec<1, U, Q> const& v) + { + this->x *= static_cast<T>(v.x); + return *this; + } + + template<typename T, qualifier Q> + template<typename U> + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<1, T, Q> & vec<1, T, Q>::operator/=(U scalar) + { + this->x /= static_cast<T>(scalar); + return *this; + } + + template<typename T, qualifier Q> + template<typename U> + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<1, T, Q> & vec<1, T, Q>::operator/=(vec<1, U, Q> const& v) + { + this->x /= static_cast<T>(v.x); + return *this; + } + + // -- Increment and decrement operators -- + + template<typename T, qualifier Q> + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<1, T, Q> & vec<1, T, Q>::operator++() + { + ++this->x; + return *this; + } + + template<typename T, qualifier Q> + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<1, T, Q> & vec<1, T, Q>::operator--() + { + --this->x; + return *this; + } + + template<typename T, qualifier Q> + 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<typename T, qualifier Q> + 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<typename T, qualifier Q> + template<typename U> + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<1, T, Q> & vec<1, T, Q>::operator%=(U scalar) + { + this->x %= static_cast<T>(scalar); + return *this; + } + + template<typename T, qualifier Q> + template<typename U> + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<1, T, Q> & vec<1, T, Q>::operator%=(vec<1, U, Q> const& v) + { + this->x %= static_cast<T>(v.x); + return *this; + } + + template<typename T, qualifier Q> + template<typename U> + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<1, T, Q> & vec<1, T, Q>::operator&=(U scalar) + { + this->x &= static_cast<T>(scalar); + return *this; + } + + template<typename T, qualifier Q> + template<typename U> + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<1, T, Q> & vec<1, T, Q>::operator&=(vec<1, U, Q> const& v) + { + this->x &= static_cast<T>(v.x); + return *this; + } + + template<typename T, qualifier Q> + template<typename U> + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<1, T, Q> & vec<1, T, Q>::operator|=(U scalar) + { + this->x |= static_cast<T>(scalar); + return *this; + } + + template<typename T, qualifier Q> + template<typename U> + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<1, T, Q> & vec<1, T, Q>::operator|=(vec<1, U, Q> const& v) + { + this->x |= U(v.x); + return *this; + } + + template<typename T, qualifier Q> + template<typename U> + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<1, T, Q> & vec<1, T, Q>::operator^=(U scalar) + { + this->x ^= static_cast<T>(scalar); + return *this; + } + + template<typename T, qualifier Q> + template<typename U> + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<1, T, Q> & vec<1, T, Q>::operator^=(vec<1, U, Q> const& v) + { + this->x ^= static_cast<T>(v.x); + return *this; + } + + template<typename T, qualifier Q> + template<typename U> + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<1, T, Q> & vec<1, T, Q>::operator<<=(U scalar) + { + this->x <<= static_cast<T>(scalar); + return *this; + } + + template<typename T, qualifier Q> + template<typename U> + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<1, T, Q> & vec<1, T, Q>::operator<<=(vec<1, U, Q> const& v) + { + this->x <<= static_cast<T>(v.x); + return *this; + } + + template<typename T, qualifier Q> + template<typename U> + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<1, T, Q> & vec<1, T, Q>::operator>>=(U scalar) + { + this->x >>= static_cast<T>(scalar); + return *this; + } + + template<typename T, qualifier Q> + template<typename U> + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<1, T, Q> & vec<1, T, Q>::operator>>=(vec<1, U, Q> const& v) + { + this->x >>= static_cast<T>(v.x); + return *this; + } + + // -- Unary constant operators -- + + template<typename T, qualifier Q> + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<1, T, Q> operator+(vec<1, T, Q> const& v) + { + return v; + } + + template<typename T, qualifier Q> + 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<typename T, qualifier Q> + 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<typename T, qualifier Q> + 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<typename T, qualifier Q> + 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<typename T, qualifier Q> + 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<typename T, qualifier Q> + 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<typename T, qualifier Q> + 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<typename T, qualifier Q> + 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<typename T, qualifier Q> + 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<typename T, qualifier Q> + 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<typename T, qualifier Q> + 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<typename T, qualifier Q> + 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<typename T, qualifier Q> + 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<typename T, qualifier Q> + 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<typename T, qualifier Q> + 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<typename T, qualifier Q> + 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<typename T, qualifier Q> + 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<typename T, qualifier Q> + 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<typename T, qualifier Q> + 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<typename T, qualifier Q> + 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<typename T, qualifier Q> + 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<typename T, qualifier Q> + 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<typename T, qualifier Q> + 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<typename T, qualifier Q> + 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<typename T, qualifier Q> + 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<typename T, qualifier Q> + 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<T>(v.x << scalar)); + } + + template<typename T, qualifier Q> + 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<T>(scalar << v.x)); + } + + template<typename T, qualifier Q> + 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<T>(v1.x << v2.x)); + } + + template<typename T, qualifier Q> + 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<T>(v.x >> scalar)); + } + + template<typename T, qualifier Q> + 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<T>(scalar >> v.x)); + } + + template<typename T, qualifier Q> + 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<T>(v1.x >> v2.x)); + } + + template<typename T, qualifier Q> + 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<typename T, qualifier Q> + GLM_FUNC_QUALIFIER GLM_CONSTEXPR bool operator==(vec<1, T, Q> const& v1, vec<1, T, Q> const& v2) + { + return detail::compute_equal<T, std::numeric_limits<T>::is_iec559>::call(v1.x, v2.x); + } + + template<typename T, qualifier Q> + GLM_FUNC_QUALIFIER GLM_CONSTEXPR bool operator!=(vec<1, T, Q> const& v1, vec<1, T, Q> const& v2) + { + return !(v1 == v2); + } + + template<qualifier Q> + 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<qualifier Q> + 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 0000000000000000000000000000000000000000..52ef408e5d2165623e764cfa664fcb8372361bf6 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/detail/type_vec2.hpp @@ -0,0 +1,399 @@ +/// @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 <cstddef> + +namespace glm +{ + template<typename T, qualifier Q> + 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; +# 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<Q>::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_FUNC_DECL GLM_CONSTEXPR vec() GLM_DEFAULT; + GLM_FUNC_DECL GLM_CONSTEXPR vec(vec const& v) GLM_DEFAULT; + template<qualifier P> + GLM_FUNC_DECL GLM_CONSTEXPR vec(vec<2, T, P> const& v); + + // -- Explicit basic constructors -- + + GLM_FUNC_DECL GLM_CONSTEXPR explicit vec(T scalar); + GLM_FUNC_DECL GLM_CONSTEXPR vec(T x, T y); + + // -- Conversion constructors -- + + template<typename U, qualifier P> + GLM_FUNC_DECL GLM_CONSTEXPR 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<typename A, typename B> + GLM_FUNC_DECL GLM_CONSTEXPR vec(A x, B y); + template<typename A, typename B> + GLM_FUNC_DECL GLM_CONSTEXPR vec(vec<1, A, Q> const& x, B y); + template<typename A, typename B> + GLM_FUNC_DECL GLM_CONSTEXPR vec(A x, vec<1, B, Q> const& y); + template<typename A, typename B> + GLM_FUNC_DECL GLM_CONSTEXPR 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<typename U, qualifier P> + GLM_FUNC_DECL GLM_CONSTEXPR 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<typename U, qualifier P> + GLM_FUNC_DECL GLM_CONSTEXPR 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<typename U, qualifier P> + GLM_FUNC_DECL GLM_CONSTEXPR GLM_EXPLICIT vec(vec<2, U, P> const& v); + + // -- Swizzle constructors -- +# if GLM_CONFIG_SWIZZLE == GLM_SWIZZLE_OPERATOR + template<int E0, int E1> + GLM_FUNC_DECL GLM_CONSTEXPR 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_FUNC_DECL GLM_CONSTEXPR vec<2, T, Q> & operator=(vec const& v) GLM_DEFAULT; + + template<typename U> + GLM_FUNC_DECL GLM_CONSTEXPR vec<2, T, Q> & operator=(vec<2, U, Q> const& v); + template<typename U> + GLM_FUNC_DECL GLM_CONSTEXPR vec<2, T, Q> & operator+=(U scalar); + template<typename U> + GLM_FUNC_DECL GLM_CONSTEXPR vec<2, T, Q> & operator+=(vec<1, U, Q> const& v); + template<typename U> + GLM_FUNC_DECL GLM_CONSTEXPR vec<2, T, Q> & operator+=(vec<2, U, Q> const& v); + template<typename U> + GLM_FUNC_DECL GLM_CONSTEXPR vec<2, T, Q> & operator-=(U scalar); + template<typename U> + GLM_FUNC_DECL GLM_CONSTEXPR vec<2, T, Q> & operator-=(vec<1, U, Q> const& v); + template<typename U> + GLM_FUNC_DECL GLM_CONSTEXPR vec<2, T, Q> & operator-=(vec<2, U, Q> const& v); + template<typename U> + GLM_FUNC_DECL GLM_CONSTEXPR vec<2, T, Q> & operator*=(U scalar); + template<typename U> + GLM_FUNC_DECL GLM_CONSTEXPR vec<2, T, Q> & operator*=(vec<1, U, Q> const& v); + template<typename U> + GLM_FUNC_DECL GLM_CONSTEXPR vec<2, T, Q> & operator*=(vec<2, U, Q> const& v); + template<typename U> + GLM_FUNC_DECL GLM_CONSTEXPR vec<2, T, Q> & operator/=(U scalar); + template<typename U> + GLM_FUNC_DECL GLM_CONSTEXPR vec<2, T, Q> & operator/=(vec<1, U, Q> const& v); + template<typename U> + GLM_FUNC_DECL GLM_CONSTEXPR vec<2, T, Q> & operator/=(vec<2, U, Q> const& v); + + // -- Increment and decrement operators -- + + GLM_FUNC_DECL GLM_CONSTEXPR vec<2, T, Q> & operator++(); + GLM_FUNC_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<typename U> + GLM_FUNC_DECL GLM_CONSTEXPR vec<2, T, Q> & operator%=(U scalar); + template<typename U> + GLM_FUNC_DECL GLM_CONSTEXPR vec<2, T, Q> & operator%=(vec<1, U, Q> const& v); + template<typename U> + GLM_FUNC_DECL GLM_CONSTEXPR vec<2, T, Q> & operator%=(vec<2, U, Q> const& v); + template<typename U> + GLM_FUNC_DECL GLM_CONSTEXPR vec<2, T, Q> & operator&=(U scalar); + template<typename U> + GLM_FUNC_DECL GLM_CONSTEXPR vec<2, T, Q> & operator&=(vec<1, U, Q> const& v); + template<typename U> + GLM_FUNC_DECL GLM_CONSTEXPR vec<2, T, Q> & operator&=(vec<2, U, Q> const& v); + template<typename U> + GLM_FUNC_DECL GLM_CONSTEXPR vec<2, T, Q> & operator|=(U scalar); + template<typename U> + GLM_FUNC_DECL GLM_CONSTEXPR vec<2, T, Q> & operator|=(vec<1, U, Q> const& v); + template<typename U> + GLM_FUNC_DECL GLM_CONSTEXPR vec<2, T, Q> & operator|=(vec<2, U, Q> const& v); + template<typename U> + GLM_FUNC_DECL GLM_CONSTEXPR vec<2, T, Q> & operator^=(U scalar); + template<typename U> + GLM_FUNC_DECL GLM_CONSTEXPR vec<2, T, Q> & operator^=(vec<1, U, Q> const& v); + template<typename U> + GLM_FUNC_DECL GLM_CONSTEXPR vec<2, T, Q> & operator^=(vec<2, U, Q> const& v); + template<typename U> + GLM_FUNC_DECL GLM_CONSTEXPR vec<2, T, Q> & operator<<=(U scalar); + template<typename U> + GLM_FUNC_DECL GLM_CONSTEXPR vec<2, T, Q> & operator<<=(vec<1, U, Q> const& v); + template<typename U> + GLM_FUNC_DECL GLM_CONSTEXPR vec<2, T, Q> & operator<<=(vec<2, U, Q> const& v); + template<typename U> + GLM_FUNC_DECL GLM_CONSTEXPR vec<2, T, Q> & operator>>=(U scalar); + template<typename U> + GLM_FUNC_DECL GLM_CONSTEXPR vec<2, T, Q> & operator>>=(vec<1, U, Q> const& v); + template<typename U> + GLM_FUNC_DECL GLM_CONSTEXPR vec<2, T, Q> & operator>>=(vec<2, U, Q> const& v); + }; + + // -- Unary operators -- + + template<typename T, qualifier Q> + GLM_FUNC_DECL GLM_CONSTEXPR vec<2, T, Q> operator+(vec<2, T, Q> const& v); + + template<typename T, qualifier Q> + GLM_FUNC_DECL GLM_CONSTEXPR vec<2, T, Q> operator-(vec<2, T, Q> const& v); + + // -- Binary operators -- + + template<typename T, qualifier Q> + GLM_FUNC_DECL GLM_CONSTEXPR vec<2, T, Q> operator+(vec<2, T, Q> const& v, T scalar); + + template<typename T, qualifier Q> + GLM_FUNC_DECL GLM_CONSTEXPR vec<2, T, Q> operator+(vec<2, T, Q> const& v1, vec<1, T, Q> const& v2); + + template<typename T, qualifier Q> + GLM_FUNC_DECL GLM_CONSTEXPR vec<2, T, Q> operator+(T scalar, vec<2, T, Q> const& v); + + template<typename T, qualifier Q> + GLM_FUNC_DECL GLM_CONSTEXPR vec<2, T, Q> operator+(vec<1, T, Q> const& v1, vec<2, T, Q> const& v2); + + template<typename T, qualifier Q> + GLM_FUNC_DECL GLM_CONSTEXPR vec<2, T, Q> operator+(vec<2, T, Q> const& v1, vec<2, T, Q> const& v2); + + template<typename T, qualifier Q> + GLM_FUNC_DECL GLM_CONSTEXPR vec<2, T, Q> operator-(vec<2, T, Q> const& v, T scalar); + + template<typename T, qualifier Q> + GLM_FUNC_DECL GLM_CONSTEXPR vec<2, T, Q> operator-(vec<2, T, Q> const& v1, vec<1, T, Q> const& v2); + + template<typename T, qualifier Q> + GLM_FUNC_DECL GLM_CONSTEXPR vec<2, T, Q> operator-(T scalar, vec<2, T, Q> const& v); + + template<typename T, qualifier Q> + GLM_FUNC_DECL GLM_CONSTEXPR vec<2, T, Q> operator-(vec<1, T, Q> const& v1, vec<2, T, Q> const& v2); + + template<typename T, qualifier Q> + GLM_FUNC_DECL GLM_CONSTEXPR vec<2, T, Q> operator-(vec<2, T, Q> const& v1, vec<2, T, Q> const& v2); + + template<typename T, qualifier Q> + GLM_FUNC_DECL GLM_CONSTEXPR vec<2, T, Q> operator*(vec<2, T, Q> const& v, T scalar); + + template<typename T, qualifier Q> + GLM_FUNC_DECL GLM_CONSTEXPR vec<2, T, Q> operator*(vec<2, T, Q> const& v1, vec<1, T, Q> const& v2); + + template<typename T, qualifier Q> + GLM_FUNC_DECL GLM_CONSTEXPR vec<2, T, Q> operator*(T scalar, vec<2, T, Q> const& v); + + template<typename T, qualifier Q> + GLM_FUNC_DECL GLM_CONSTEXPR vec<2, T, Q> operator*(vec<1, T, Q> const& v1, vec<2, T, Q> const& v2); + + template<typename T, qualifier Q> + GLM_FUNC_DECL GLM_CONSTEXPR vec<2, T, Q> operator*(vec<2, T, Q> const& v1, vec<2, T, Q> const& v2); + + template<typename T, qualifier Q> + GLM_FUNC_DECL GLM_CONSTEXPR vec<2, T, Q> operator/(vec<2, T, Q> const& v, T scalar); + + template<typename T, qualifier Q> + GLM_FUNC_DECL GLM_CONSTEXPR vec<2, T, Q> operator/(vec<2, T, Q> const& v1, vec<1, T, Q> const& v2); + + template<typename T, qualifier Q> + GLM_FUNC_DECL GLM_CONSTEXPR vec<2, T, Q> operator/(T scalar, vec<2, T, Q> const& v); + + template<typename T, qualifier Q> + GLM_FUNC_DECL GLM_CONSTEXPR vec<2, T, Q> operator/(vec<1, T, Q> const& v1, vec<2, T, Q> const& v2); + + template<typename T, qualifier Q> + GLM_FUNC_DECL GLM_CONSTEXPR vec<2, T, Q> operator/(vec<2, T, Q> const& v1, vec<2, T, Q> const& v2); + + template<typename T, qualifier Q> + GLM_FUNC_DECL GLM_CONSTEXPR vec<2, T, Q> operator%(vec<2, T, Q> const& v, T scalar); + + template<typename T, qualifier Q> + GLM_FUNC_DECL GLM_CONSTEXPR vec<2, T, Q> operator%(vec<2, T, Q> const& v1, vec<1, T, Q> const& v2); + + template<typename T, qualifier Q> + GLM_FUNC_DECL GLM_CONSTEXPR vec<2, T, Q> operator%(T scalar, vec<2, T, Q> const& v); + + template<typename T, qualifier Q> + GLM_FUNC_DECL GLM_CONSTEXPR vec<2, T, Q> operator%(vec<1, T, Q> const& v1, vec<2, T, Q> const& v2); + + template<typename T, qualifier Q> + GLM_FUNC_DECL GLM_CONSTEXPR vec<2, T, Q> operator%(vec<2, T, Q> const& v1, vec<2, T, Q> const& v2); + + template<typename T, qualifier Q> + GLM_FUNC_DECL GLM_CONSTEXPR vec<2, T, Q> operator&(vec<2, T, Q> const& v, T scalar); + + template<typename T, qualifier Q> + GLM_FUNC_DECL GLM_CONSTEXPR vec<2, T, Q> operator&(vec<2, T, Q> const& v1, vec<1, T, Q> const& v2); + + template<typename T, qualifier Q> + GLM_FUNC_DECL GLM_CONSTEXPR vec<2, T, Q> operator&(T scalar, vec<2, T, Q> const& v); + + template<typename T, qualifier Q> + GLM_FUNC_DECL GLM_CONSTEXPR vec<2, T, Q> operator&(vec<1, T, Q> const& v1, vec<2, T, Q> const& v2); + + template<typename T, qualifier Q> + GLM_FUNC_DECL GLM_CONSTEXPR vec<2, T, Q> operator&(vec<2, T, Q> const& v1, vec<2, T, Q> const& v2); + + template<typename T, qualifier Q> + GLM_FUNC_DECL GLM_CONSTEXPR vec<2, T, Q> operator|(vec<2, T, Q> const& v, T scalar); + + template<typename T, qualifier Q> + GLM_FUNC_DECL GLM_CONSTEXPR vec<2, T, Q> operator|(vec<2, T, Q> const& v1, vec<1, T, Q> const& v2); + + template<typename T, qualifier Q> + GLM_FUNC_DECL GLM_CONSTEXPR vec<2, T, Q> operator|(T scalar, vec<2, T, Q> const& v); + + template<typename T, qualifier Q> + GLM_FUNC_DECL GLM_CONSTEXPR vec<2, T, Q> operator|(vec<1, T, Q> const& v1, vec<2, T, Q> const& v2); + + template<typename T, qualifier Q> + GLM_FUNC_DECL GLM_CONSTEXPR vec<2, T, Q> operator|(vec<2, T, Q> const& v1, vec<2, T, Q> const& v2); + + template<typename T, qualifier Q> + GLM_FUNC_DECL GLM_CONSTEXPR vec<2, T, Q> operator^(vec<2, T, Q> const& v, T scalar); + + template<typename T, qualifier Q> + GLM_FUNC_DECL GLM_CONSTEXPR vec<2, T, Q> operator^(vec<2, T, Q> const& v1, vec<1, T, Q> const& v2); + + template<typename T, qualifier Q> + GLM_FUNC_DECL GLM_CONSTEXPR vec<2, T, Q> operator^(T scalar, vec<2, T, Q> const& v); + + template<typename T, qualifier Q> + GLM_FUNC_DECL GLM_CONSTEXPR vec<2, T, Q> operator^(vec<1, T, Q> const& v1, vec<2, T, Q> const& v2); + + template<typename T, qualifier Q> + GLM_FUNC_DECL GLM_CONSTEXPR vec<2, T, Q> operator^(vec<2, T, Q> const& v1, vec<2, T, Q> const& v2); + + template<typename T, qualifier Q> + GLM_FUNC_DECL GLM_CONSTEXPR vec<2, T, Q> operator<<(vec<2, T, Q> const& v, T scalar); + + template<typename T, qualifier Q> + GLM_FUNC_DECL GLM_CONSTEXPR vec<2, T, Q> operator<<(vec<2, T, Q> const& v1, vec<1, T, Q> const& v2); + + template<typename T, qualifier Q> + GLM_FUNC_DECL GLM_CONSTEXPR vec<2, T, Q> operator<<(T scalar, vec<2, T, Q> const& v); + + template<typename T, qualifier Q> + GLM_FUNC_DECL GLM_CONSTEXPR vec<2, T, Q> operator<<(vec<1, T, Q> const& v1, vec<2, T, Q> const& v2); + + template<typename T, qualifier Q> + GLM_FUNC_DECL GLM_CONSTEXPR vec<2, T, Q> operator<<(vec<2, T, Q> const& v1, vec<2, T, Q> const& v2); + + template<typename T, qualifier Q> + GLM_FUNC_DECL GLM_CONSTEXPR vec<2, T, Q> operator>>(vec<2, T, Q> const& v, T scalar); + + template<typename T, qualifier Q> + GLM_FUNC_DECL GLM_CONSTEXPR vec<2, T, Q> operator>>(vec<2, T, Q> const& v1, vec<1, T, Q> const& v2); + + template<typename T, qualifier Q> + GLM_FUNC_DECL GLM_CONSTEXPR vec<2, T, Q> operator>>(T scalar, vec<2, T, Q> const& v); + + template<typename T, qualifier Q> + GLM_FUNC_DECL GLM_CONSTEXPR vec<2, T, Q> operator>>(vec<1, T, Q> const& v1, vec<2, T, Q> const& v2); + + template<typename T, qualifier Q> + GLM_FUNC_DECL GLM_CONSTEXPR vec<2, T, Q> operator>>(vec<2, T, Q> const& v1, vec<2, T, Q> const& v2); + + template<typename T, qualifier Q> + GLM_FUNC_DECL GLM_CONSTEXPR vec<2, T, Q> operator~(vec<2, T, Q> const& v); + + // -- Boolean operators -- + + template<typename T, qualifier Q> + GLM_FUNC_DECL GLM_CONSTEXPR bool operator==(vec<2, T, Q> const& v1, vec<2, T, Q> const& v2); + + template<typename T, qualifier Q> + GLM_FUNC_DECL GLM_CONSTEXPR bool operator!=(vec<2, T, Q> const& v1, vec<2, T, Q> const& v2); + + template<qualifier Q> + GLM_FUNC_DECL GLM_CONSTEXPR vec<2, bool, Q> operator&&(vec<2, bool, Q> const& v1, vec<2, bool, Q> const& v2); + + template<qualifier Q> + 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 0000000000000000000000000000000000000000..8e65d6bb9e2e358c6284404b84dda0373b2f90fe --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/detail/type_vec2.inl @@ -0,0 +1,913 @@ +/// @ref core + +#include "./compute_vector_relational.hpp" + +namespace glm +{ + // -- Implicit basic constructors -- + +# if GLM_CONFIG_DEFAULTED_FUNCTIONS == GLM_DISABLE + template<typename T, qualifier Q> + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<2, T, Q>::vec() +# if GLM_CONFIG_CTOR_INIT != GLM_CTOR_INIT_DISABLE + : x(0), y(0) +# endif + {} + + template<typename T, qualifier Q> + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<2, T, Q>::vec(vec<2, T, Q> const& v) + : x(v.x), y(v.y) + {} +# endif + + template<typename T, qualifier Q> + template<qualifier P> + 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<typename T, qualifier Q> + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<2, T, Q>::vec(T scalar) + : x(scalar), y(scalar) + {} + + template<typename T, qualifier Q> + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<2, T, Q>::vec(T _x, T _y) + : x(_x), y(_y) + {} + + // -- Conversion scalar constructors -- + + template<typename T, qualifier Q> + template<typename U, qualifier P> + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<2, T, Q>::vec(vec<1, U, P> const& v) + : x(static_cast<T>(v.x)) + , y(static_cast<T>(v.x)) + {} + + template<typename T, qualifier Q> + template<typename A, typename B> + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<2, T, Q>::vec(A _x, B _y) + : x(static_cast<T>(_x)) + , y(static_cast<T>(_y)) + {} + + template<typename T, qualifier Q> + template<typename A, typename B> + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<2, T, Q>::vec(vec<1, A, Q> const& _x, B _y) + : x(static_cast<T>(_x.x)) + , y(static_cast<T>(_y)) + {} + + template<typename T, qualifier Q> + template<typename A, typename B> + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<2, T, Q>::vec(A _x, vec<1, B, Q> const& _y) + : x(static_cast<T>(_x)) + , y(static_cast<T>(_y.x)) + {} + + template<typename T, qualifier Q> + template<typename A, typename B> + 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<T>(_x.x)) + , y(static_cast<T>(_y.x)) + {} + + // -- Conversion vector constructors -- + + template<typename T, qualifier Q> + template<typename U, qualifier P> + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<2, T, Q>::vec(vec<2, U, P> const& v) + : x(static_cast<T>(v.x)) + , y(static_cast<T>(v.y)) + {} + + template<typename T, qualifier Q> + template<typename U, qualifier P> + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<2, T, Q>::vec(vec<3, U, P> const& v) + : x(static_cast<T>(v.x)) + , y(static_cast<T>(v.y)) + {} + + template<typename T, qualifier Q> + template<typename U, qualifier P> + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<2, T, Q>::vec(vec<4, U, P> const& v) + : x(static_cast<T>(v.x)) + , y(static_cast<T>(v.y)) + {} + + // -- Component accesses -- + + template<typename T, qualifier Q> + GLM_FUNC_QUALIFIER GLM_CONSTEXPR T & vec<2, T, Q>::operator[](typename vec<2, T, Q>::length_type i) + { + assert(i >= 0 && i < this->length()); + switch(i) + { + default: + case 0: + return x; + case 1: + return y; + } + } + + template<typename T, qualifier Q> + GLM_FUNC_QUALIFIER GLM_CONSTEXPR T const& vec<2, T, Q>::operator[](typename vec<2, T, Q>::length_type i) const + { + assert(i >= 0 && 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<typename T, qualifier Q> + GLM_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<typename T, qualifier Q> + template<typename U> + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<2, T, Q> & vec<2, T, Q>::operator=(vec<2, U, Q> const& v) + { + this->x = static_cast<T>(v.x); + this->y = static_cast<T>(v.y); + return *this; + } + + template<typename T, qualifier Q> + template<typename U> + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<2, T, Q> & vec<2, T, Q>::operator+=(U scalar) + { + this->x += static_cast<T>(scalar); + this->y += static_cast<T>(scalar); + return *this; + } + + template<typename T, qualifier Q> + template<typename U> + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<2, T, Q> & vec<2, T, Q>::operator+=(vec<1, U, Q> const& v) + { + this->x += static_cast<T>(v.x); + this->y += static_cast<T>(v.x); + return *this; + } + + template<typename T, qualifier Q> + template<typename U> + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<2, T, Q> & vec<2, T, Q>::operator+=(vec<2, U, Q> const& v) + { + this->x += static_cast<T>(v.x); + this->y += static_cast<T>(v.y); + return *this; + } + + template<typename T, qualifier Q> + template<typename U> + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<2, T, Q> & vec<2, T, Q>::operator-=(U scalar) + { + this->x -= static_cast<T>(scalar); + this->y -= static_cast<T>(scalar); + return *this; + } + + template<typename T, qualifier Q> + template<typename U> + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<2, T, Q> & vec<2, T, Q>::operator-=(vec<1, U, Q> const& v) + { + this->x -= static_cast<T>(v.x); + this->y -= static_cast<T>(v.x); + return *this; + } + + template<typename T, qualifier Q> + template<typename U> + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<2, T, Q> & vec<2, T, Q>::operator-=(vec<2, U, Q> const& v) + { + this->x -= static_cast<T>(v.x); + this->y -= static_cast<T>(v.y); + return *this; + } + + template<typename T, qualifier Q> + template<typename U> + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<2, T, Q> & vec<2, T, Q>::operator*=(U scalar) + { + this->x *= static_cast<T>(scalar); + this->y *= static_cast<T>(scalar); + return *this; + } + + template<typename T, qualifier Q> + template<typename U> + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<2, T, Q> & vec<2, T, Q>::operator*=(vec<1, U, Q> const& v) + { + this->x *= static_cast<T>(v.x); + this->y *= static_cast<T>(v.x); + return *this; + } + + template<typename T, qualifier Q> + template<typename U> + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<2, T, Q> & vec<2, T, Q>::operator*=(vec<2, U, Q> const& v) + { + this->x *= static_cast<T>(v.x); + this->y *= static_cast<T>(v.y); + return *this; + } + + template<typename T, qualifier Q> + template<typename U> + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<2, T, Q> & vec<2, T, Q>::operator/=(U scalar) + { + this->x /= static_cast<T>(scalar); + this->y /= static_cast<T>(scalar); + return *this; + } + + template<typename T, qualifier Q> + template<typename U> + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<2, T, Q> & vec<2, T, Q>::operator/=(vec<1, U, Q> const& v) + { + this->x /= static_cast<T>(v.x); + this->y /= static_cast<T>(v.x); + return *this; + } + + template<typename T, qualifier Q> + template<typename U> + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<2, T, Q> & vec<2, T, Q>::operator/=(vec<2, U, Q> const& v) + { + this->x /= static_cast<T>(v.x); + this->y /= static_cast<T>(v.y); + return *this; + } + + // -- Increment and decrement operators -- + + template<typename T, qualifier Q> + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<2, T, Q> & vec<2, T, Q>::operator++() + { + ++this->x; + ++this->y; + return *this; + } + + template<typename T, qualifier Q> + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<2, T, Q> & vec<2, T, Q>::operator--() + { + --this->x; + --this->y; + return *this; + } + + template<typename T, qualifier Q> + 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<typename T, qualifier Q> + 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<typename T, qualifier Q> + template<typename U> + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<2, T, Q> & vec<2, T, Q>::operator%=(U scalar) + { + this->x %= static_cast<T>(scalar); + this->y %= static_cast<T>(scalar); + return *this; + } + + template<typename T, qualifier Q> + template<typename U> + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<2, T, Q> & vec<2, T, Q>::operator%=(vec<1, U, Q> const& v) + { + this->x %= static_cast<T>(v.x); + this->y %= static_cast<T>(v.x); + return *this; + } + + template<typename T, qualifier Q> + template<typename U> + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<2, T, Q> & vec<2, T, Q>::operator%=(vec<2, U, Q> const& v) + { + this->x %= static_cast<T>(v.x); + this->y %= static_cast<T>(v.y); + return *this; + } + + template<typename T, qualifier Q> + template<typename U> + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<2, T, Q> & vec<2, T, Q>::operator&=(U scalar) + { + this->x &= static_cast<T>(scalar); + this->y &= static_cast<T>(scalar); + return *this; + } + + template<typename T, qualifier Q> + template<typename U> + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<2, T, Q> & vec<2, T, Q>::operator&=(vec<1, U, Q> const& v) + { + this->x &= static_cast<T>(v.x); + this->y &= static_cast<T>(v.x); + return *this; + } + + template<typename T, qualifier Q> + template<typename U> + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<2, T, Q> & vec<2, T, Q>::operator&=(vec<2, U, Q> const& v) + { + this->x &= static_cast<T>(v.x); + this->y &= static_cast<T>(v.y); + return *this; + } + + template<typename T, qualifier Q> + template<typename U> + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<2, T, Q> & vec<2, T, Q>::operator|=(U scalar) + { + this->x |= static_cast<T>(scalar); + this->y |= static_cast<T>(scalar); + return *this; + } + + template<typename T, qualifier Q> + template<typename U> + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<2, T, Q> & vec<2, T, Q>::operator|=(vec<1, U, Q> const& v) + { + this->x |= static_cast<T>(v.x); + this->y |= static_cast<T>(v.x); + return *this; + } + + template<typename T, qualifier Q> + template<typename U> + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<2, T, Q> & vec<2, T, Q>::operator|=(vec<2, U, Q> const& v) + { + this->x |= static_cast<T>(v.x); + this->y |= static_cast<T>(v.y); + return *this; + } + + template<typename T, qualifier Q> + template<typename U> + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<2, T, Q> & vec<2, T, Q>::operator^=(U scalar) + { + this->x ^= static_cast<T>(scalar); + this->y ^= static_cast<T>(scalar); + return *this; + } + + template<typename T, qualifier Q> + template<typename U> + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<2, T, Q> & vec<2, T, Q>::operator^=(vec<1, U, Q> const& v) + { + this->x ^= static_cast<T>(v.x); + this->y ^= static_cast<T>(v.x); + return *this; + } + + template<typename T, qualifier Q> + template<typename U> + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<2, T, Q> & vec<2, T, Q>::operator^=(vec<2, U, Q> const& v) + { + this->x ^= static_cast<T>(v.x); + this->y ^= static_cast<T>(v.y); + return *this; + } + + template<typename T, qualifier Q> + template<typename U> + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<2, T, Q> & vec<2, T, Q>::operator<<=(U scalar) + { + this->x <<= static_cast<T>(scalar); + this->y <<= static_cast<T>(scalar); + return *this; + } + + template<typename T, qualifier Q> + template<typename U> + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<2, T, Q> & vec<2, T, Q>::operator<<=(vec<1, U, Q> const& v) + { + this->x <<= static_cast<T>(v.x); + this->y <<= static_cast<T>(v.x); + return *this; + } + + template<typename T, qualifier Q> + template<typename U> + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<2, T, Q> & vec<2, T, Q>::operator<<=(vec<2, U, Q> const& v) + { + this->x <<= static_cast<T>(v.x); + this->y <<= static_cast<T>(v.y); + return *this; + } + + template<typename T, qualifier Q> + template<typename U> + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<2, T, Q> & vec<2, T, Q>::operator>>=(U scalar) + { + this->x >>= static_cast<T>(scalar); + this->y >>= static_cast<T>(scalar); + return *this; + } + + template<typename T, qualifier Q> + template<typename U> + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<2, T, Q> & vec<2, T, Q>::operator>>=(vec<1, U, Q> const& v) + { + this->x >>= static_cast<T>(v.x); + this->y >>= static_cast<T>(v.x); + return *this; + } + + template<typename T, qualifier Q> + template<typename U> + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<2, T, Q> & vec<2, T, Q>::operator>>=(vec<2, U, Q> const& v) + { + this->x >>= static_cast<T>(v.x); + this->y >>= static_cast<T>(v.y); + return *this; + } + + // -- Unary arithmetic operators -- + + template<typename T, qualifier Q> + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<2, T, Q> operator+(vec<2, T, Q> const& v) + { + return v; + } + + template<typename T, qualifier Q> + 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<typename T, qualifier Q> + 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<typename T, qualifier Q> + 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<typename T, qualifier Q> + 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<typename T, qualifier Q> + 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<typename T, qualifier Q> + 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<typename T, qualifier Q> + 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<typename T, qualifier Q> + 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<typename T, qualifier Q> + 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<typename T, qualifier Q> + 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<typename T, qualifier Q> + 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<typename T, qualifier Q> + 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<typename T, qualifier Q> + 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<typename T, qualifier Q> + 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<typename T, qualifier Q> + 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<typename T, qualifier Q> + 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<typename T, qualifier Q> + 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<typename T, qualifier Q> + 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<typename T, qualifier Q> + 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<typename T, qualifier Q> + 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<typename T, qualifier Q> + 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<typename T, qualifier Q> + 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<typename T, qualifier Q> + 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<typename T, qualifier Q> + 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<typename T, qualifier Q> + 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<typename T, qualifier Q> + 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<typename T, qualifier Q> + 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<typename T, qualifier Q> + 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<typename T, qualifier Q> + 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<typename T, qualifier Q> + 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<typename T, qualifier Q> + 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<typename T, qualifier Q> + 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<typename T, qualifier Q> + 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<typename T, qualifier Q> + 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<typename T, qualifier Q> + 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<typename T, qualifier Q> + 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<typename T, qualifier Q> + 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<typename T, qualifier Q> + 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<typename T, qualifier Q> + 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<typename T, qualifier Q> + 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<typename T, qualifier Q> + 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<typename T, qualifier Q> + 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<typename T, qualifier Q> + 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<typename T, qualifier Q> + 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<typename T, qualifier Q> + 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<typename T, qualifier Q> + 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<typename T, qualifier Q> + 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<typename T, qualifier Q> + 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<typename T, qualifier Q> + 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<typename T, qualifier Q> + 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<typename T, qualifier Q> + 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<typename T, qualifier Q> + 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<typename T, qualifier Q> + GLM_FUNC_QUALIFIER GLM_CONSTEXPR bool operator==(vec<2, T, Q> const& v1, vec<2, T, Q> const& v2) + { + return + detail::compute_equal<T, std::numeric_limits<T>::is_iec559>::call(v1.x, v2.x) && + detail::compute_equal<T, std::numeric_limits<T>::is_iec559>::call(v1.y, v2.y); + } + + template<typename T, qualifier Q> + GLM_FUNC_QUALIFIER GLM_CONSTEXPR bool operator!=(vec<2, T, Q> const& v1, vec<2, T, Q> const& v2) + { + return !(v1 == v2); + } + + template<qualifier Q> + 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<qualifier Q> + 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 0000000000000000000000000000000000000000..d83cde678f8b695532e94cdf2a78c589f72eb1b4 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/detail/type_vec3.hpp @@ -0,0 +1,432 @@ +/// @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 <cstddef> + +namespace glm +{ + template<typename T, qualifier Q> + 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" +# 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; +# 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<Q>::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_FUNC_DECL GLM_CONSTEXPR vec() GLM_DEFAULT; + GLM_FUNC_DECL GLM_CONSTEXPR vec(vec const& v) GLM_DEFAULT; + template<qualifier P> + GLM_FUNC_DECL GLM_CONSTEXPR vec(vec<3, T, P> const& v); + + // -- Explicit basic constructors -- + + GLM_FUNC_DECL GLM_CONSTEXPR explicit vec(T scalar); + GLM_FUNC_DECL GLM_CONSTEXPR vec(T a, T b, T c); + + // -- Conversion scalar constructors -- + + template<typename U, qualifier P> + GLM_FUNC_DECL GLM_CONSTEXPR 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<typename X, typename Y, typename Z> + GLM_FUNC_DECL GLM_CONSTEXPR vec(X x, Y y, Z z); + template<typename X, typename Y, typename Z> + GLM_FUNC_DECL GLM_CONSTEXPR vec(vec<1, X, Q> const& _x, Y _y, Z _z); + template<typename X, typename Y, typename Z> + GLM_FUNC_DECL GLM_CONSTEXPR vec(X _x, vec<1, Y, Q> const& _y, Z _z); + template<typename X, typename Y, typename Z> + GLM_FUNC_DECL GLM_CONSTEXPR vec(vec<1, X, Q> const& _x, vec<1, Y, Q> const& _y, Z _z); + template<typename X, typename Y, typename Z> + GLM_FUNC_DECL GLM_CONSTEXPR vec(X _x, Y _y, vec<1, Z, Q> const& _z); + template<typename X, typename Y, typename Z> + GLM_FUNC_DECL GLM_CONSTEXPR vec(vec<1, X, Q> const& _x, Y _y, vec<1, Z, Q> const& _z); + template<typename X, typename Y, typename Z> + GLM_FUNC_DECL GLM_CONSTEXPR vec(X _x, vec<1, Y, Q> const& _y, vec<1, Z, Q> const& _z); + template<typename X, typename Y, typename Z> + GLM_FUNC_DECL GLM_CONSTEXPR 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<typename A, typename B, qualifier P> + GLM_FUNC_DECL GLM_CONSTEXPR 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<typename A, typename B, qualifier P> + GLM_FUNC_DECL GLM_CONSTEXPR 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<typename A, typename B, qualifier P> + GLM_FUNC_DECL GLM_CONSTEXPR 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<typename A, typename B, qualifier P> + GLM_FUNC_DECL GLM_CONSTEXPR 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<typename U, qualifier P> + GLM_FUNC_DECL GLM_CONSTEXPR 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<typename U, qualifier P> + GLM_FUNC_DECL GLM_CONSTEXPR GLM_EXPLICIT vec(vec<3, U, P> const& v); + + // -- Swizzle constructors -- +# if GLM_CONFIG_SWIZZLE == GLM_SWIZZLE_OPERATOR + template<int E0, int E1, int E2> + GLM_FUNC_DECL GLM_CONSTEXPR vec(detail::_swizzle<3, T, Q, E0, E1, E2, -1> const& that) + { + *this = that(); + } + + template<int E0, int E1> + GLM_FUNC_DECL GLM_CONSTEXPR vec(detail::_swizzle<2, T, Q, E0, E1, -1, -2> const& v, T const& scalar) + { + *this = vec(v(), scalar); + } + + template<int E0, int E1> + GLM_FUNC_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_FUNC_DECL GLM_CONSTEXPR vec<3, T, Q>& operator=(vec<3, T, Q> const& v) GLM_DEFAULT; + + template<typename U> + GLM_FUNC_DECL GLM_CONSTEXPR vec<3, T, Q> & operator=(vec<3, U, Q> const& v); + template<typename U> + GLM_FUNC_DECL GLM_CONSTEXPR vec<3, T, Q> & operator+=(U scalar); + template<typename U> + GLM_FUNC_DECL GLM_CONSTEXPR vec<3, T, Q> & operator+=(vec<1, U, Q> const& v); + template<typename U> + GLM_FUNC_DECL GLM_CONSTEXPR vec<3, T, Q> & operator+=(vec<3, U, Q> const& v); + template<typename U> + GLM_FUNC_DECL GLM_CONSTEXPR vec<3, T, Q> & operator-=(U scalar); + template<typename U> + GLM_FUNC_DECL GLM_CONSTEXPR vec<3, T, Q> & operator-=(vec<1, U, Q> const& v); + template<typename U> + GLM_FUNC_DECL GLM_CONSTEXPR vec<3, T, Q> & operator-=(vec<3, U, Q> const& v); + template<typename U> + GLM_FUNC_DECL GLM_CONSTEXPR vec<3, T, Q> & operator*=(U scalar); + template<typename U> + GLM_FUNC_DECL GLM_CONSTEXPR vec<3, T, Q> & operator*=(vec<1, U, Q> const& v); + template<typename U> + GLM_FUNC_DECL GLM_CONSTEXPR vec<3, T, Q> & operator*=(vec<3, U, Q> const& v); + template<typename U> + GLM_FUNC_DECL GLM_CONSTEXPR vec<3, T, Q> & operator/=(U scalar); + template<typename U> + GLM_FUNC_DECL GLM_CONSTEXPR vec<3, T, Q> & operator/=(vec<1, U, Q> const& v); + template<typename U> + GLM_FUNC_DECL GLM_CONSTEXPR vec<3, T, Q> & operator/=(vec<3, U, Q> const& v); + + // -- Increment and decrement operators -- + + GLM_FUNC_DECL GLM_CONSTEXPR vec<3, T, Q> & operator++(); + GLM_FUNC_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<typename U> + GLM_FUNC_DECL GLM_CONSTEXPR vec<3, T, Q> & operator%=(U scalar); + template<typename U> + GLM_FUNC_DECL GLM_CONSTEXPR vec<3, T, Q> & operator%=(vec<1, U, Q> const& v); + template<typename U> + GLM_FUNC_DECL GLM_CONSTEXPR vec<3, T, Q> & operator%=(vec<3, U, Q> const& v); + template<typename U> + GLM_FUNC_DECL GLM_CONSTEXPR vec<3, T, Q> & operator&=(U scalar); + template<typename U> + GLM_FUNC_DECL GLM_CONSTEXPR vec<3, T, Q> & operator&=(vec<1, U, Q> const& v); + template<typename U> + GLM_FUNC_DECL GLM_CONSTEXPR vec<3, T, Q> & operator&=(vec<3, U, Q> const& v); + template<typename U> + GLM_FUNC_DECL GLM_CONSTEXPR vec<3, T, Q> & operator|=(U scalar); + template<typename U> + GLM_FUNC_DECL GLM_CONSTEXPR vec<3, T, Q> & operator|=(vec<1, U, Q> const& v); + template<typename U> + GLM_FUNC_DECL GLM_CONSTEXPR vec<3, T, Q> & operator|=(vec<3, U, Q> const& v); + template<typename U> + GLM_FUNC_DECL GLM_CONSTEXPR vec<3, T, Q> & operator^=(U scalar); + template<typename U> + GLM_FUNC_DECL GLM_CONSTEXPR vec<3, T, Q> & operator^=(vec<1, U, Q> const& v); + template<typename U> + GLM_FUNC_DECL GLM_CONSTEXPR vec<3, T, Q> & operator^=(vec<3, U, Q> const& v); + template<typename U> + GLM_FUNC_DECL GLM_CONSTEXPR vec<3, T, Q> & operator<<=(U scalar); + template<typename U> + GLM_FUNC_DECL GLM_CONSTEXPR vec<3, T, Q> & operator<<=(vec<1, U, Q> const& v); + template<typename U> + GLM_FUNC_DECL GLM_CONSTEXPR vec<3, T, Q> & operator<<=(vec<3, U, Q> const& v); + template<typename U> + GLM_FUNC_DECL GLM_CONSTEXPR vec<3, T, Q> & operator>>=(U scalar); + template<typename U> + GLM_FUNC_DECL GLM_CONSTEXPR vec<3, T, Q> & operator>>=(vec<1, U, Q> const& v); + template<typename U> + GLM_FUNC_DECL GLM_CONSTEXPR vec<3, T, Q> & operator>>=(vec<3, U, Q> const& v); + }; + + // -- Unary operators -- + + template<typename T, qualifier Q> + GLM_FUNC_DECL GLM_CONSTEXPR vec<3, T, Q> operator+(vec<3, T, Q> const& v); + + template<typename T, qualifier Q> + GLM_FUNC_DECL GLM_CONSTEXPR vec<3, T, Q> operator-(vec<3, T, Q> const& v); + + // -- Binary operators -- + + template<typename T, qualifier Q> + GLM_FUNC_DECL GLM_CONSTEXPR vec<3, T, Q> operator+(vec<3, T, Q> const& v, T scalar); + + template<typename T, qualifier Q> + GLM_FUNC_DECL GLM_CONSTEXPR vec<3, T, Q> operator+(vec<3, T, Q> const& v, vec<1, T, Q> const& scalar); + + template<typename T, qualifier Q> + GLM_FUNC_DECL GLM_CONSTEXPR vec<3, T, Q> operator+(T scalar, vec<3, T, Q> const& v); + + template<typename T, qualifier Q> + GLM_FUNC_DECL GLM_CONSTEXPR vec<3, T, Q> operator+(vec<1, T, Q> const& v1, vec<3, T, Q> const& v2); + + template<typename T, qualifier Q> + GLM_FUNC_DECL GLM_CONSTEXPR vec<3, T, Q> operator+(vec<3, T, Q> const& v1, vec<3, T, Q> const& v2); + + template<typename T, qualifier Q> + GLM_FUNC_DECL GLM_CONSTEXPR vec<3, T, Q> operator-(vec<3, T, Q> const& v, T scalar); + + template<typename T, qualifier Q> + GLM_FUNC_DECL GLM_CONSTEXPR vec<3, T, Q> operator-(vec<3, T, Q> const& v1, vec<1, T, Q> const& v2); + + template<typename T, qualifier Q> + GLM_FUNC_DECL GLM_CONSTEXPR vec<3, T, Q> operator-(T scalar, vec<3, T, Q> const& v); + + template<typename T, qualifier Q> + GLM_FUNC_DECL GLM_CONSTEXPR vec<3, T, Q> operator-(vec<1, T, Q> const& v1, vec<3, T, Q> const& v2); + + template<typename T, qualifier Q> + GLM_FUNC_DECL GLM_CONSTEXPR vec<3, T, Q> operator-(vec<3, T, Q> const& v1, vec<3, T, Q> const& v2); + + template<typename T, qualifier Q> + GLM_FUNC_DECL GLM_CONSTEXPR vec<3, T, Q> operator*(vec<3, T, Q> const& v, T scalar); + + template<typename T, qualifier Q> + GLM_FUNC_DECL GLM_CONSTEXPR vec<3, T, Q> operator*(vec<3, T, Q> const& v1, vec<1, T, Q> const& v2); + + template<typename T, qualifier Q> + GLM_FUNC_DECL GLM_CONSTEXPR vec<3, T, Q> operator*(T scalar, vec<3, T, Q> const& v); + + template<typename T, qualifier Q> + GLM_FUNC_DECL GLM_CONSTEXPR vec<3, T, Q> operator*(vec<1, T, Q> const& v1, vec<3, T, Q> const& v2); + + template<typename T, qualifier Q> + GLM_FUNC_DECL GLM_CONSTEXPR vec<3, T, Q> operator*(vec<3, T, Q> const& v1, vec<3, T, Q> const& v2); + + template<typename T, qualifier Q> + GLM_FUNC_DECL GLM_CONSTEXPR vec<3, T, Q> operator/(vec<3, T, Q> const& v, T scalar); + + template<typename T, qualifier Q> + GLM_FUNC_DECL GLM_CONSTEXPR vec<3, T, Q> operator/(vec<3, T, Q> const& v1, vec<1, T, Q> const& v2); + + template<typename T, qualifier Q> + GLM_FUNC_DECL GLM_CONSTEXPR vec<3, T, Q> operator/(T scalar, vec<3, T, Q> const& v); + + template<typename T, qualifier Q> + GLM_FUNC_DECL GLM_CONSTEXPR vec<3, T, Q> operator/(vec<1, T, Q> const& v1, vec<3, T, Q> const& v2); + + template<typename T, qualifier Q> + GLM_FUNC_DECL GLM_CONSTEXPR vec<3, T, Q> operator/(vec<3, T, Q> const& v1, vec<3, T, Q> const& v2); + + template<typename T, qualifier Q> + GLM_FUNC_DECL GLM_CONSTEXPR vec<3, T, Q> operator%(vec<3, T, Q> const& v, T scalar); + + template<typename T, qualifier Q> + GLM_FUNC_DECL GLM_CONSTEXPR vec<3, T, Q> operator%(vec<3, T, Q> const& v1, vec<1, T, Q> const& v2); + + template<typename T, qualifier Q> + GLM_FUNC_DECL GLM_CONSTEXPR vec<3, T, Q> operator%(T scalar, vec<3, T, Q> const& v); + + template<typename T, qualifier Q> + GLM_FUNC_DECL GLM_CONSTEXPR vec<3, T, Q> operator%(vec<1, T, Q> const& v1, vec<3, T, Q> const& v2); + + template<typename T, qualifier Q> + GLM_FUNC_DECL GLM_CONSTEXPR vec<3, T, Q> operator%(vec<3, T, Q> const& v1, vec<3, T, Q> const& v2); + + template<typename T, qualifier Q> + GLM_FUNC_DECL GLM_CONSTEXPR vec<3, T, Q> operator&(vec<3, T, Q> const& v1, T scalar); + + template<typename T, qualifier Q> + GLM_FUNC_DECL GLM_CONSTEXPR vec<3, T, Q> operator&(vec<3, T, Q> const& v1, vec<1, T, Q> const& v2); + + template<typename T, qualifier Q> + GLM_FUNC_DECL GLM_CONSTEXPR vec<3, T, Q> operator&(T scalar, vec<3, T, Q> const& v); + + template<typename T, qualifier Q> + GLM_FUNC_DECL GLM_CONSTEXPR vec<3, T, Q> operator&(vec<1, T, Q> const& v1, vec<3, T, Q> const& v2); + + template<typename T, qualifier Q> + GLM_FUNC_DECL GLM_CONSTEXPR vec<3, T, Q> operator&(vec<3, T, Q> const& v1, vec<3, T, Q> const& v2); + + template<typename T, qualifier Q> + GLM_FUNC_DECL GLM_CONSTEXPR vec<3, T, Q> operator|(vec<3, T, Q> const& v, T scalar); + + template<typename T, qualifier Q> + GLM_FUNC_DECL GLM_CONSTEXPR vec<3, T, Q> operator|(vec<3, T, Q> const& v1, vec<1, T, Q> const& v2); + + template<typename T, qualifier Q> + GLM_FUNC_DECL GLM_CONSTEXPR vec<3, T, Q> operator|(T scalar, vec<3, T, Q> const& v); + + template<typename T, qualifier Q> + GLM_FUNC_DECL GLM_CONSTEXPR vec<3, T, Q> operator|(vec<1, T, Q> const& v1, vec<3, T, Q> const& v2); + + template<typename T, qualifier Q> + GLM_FUNC_DECL GLM_CONSTEXPR vec<3, T, Q> operator|(vec<3, T, Q> const& v1, vec<3, T, Q> const& v2); + + template<typename T, qualifier Q> + GLM_FUNC_DECL GLM_CONSTEXPR vec<3, T, Q> operator^(vec<3, T, Q> const& v, T scalar); + + template<typename T, qualifier Q> + GLM_FUNC_DECL GLM_CONSTEXPR vec<3, T, Q> operator^(vec<3, T, Q> const& v1, vec<1, T, Q> const& v2); + + template<typename T, qualifier Q> + GLM_FUNC_DECL GLM_CONSTEXPR vec<3, T, Q> operator^(T scalar, vec<3, T, Q> const& v); + + template<typename T, qualifier Q> + GLM_FUNC_DECL GLM_CONSTEXPR vec<3, T, Q> operator^(vec<1, T, Q> const& v1, vec<3, T, Q> const& v2); + + template<typename T, qualifier Q> + GLM_FUNC_DECL GLM_CONSTEXPR vec<3, T, Q> operator^(vec<3, T, Q> const& v1, vec<3, T, Q> const& v2); + + template<typename T, qualifier Q> + GLM_FUNC_DECL GLM_CONSTEXPR vec<3, T, Q> operator<<(vec<3, T, Q> const& v, T scalar); + + template<typename T, qualifier Q> + GLM_FUNC_DECL GLM_CONSTEXPR vec<3, T, Q> operator<<(vec<3, T, Q> const& v1, vec<1, T, Q> const& v2); + + template<typename T, qualifier Q> + GLM_FUNC_DECL GLM_CONSTEXPR vec<3, T, Q> operator<<(T scalar, vec<3, T, Q> const& v); + + template<typename T, qualifier Q> + GLM_FUNC_DECL GLM_CONSTEXPR vec<3, T, Q> operator<<(vec<1, T, Q> const& v1, vec<3, T, Q> const& v2); + + template<typename T, qualifier Q> + GLM_FUNC_DECL GLM_CONSTEXPR vec<3, T, Q> operator<<(vec<3, T, Q> const& v1, vec<3, T, Q> const& v2); + + template<typename T, qualifier Q> + GLM_FUNC_DECL GLM_CONSTEXPR vec<3, T, Q> operator>>(vec<3, T, Q> const& v, T scalar); + + template<typename T, qualifier Q> + GLM_FUNC_DECL GLM_CONSTEXPR vec<3, T, Q> operator>>(vec<3, T, Q> const& v1, vec<1, T, Q> const& v2); + + template<typename T, qualifier Q> + GLM_FUNC_DECL GLM_CONSTEXPR vec<3, T, Q> operator>>(T scalar, vec<3, T, Q> const& v); + + template<typename T, qualifier Q> + GLM_FUNC_DECL GLM_CONSTEXPR vec<3, T, Q> operator>>(vec<1, T, Q> const& v1, vec<3, T, Q> const& v2); + + template<typename T, qualifier Q> + GLM_FUNC_DECL GLM_CONSTEXPR vec<3, T, Q> operator>>(vec<3, T, Q> const& v1, vec<3, T, Q> const& v2); + + template<typename T, qualifier Q> + GLM_FUNC_DECL GLM_CONSTEXPR vec<3, T, Q> operator~(vec<3, T, Q> const& v); + + // -- Boolean operators -- + + template<typename T, qualifier Q> + GLM_FUNC_DECL GLM_CONSTEXPR bool operator==(vec<3, T, Q> const& v1, vec<3, T, Q> const& v2); + + template<typename T, qualifier Q> + GLM_FUNC_DECL GLM_CONSTEXPR bool operator!=(vec<3, T, Q> const& v1, vec<3, T, Q> const& v2); + + template<qualifier Q> + GLM_FUNC_DECL GLM_CONSTEXPR vec<3, bool, Q> operator&&(vec<3, bool, Q> const& v1, vec<3, bool, Q> const& v2); + + template<qualifier Q> + 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 0000000000000000000000000000000000000000..6532c9e6e06ba8fac8edc1fcefeff7547118641e --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/detail/type_vec3.inl @@ -0,0 +1,1068 @@ +/// @ref core + +#include "compute_vector_relational.hpp" + +namespace glm +{ + // -- Implicit basic constructors -- + +# if GLM_CONFIG_DEFAULTED_FUNCTIONS == GLM_DISABLE + template<typename T, qualifier Q> + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<3, T, Q>::vec() +# if GLM_CONFIG_CTOR_INIT != GLM_CTOR_INIT_DISABLE + : x(0), y(0), z(0) +# endif + {} + + template<typename T, qualifier Q> + GLM_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<typename T, qualifier Q> + template<qualifier P> + 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<typename T, qualifier Q> + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<3, T, Q>::vec(T scalar) + : x(scalar), y(scalar), z(scalar) + {} + + template <typename T, qualifier Q> + 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<typename T, qualifier Q> + template<typename U, qualifier P> + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<3, T, Q>::vec(vec<1, U, P> const& v) + : x(static_cast<T>(v.x)) + , y(static_cast<T>(v.x)) + , z(static_cast<T>(v.x)) + {} + + template<typename T, qualifier Q> + template<typename X, typename Y, typename Z> + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<3, T, Q>::vec(X _x, Y _y, Z _z) + : x(static_cast<T>(_x)) + , y(static_cast<T>(_y)) + , z(static_cast<T>(_z)) + {} + + template<typename T, qualifier Q> + template<typename X, typename Y, typename Z> + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<3, T, Q>::vec(vec<1, X, Q> const& _x, Y _y, Z _z) + : x(static_cast<T>(_x.x)) + , y(static_cast<T>(_y)) + , z(static_cast<T>(_z)) + {} + + template<typename T, qualifier Q> + template<typename X, typename Y, typename Z> + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<3, T, Q>::vec(X _x, vec<1, Y, Q> const& _y, Z _z) + : x(static_cast<T>(_x)) + , y(static_cast<T>(_y.x)) + , z(static_cast<T>(_z)) + {} + + template<typename T, qualifier Q> + template<typename X, typename Y, typename Z> + 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<T>(_x.x)) + , y(static_cast<T>(_y.x)) + , z(static_cast<T>(_z)) + {} + + template<typename T, qualifier Q> + template<typename X, typename Y, typename Z> + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<3, T, Q>::vec(X _x, Y _y, vec<1, Z, Q> const& _z) + : x(static_cast<T>(_x)) + , y(static_cast<T>(_y)) + , z(static_cast<T>(_z.x)) + {} + + template<typename T, qualifier Q> + template<typename X, typename Y, typename Z> + 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<T>(_x.x)) + , y(static_cast<T>(_y)) + , z(static_cast<T>(_z.x)) + {} + + template<typename T, qualifier Q> + template<typename X, typename Y, typename Z> + 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<T>(_x)) + , y(static_cast<T>(_y.x)) + , z(static_cast<T>(_z.x)) + {} + + template<typename T, qualifier Q> + template<typename X, typename Y, typename Z> + 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<T>(_x.x)) + , y(static_cast<T>(_y.x)) + , z(static_cast<T>(_z.x)) + {} + + // -- Conversion vector constructors -- + + template<typename T, qualifier Q> + template<typename A, typename B, qualifier P> + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<3, T, Q>::vec(vec<2, A, P> const& _xy, B _z) + : x(static_cast<T>(_xy.x)) + , y(static_cast<T>(_xy.y)) + , z(static_cast<T>(_z)) + {} + + template<typename T, qualifier Q> + template<typename A, typename B, qualifier P> + 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<T>(_xy.x)) + , y(static_cast<T>(_xy.y)) + , z(static_cast<T>(_z.x)) + {} + + template<typename T, qualifier Q> + template<typename A, typename B, qualifier P> + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<3, T, Q>::vec(A _x, vec<2, B, P> const& _yz) + : x(static_cast<T>(_x)) + , y(static_cast<T>(_yz.x)) + , z(static_cast<T>(_yz.y)) + {} + + template<typename T, qualifier Q> + template<typename A, typename B, qualifier P> + 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<T>(_x.x)) + , y(static_cast<T>(_yz.x)) + , z(static_cast<T>(_yz.y)) + {} + + template<typename T, qualifier Q> + template<typename U, qualifier P> + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<3, T, Q>::vec(vec<3, U, P> const& v) + : x(static_cast<T>(v.x)) + , y(static_cast<T>(v.y)) + , z(static_cast<T>(v.z)) + {} + + template<typename T, qualifier Q> + template<typename U, qualifier P> + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<3, T, Q>::vec(vec<4, U, P> const& v) + : x(static_cast<T>(v.x)) + , y(static_cast<T>(v.y)) + , z(static_cast<T>(v.z)) + {} + + // -- Component accesses -- + + template<typename T, qualifier Q> + GLM_FUNC_QUALIFIER GLM_CONSTEXPR T & vec<3, T, Q>::operator[](typename vec<3, T, Q>::length_type i) + { + assert(i >= 0 && i < this->length()); + switch(i) + { + default: + case 0: + return x; + case 1: + return y; + case 2: + return z; + } + } + + template<typename T, qualifier Q> + GLM_FUNC_QUALIFIER GLM_CONSTEXPR T const& vec<3, T, Q>::operator[](typename vec<3, T, Q>::length_type i) const + { + assert(i >= 0 && 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<typename T, qualifier Q> + GLM_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<typename T, qualifier Q> + template<typename U> + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<3, T, Q>& vec<3, T, Q>::operator=(vec<3, U, Q> const& v) + { + this->x = static_cast<T>(v.x); + this->y = static_cast<T>(v.y); + this->z = static_cast<T>(v.z); + return *this; + } + + template<typename T, qualifier Q> + template<typename U> + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<3, T, Q> & vec<3, T, Q>::operator+=(U scalar) + { + this->x += static_cast<T>(scalar); + this->y += static_cast<T>(scalar); + this->z += static_cast<T>(scalar); + return *this; + } + + template<typename T, qualifier Q> + template<typename U> + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<3, T, Q> & vec<3, T, Q>::operator+=(vec<1, U, Q> const& v) + { + this->x += static_cast<T>(v.x); + this->y += static_cast<T>(v.x); + this->z += static_cast<T>(v.x); + return *this; + } + + template<typename T, qualifier Q> + template<typename U> + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<3, T, Q> & vec<3, T, Q>::operator+=(vec<3, U, Q> const& v) + { + this->x += static_cast<T>(v.x); + this->y += static_cast<T>(v.y); + this->z += static_cast<T>(v.z); + return *this; + } + + template<typename T, qualifier Q> + template<typename U> + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<3, T, Q> & vec<3, T, Q>::operator-=(U scalar) + { + this->x -= static_cast<T>(scalar); + this->y -= static_cast<T>(scalar); + this->z -= static_cast<T>(scalar); + return *this; + } + + template<typename T, qualifier Q> + template<typename U> + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<3, T, Q> & vec<3, T, Q>::operator-=(vec<1, U, Q> const& v) + { + this->x -= static_cast<T>(v.x); + this->y -= static_cast<T>(v.x); + this->z -= static_cast<T>(v.x); + return *this; + } + + template<typename T, qualifier Q> + template<typename U> + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<3, T, Q> & vec<3, T, Q>::operator-=(vec<3, U, Q> const& v) + { + this->x -= static_cast<T>(v.x); + this->y -= static_cast<T>(v.y); + this->z -= static_cast<T>(v.z); + return *this; + } + + template<typename T, qualifier Q> + template<typename U> + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<3, T, Q> & vec<3, T, Q>::operator*=(U scalar) + { + this->x *= static_cast<T>(scalar); + this->y *= static_cast<T>(scalar); + this->z *= static_cast<T>(scalar); + return *this; + } + + template<typename T, qualifier Q> + template<typename U> + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<3, T, Q> & vec<3, T, Q>::operator*=(vec<1, U, Q> const& v) + { + this->x *= static_cast<T>(v.x); + this->y *= static_cast<T>(v.x); + this->z *= static_cast<T>(v.x); + return *this; + } + + template<typename T, qualifier Q> + template<typename U> + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<3, T, Q> & vec<3, T, Q>::operator*=(vec<3, U, Q> const& v) + { + this->x *= static_cast<T>(v.x); + this->y *= static_cast<T>(v.y); + this->z *= static_cast<T>(v.z); + return *this; + } + + template<typename T, qualifier Q> + template<typename U> + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<3, T, Q> & vec<3, T, Q>::operator/=(U v) + { + this->x /= static_cast<T>(v); + this->y /= static_cast<T>(v); + this->z /= static_cast<T>(v); + return *this; + } + + template<typename T, qualifier Q> + template<typename U> + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<3, T, Q> & vec<3, T, Q>::operator/=(vec<1, U, Q> const& v) + { + this->x /= static_cast<T>(v.x); + this->y /= static_cast<T>(v.x); + this->z /= static_cast<T>(v.x); + return *this; + } + + template<typename T, qualifier Q> + template<typename U> + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<3, T, Q> & vec<3, T, Q>::operator/=(vec<3, U, Q> const& v) + { + this->x /= static_cast<T>(v.x); + this->y /= static_cast<T>(v.y); + this->z /= static_cast<T>(v.z); + return *this; + } + + // -- Increment and decrement operators -- + + template<typename T, qualifier Q> + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<3, T, Q> & vec<3, T, Q>::operator++() + { + ++this->x; + ++this->y; + ++this->z; + return *this; + } + + template<typename T, qualifier Q> + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<3, T, Q> & vec<3, T, Q>::operator--() + { + --this->x; + --this->y; + --this->z; + return *this; + } + + template<typename T, qualifier Q> + 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<typename T, qualifier Q> + 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<typename T, qualifier Q> + template<typename U> + 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<typename T, qualifier Q> + template<typename U> + 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<typename T, qualifier Q> + template<typename U> + 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<typename T, qualifier Q> + template<typename U> + 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<typename T, qualifier Q> + template<typename U> + 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<typename T, qualifier Q> + template<typename U> + 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<typename T, qualifier Q> + template<typename U> + 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<typename T, qualifier Q> + template<typename U> + 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<typename T, qualifier Q> + template<typename U> + 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<typename T, qualifier Q> + template<typename U> + 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<typename T, qualifier Q> + template<typename U> + 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<typename T, qualifier Q> + template<typename U> + 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<typename T, qualifier Q> + template<typename U> + 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<typename T, qualifier Q> + template<typename U> + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<3, T, Q> & vec<3, T, Q>::operator<<=(vec<1, U, Q> const& v) + { + this->x <<= static_cast<T>(v.x); + this->y <<= static_cast<T>(v.x); + this->z <<= static_cast<T>(v.x); + return *this; + } + + template<typename T, qualifier Q> + template<typename U> + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<3, T, Q> & vec<3, T, Q>::operator<<=(vec<3, U, Q> const& v) + { + this->x <<= static_cast<T>(v.x); + this->y <<= static_cast<T>(v.y); + this->z <<= static_cast<T>(v.z); + return *this; + } + + template<typename T, qualifier Q> + template<typename U> + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<3, T, Q> & vec<3, T, Q>::operator>>=(U scalar) + { + this->x >>= static_cast<T>(scalar); + this->y >>= static_cast<T>(scalar); + this->z >>= static_cast<T>(scalar); + return *this; + } + + template<typename T, qualifier Q> + template<typename U> + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<3, T, Q> & vec<3, T, Q>::operator>>=(vec<1, U, Q> const& v) + { + this->x >>= static_cast<T>(v.x); + this->y >>= static_cast<T>(v.x); + this->z >>= static_cast<T>(v.x); + return *this; + } + + template<typename T, qualifier Q> + template<typename U> + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<3, T, Q> & vec<3, T, Q>::operator>>=(vec<3, U, Q> const& v) + { + this->x >>= static_cast<T>(v.x); + this->y >>= static_cast<T>(v.y); + this->z >>= static_cast<T>(v.z); + return *this; + } + + // -- Unary arithmetic operators -- + + template<typename T, qualifier Q> + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<3, T, Q> operator+(vec<3, T, Q> const& v) + { + return v; + } + + template<typename T, qualifier Q> + 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<typename T, qualifier Q> + 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<typename T, qualifier Q> + 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<typename T, qualifier Q> + 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<typename T, qualifier Q> + 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<typename T, qualifier Q> + 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<typename T, qualifier Q> + 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<typename T, qualifier Q> + 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<typename T, qualifier Q> + 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<typename T, qualifier Q> + 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<typename T, qualifier Q> + 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<typename T, qualifier Q> + 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<typename T, qualifier Q> + 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<typename T, qualifier Q> + 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<typename T, qualifier Q> + 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<typename T, qualifier Q> + 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<typename T, qualifier Q> + 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<typename T, qualifier Q> + 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<typename T, qualifier Q> + 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<typename T, qualifier Q> + 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<typename T, qualifier Q> + 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<typename T, qualifier Q> + 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<typename T, qualifier Q> + 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<typename T, qualifier Q> + 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<typename T, qualifier Q> + 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<typename T, qualifier Q> + 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<typename T, qualifier Q> + 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<typename T, qualifier Q> + 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<typename T, qualifier Q> + 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<typename T, qualifier Q> + 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<typename T, qualifier Q> + 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<typename T, qualifier Q> + 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<typename T, qualifier Q> + 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<typename T, qualifier Q> + 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<typename T, qualifier Q> + 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<typename T, qualifier Q> + 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<typename T, qualifier Q> + 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<typename T, qualifier Q> + 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<typename T, qualifier Q> + 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<typename T, qualifier Q> + 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<typename T, qualifier Q> + 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<typename T, qualifier Q> + 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<typename T, qualifier Q> + 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<typename T, qualifier Q> + 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<typename T, qualifier Q> + 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<typename T, qualifier Q> + 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<typename T, qualifier Q> + 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<typename T, qualifier Q> + 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<typename T, qualifier Q> + 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<typename T, qualifier Q> + 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<typename T, qualifier Q> + 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<typename T, qualifier Q> + 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<typename T, qualifier Q> + GLM_FUNC_QUALIFIER GLM_CONSTEXPR bool operator==(vec<3, T, Q> const& v1, vec<3, T, Q> const& v2) + { + return + detail::compute_equal<T, std::numeric_limits<T>::is_iec559>::call(v1.x, v2.x) && + detail::compute_equal<T, std::numeric_limits<T>::is_iec559>::call(v1.y, v2.y) && + detail::compute_equal<T, std::numeric_limits<T>::is_iec559>::call(v1.z, v2.z); + } + + template<typename T, qualifier Q> + GLM_FUNC_QUALIFIER GLM_CONSTEXPR bool operator!=(vec<3, T, Q> const& v1, vec<3, T, Q> const& v2) + { + return !(v1 == v2); + } + + template<qualifier Q> + 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<qualifier Q> + 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 0000000000000000000000000000000000000000..4a3643467382e9437cdf777cff168eccd5303aa2 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/detail/type_vec4.hpp @@ -0,0 +1,505 @@ +/// @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 <cstddef> + +namespace glm +{ + template<typename T, qualifier Q> + 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; +# 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<Q>::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_FUNC_DECL GLM_CONSTEXPR vec() GLM_DEFAULT; + GLM_FUNC_DECL GLM_CONSTEXPR vec(vec<4, T, Q> const& v) GLM_DEFAULT; + template<qualifier P> + GLM_FUNC_DECL GLM_CONSTEXPR vec(vec<4, T, P> const& v); + + // -- Explicit basic constructors -- + + GLM_FUNC_DECL GLM_CONSTEXPR explicit vec(T scalar); + GLM_FUNC_DECL GLM_CONSTEXPR vec(T x, T y, T z, T w); + + // -- Conversion scalar constructors -- + + template<typename U, qualifier P> + GLM_FUNC_DECL GLM_CONSTEXPR 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<typename X, typename Y, typename Z, typename W> + GLM_FUNC_DECL GLM_CONSTEXPR vec(X _x, Y _y, Z _z, W _w); + template<typename X, typename Y, typename Z, typename W> + GLM_FUNC_DECL GLM_CONSTEXPR vec(vec<1, X, Q> const& _x, Y _y, Z _z, W _w); + template<typename X, typename Y, typename Z, typename W> + GLM_FUNC_DECL GLM_CONSTEXPR vec(X _x, vec<1, Y, Q> const& _y, Z _z, W _w); + template<typename X, typename Y, typename Z, typename W> + GLM_FUNC_DECL GLM_CONSTEXPR vec(vec<1, X, Q> const& _x, vec<1, Y, Q> const& _y, Z _z, W _w); + template<typename X, typename Y, typename Z, typename W> + GLM_FUNC_DECL GLM_CONSTEXPR vec(X _x, Y _y, vec<1, Z, Q> const& _z, W _w); + template<typename X, typename Y, typename Z, typename W> + GLM_FUNC_DECL GLM_CONSTEXPR vec(vec<1, X, Q> const& _x, Y _y, vec<1, Z, Q> const& _z, W _w); + template<typename X, typename Y, typename Z, typename W> + GLM_FUNC_DECL GLM_CONSTEXPR vec(X _x, vec<1, Y, Q> const& _y, vec<1, Z, Q> const& _z, W _w); + template<typename X, typename Y, typename Z, typename W> + GLM_FUNC_DECL GLM_CONSTEXPR vec(vec<1, X, Q> const& _x, vec<1, Y, Q> const& _y, vec<1, Z, Q> const& _z, W _w); + template<typename X, typename Y, typename Z, typename W> + GLM_FUNC_DECL GLM_CONSTEXPR vec(vec<1, X, Q> const& _x, Y _y, Z _z, vec<1, W, Q> const& _w); + template<typename X, typename Y, typename Z, typename W> + GLM_FUNC_DECL GLM_CONSTEXPR vec(X _x, vec<1, Y, Q> const& _y, Z _z, vec<1, W, Q> const& _w); + template<typename X, typename Y, typename Z, typename W> + GLM_FUNC_DECL GLM_CONSTEXPR vec(vec<1, X, Q> const& _x, vec<1, Y, Q> const& _y, Z _z, vec<1, W, Q> const& _w); + template<typename X, typename Y, typename Z, typename W> + GLM_FUNC_DECL GLM_CONSTEXPR vec(X _x, Y _y, vec<1, Z, Q> const& _z, vec<1, W, Q> const& _w); + template<typename X, typename Y, typename Z, typename W> + GLM_FUNC_DECL GLM_CONSTEXPR vec(vec<1, X, Q> const& _x, Y _y, vec<1, Z, Q> const& _z, vec<1, W, Q> const& _w); + template<typename X, typename Y, typename Z, typename W> + GLM_FUNC_DECL GLM_CONSTEXPR vec(X _x, vec<1, Y, Q> const& _y, vec<1, Z, Q> const& _z, vec<1, W, Q> const& _w); + template<typename X, typename Y, typename Z, typename W> + GLM_FUNC_DECL GLM_CONSTEXPR 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<typename A, typename B, typename C, qualifier P> + GLM_FUNC_DECL GLM_CONSTEXPR 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<typename A, typename B, typename C, qualifier P> + GLM_FUNC_DECL GLM_CONSTEXPR 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<typename A, typename B, typename C, qualifier P> + GLM_FUNC_DECL GLM_CONSTEXPR 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<typename A, typename B, typename C, qualifier P> + GLM_FUNC_DECL GLM_CONSTEXPR 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<typename A, typename B, typename C, qualifier P> + GLM_FUNC_DECL GLM_CONSTEXPR 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<typename A, typename B, typename C, qualifier P> + GLM_FUNC_DECL GLM_CONSTEXPR 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<typename A, typename B, typename C, qualifier P> + GLM_FUNC_DECL GLM_CONSTEXPR 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<typename A, typename B, typename C, qualifier P> + GLM_FUNC_DECL GLM_CONSTEXPR 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<typename A, typename B, typename C, qualifier P> + GLM_FUNC_DECL GLM_CONSTEXPR 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<typename A, typename B, typename C, qualifier P> + GLM_FUNC_DECL GLM_CONSTEXPR 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<typename A, typename B, typename C, qualifier P> + GLM_FUNC_DECL GLM_CONSTEXPR 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<typename A, typename B, typename C, qualifier P> + GLM_FUNC_DECL GLM_CONSTEXPR 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<typename A, typename B, qualifier P> + GLM_FUNC_DECL GLM_CONSTEXPR 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<typename A, typename B, qualifier P> + GLM_FUNC_DECL GLM_CONSTEXPR 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<typename A, typename B, qualifier P> + GLM_FUNC_DECL GLM_CONSTEXPR 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<typename A, typename B, qualifier P> + GLM_FUNC_DECL GLM_CONSTEXPR 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<typename A, typename B, qualifier P> + GLM_FUNC_DECL GLM_CONSTEXPR 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<typename U, qualifier P> + GLM_FUNC_DECL GLM_CONSTEXPR GLM_EXPLICIT vec(vec<4, U, P> const& v); + + // -- Swizzle constructors -- +# if GLM_CONFIG_SWIZZLE == GLM_SWIZZLE_OPERATOR + template<int E0, int E1, int E2, int E3> + GLM_FUNC_DECL GLM_CONSTEXPR vec(detail::_swizzle<4, T, Q, E0, E1, E2, E3> const& that) + { + *this = that(); + } + + template<int E0, int E1, int F0, int F1> + GLM_FUNC_DECL GLM_CONSTEXPR 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<int E0, int E1> + GLM_FUNC_DECL GLM_CONSTEXPR 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<int E0, int E1> + GLM_FUNC_DECL GLM_CONSTEXPR 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<int E0, int E1> + GLM_FUNC_DECL GLM_CONSTEXPR 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<int E0, int E1, int E2> + GLM_FUNC_DECL GLM_CONSTEXPR vec(detail::_swizzle<3, T, Q, E0, E1, E2, -1> const& v, T const& w) + { + *this = vec<4, T, Q>(v(), w); + } + + template<int E0, int E1, int E2> + GLM_FUNC_DECL GLM_CONSTEXPR 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_FUNC_DECL GLM_CONSTEXPR vec<4, T, Q>& operator=(vec<4, T, Q> const& v) GLM_DEFAULT; + + template<typename U> + GLM_FUNC_DECL GLM_CONSTEXPR vec<4, T, Q>& operator=(vec<4, U, Q> const& v); + template<typename U> + GLM_FUNC_DECL GLM_CONSTEXPR vec<4, T, Q>& operator+=(U scalar); + template<typename U> + GLM_FUNC_DECL GLM_CONSTEXPR vec<4, T, Q>& operator+=(vec<1, U, Q> const& v); + template<typename U> + GLM_FUNC_DECL GLM_CONSTEXPR vec<4, T, Q>& operator+=(vec<4, U, Q> const& v); + template<typename U> + GLM_FUNC_DECL GLM_CONSTEXPR vec<4, T, Q>& operator-=(U scalar); + template<typename U> + GLM_FUNC_DECL GLM_CONSTEXPR vec<4, T, Q>& operator-=(vec<1, U, Q> const& v); + template<typename U> + GLM_FUNC_DECL GLM_CONSTEXPR vec<4, T, Q>& operator-=(vec<4, U, Q> const& v); + template<typename U> + GLM_FUNC_DECL GLM_CONSTEXPR vec<4, T, Q>& operator*=(U scalar); + template<typename U> + GLM_FUNC_DECL GLM_CONSTEXPR vec<4, T, Q>& operator*=(vec<1, U, Q> const& v); + template<typename U> + GLM_FUNC_DECL GLM_CONSTEXPR vec<4, T, Q>& operator*=(vec<4, U, Q> const& v); + template<typename U> + GLM_FUNC_DECL GLM_CONSTEXPR vec<4, T, Q>& operator/=(U scalar); + template<typename U> + GLM_FUNC_DECL GLM_CONSTEXPR vec<4, T, Q>& operator/=(vec<1, U, Q> const& v); + template<typename U> + GLM_FUNC_DECL GLM_CONSTEXPR vec<4, T, Q>& operator/=(vec<4, U, Q> const& v); + + // -- Increment and decrement operators -- + + GLM_FUNC_DECL GLM_CONSTEXPR vec<4, T, Q> & operator++(); + GLM_FUNC_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<typename U> + GLM_FUNC_DECL GLM_CONSTEXPR vec<4, T, Q> & operator%=(U scalar); + template<typename U> + GLM_FUNC_DECL GLM_CONSTEXPR vec<4, T, Q> & operator%=(vec<1, U, Q> const& v); + template<typename U> + GLM_FUNC_DECL GLM_CONSTEXPR vec<4, T, Q> & operator%=(vec<4, U, Q> const& v); + template<typename U> + GLM_FUNC_DECL GLM_CONSTEXPR vec<4, T, Q> & operator&=(U scalar); + template<typename U> + GLM_FUNC_DECL GLM_CONSTEXPR vec<4, T, Q> & operator&=(vec<1, U, Q> const& v); + template<typename U> + GLM_FUNC_DECL GLM_CONSTEXPR vec<4, T, Q> & operator&=(vec<4, U, Q> const& v); + template<typename U> + GLM_FUNC_DECL GLM_CONSTEXPR vec<4, T, Q> & operator|=(U scalar); + template<typename U> + GLM_FUNC_DECL GLM_CONSTEXPR vec<4, T, Q> & operator|=(vec<1, U, Q> const& v); + template<typename U> + GLM_FUNC_DECL GLM_CONSTEXPR vec<4, T, Q> & operator|=(vec<4, U, Q> const& v); + template<typename U> + GLM_FUNC_DECL GLM_CONSTEXPR vec<4, T, Q> & operator^=(U scalar); + template<typename U> + GLM_FUNC_DECL GLM_CONSTEXPR vec<4, T, Q> & operator^=(vec<1, U, Q> const& v); + template<typename U> + GLM_FUNC_DECL GLM_CONSTEXPR vec<4, T, Q> & operator^=(vec<4, U, Q> const& v); + template<typename U> + GLM_FUNC_DECL GLM_CONSTEXPR vec<4, T, Q> & operator<<=(U scalar); + template<typename U> + GLM_FUNC_DECL GLM_CONSTEXPR vec<4, T, Q> & operator<<=(vec<1, U, Q> const& v); + template<typename U> + GLM_FUNC_DECL GLM_CONSTEXPR vec<4, T, Q> & operator<<=(vec<4, U, Q> const& v); + template<typename U> + GLM_FUNC_DECL GLM_CONSTEXPR vec<4, T, Q> & operator>>=(U scalar); + template<typename U> + GLM_FUNC_DECL GLM_CONSTEXPR vec<4, T, Q> & operator>>=(vec<1, U, Q> const& v); + template<typename U> + GLM_FUNC_DECL GLM_CONSTEXPR vec<4, T, Q> & operator>>=(vec<4, U, Q> const& v); + }; + + // -- Unary operators -- + + template<typename T, qualifier Q> + GLM_FUNC_DECL GLM_CONSTEXPR vec<4, T, Q> operator+(vec<4, T, Q> const& v); + + template<typename T, qualifier Q> + GLM_FUNC_DECL GLM_CONSTEXPR vec<4, T, Q> operator-(vec<4, T, Q> const& v); + + // -- Binary operators -- + + template<typename T, qualifier Q> + GLM_FUNC_DECL GLM_CONSTEXPR vec<4, T, Q> operator+(vec<4, T, Q> const& v, T const & scalar); + + template<typename T, qualifier Q> + GLM_FUNC_DECL GLM_CONSTEXPR vec<4, T, Q> operator+(vec<4, T, Q> const& v1, vec<1, T, Q> const& v2); + + template<typename T, qualifier Q> + GLM_FUNC_DECL GLM_CONSTEXPR vec<4, T, Q> operator+(T scalar, vec<4, T, Q> const& v); + + template<typename T, qualifier Q> + GLM_FUNC_DECL GLM_CONSTEXPR vec<4, T, Q> operator+(vec<1, T, Q> const& v1, vec<4, T, Q> const& v2); + + template<typename T, qualifier Q> + GLM_FUNC_DECL GLM_CONSTEXPR vec<4, T, Q> operator+(vec<4, T, Q> const& v1, vec<4, T, Q> const& v2); + + template<typename T, qualifier Q> + GLM_FUNC_DECL GLM_CONSTEXPR vec<4, T, Q> operator-(vec<4, T, Q> const& v, T const & scalar); + + template<typename T, qualifier Q> + GLM_FUNC_DECL GLM_CONSTEXPR vec<4, T, Q> operator-(vec<4, T, Q> const& v1, vec<1, T, Q> const& v2); + + template<typename T, qualifier Q> + GLM_FUNC_DECL GLM_CONSTEXPR vec<4, T, Q> operator-(T scalar, vec<4, T, Q> const& v); + + template<typename T, qualifier Q> + GLM_FUNC_DECL GLM_CONSTEXPR vec<4, T, Q> operator-(vec<1, T, Q> const& v1, vec<4, T, Q> const& v2); + + template<typename T, qualifier Q> + GLM_FUNC_DECL GLM_CONSTEXPR vec<4, T, Q> operator-(vec<4, T, Q> const& v1, vec<4, T, Q> const& v2); + + template<typename T, qualifier Q> + GLM_FUNC_DECL GLM_CONSTEXPR vec<4, T, Q> operator*(vec<4, T, Q> const& v, T const & scalar); + + template<typename T, qualifier Q> + GLM_FUNC_DECL GLM_CONSTEXPR vec<4, T, Q> operator*(vec<4, T, Q> const& v1, vec<1, T, Q> const& v2); + + template<typename T, qualifier Q> + GLM_FUNC_DECL GLM_CONSTEXPR vec<4, T, Q> operator*(T scalar, vec<4, T, Q> const& v); + + template<typename T, qualifier Q> + GLM_FUNC_DECL GLM_CONSTEXPR vec<4, T, Q> operator*(vec<1, T, Q> const& v1, vec<4, T, Q> const& v2); + + template<typename T, qualifier Q> + GLM_FUNC_DECL GLM_CONSTEXPR vec<4, T, Q> operator*(vec<4, T, Q> const& v1, vec<4, T, Q> const& v2); + + template<typename T, qualifier Q> + GLM_FUNC_DECL GLM_CONSTEXPR vec<4, T, Q> operator/(vec<4, T, Q> const& v, T const & scalar); + + template<typename T, qualifier Q> + GLM_FUNC_DECL GLM_CONSTEXPR vec<4, T, Q> operator/(vec<4, T, Q> const& v1, vec<1, T, Q> const& v2); + + template<typename T, qualifier Q> + GLM_FUNC_DECL GLM_CONSTEXPR vec<4, T, Q> operator/(T scalar, vec<4, T, Q> const& v); + + template<typename T, qualifier Q> + GLM_FUNC_DECL GLM_CONSTEXPR vec<4, T, Q> operator/(vec<1, T, Q> const& v1, vec<4, T, Q> const& v2); + + template<typename T, qualifier Q> + GLM_FUNC_DECL GLM_CONSTEXPR vec<4, T, Q> operator/(vec<4, T, Q> const& v1, vec<4, T, Q> const& v2); + + template<typename T, qualifier Q> + GLM_FUNC_DECL GLM_CONSTEXPR vec<4, T, Q> operator%(vec<4, T, Q> const& v, T scalar); + + template<typename T, qualifier Q> + GLM_FUNC_DECL GLM_CONSTEXPR vec<4, T, Q> operator%(vec<4, T, Q> const& v, vec<1, T, Q> const& scalar); + + template<typename T, qualifier Q> + GLM_FUNC_DECL GLM_CONSTEXPR vec<4, T, Q> operator%(T scalar, vec<4, T, Q> const& v); + + template<typename T, qualifier Q> + GLM_FUNC_DECL GLM_CONSTEXPR vec<4, T, Q> operator%(vec<1, T, Q> const& scalar, vec<4, T, Q> const& v); + + template<typename T, qualifier Q> + GLM_FUNC_DECL GLM_CONSTEXPR vec<4, T, Q> operator%(vec<4, T, Q> const& v1, vec<4, T, Q> const& v2); + + template<typename T, qualifier Q> + GLM_FUNC_DECL GLM_CONSTEXPR vec<4, T, Q> operator&(vec<4, T, Q> const& v, T scalar); + + template<typename T, qualifier Q> + GLM_FUNC_DECL GLM_CONSTEXPR vec<4, T, Q> operator&(vec<4, T, Q> const& v, vec<1, T, Q> const& scalar); + + template<typename T, qualifier Q> + GLM_FUNC_DECL GLM_CONSTEXPR vec<4, T, Q> operator&(T scalar, vec<4, T, Q> const& v); + + template<typename T, qualifier Q> + GLM_FUNC_DECL GLM_CONSTEXPR vec<4, T, Q> operator&(vec<1, T, Q> const& scalar, vec<4, T, Q> const& v); + + template<typename T, qualifier Q> + GLM_FUNC_DECL GLM_CONSTEXPR vec<4, T, Q> operator&(vec<4, T, Q> const& v1, vec<4, T, Q> const& v2); + + template<typename T, qualifier Q> + GLM_FUNC_DECL GLM_CONSTEXPR vec<4, T, Q> operator|(vec<4, T, Q> const& v, T scalar); + + template<typename T, qualifier Q> + GLM_FUNC_DECL GLM_CONSTEXPR vec<4, T, Q> operator|(vec<4, T, Q> const& v, vec<1, T, Q> const& scalar); + + template<typename T, qualifier Q> + GLM_FUNC_DECL GLM_CONSTEXPR vec<4, T, Q> operator|(T scalar, vec<4, T, Q> const& v); + + template<typename T, qualifier Q> + GLM_FUNC_DECL GLM_CONSTEXPR vec<4, T, Q> operator|(vec<1, T, Q> const& scalar, vec<4, T, Q> const& v); + + template<typename T, qualifier Q> + GLM_FUNC_DECL GLM_CONSTEXPR vec<4, T, Q> operator|(vec<4, T, Q> const& v1, vec<4, T, Q> const& v2); + + template<typename T, qualifier Q> + GLM_FUNC_DECL GLM_CONSTEXPR vec<4, T, Q> operator^(vec<4, T, Q> const& v, T scalar); + + template<typename T, qualifier Q> + GLM_FUNC_DECL GLM_CONSTEXPR vec<4, T, Q> operator^(vec<4, T, Q> const& v, vec<1, T, Q> const& scalar); + + template<typename T, qualifier Q> + GLM_FUNC_DECL GLM_CONSTEXPR vec<4, T, Q> operator^(T scalar, vec<4, T, Q> const& v); + + template<typename T, qualifier Q> + GLM_FUNC_DECL GLM_CONSTEXPR vec<4, T, Q> operator^(vec<1, T, Q> const& scalar, vec<4, T, Q> const& v); + + template<typename T, qualifier Q> + GLM_FUNC_DECL GLM_CONSTEXPR vec<4, T, Q> operator^(vec<4, T, Q> const& v1, vec<4, T, Q> const& v2); + + template<typename T, qualifier Q> + GLM_FUNC_DECL GLM_CONSTEXPR vec<4, T, Q> operator<<(vec<4, T, Q> const& v, T scalar); + + template<typename T, qualifier Q> + GLM_FUNC_DECL GLM_CONSTEXPR vec<4, T, Q> operator<<(vec<4, T, Q> const& v, vec<1, T, Q> const& scalar); + + template<typename T, qualifier Q> + GLM_FUNC_DECL GLM_CONSTEXPR vec<4, T, Q> operator<<(T scalar, vec<4, T, Q> const& v); + + template<typename T, qualifier Q> + GLM_FUNC_DECL GLM_CONSTEXPR vec<4, T, Q> operator<<(vec<1, T, Q> const& scalar, vec<4, T, Q> const& v); + + template<typename T, qualifier Q> + GLM_FUNC_DECL GLM_CONSTEXPR vec<4, T, Q> operator<<(vec<4, T, Q> const& v1, vec<4, T, Q> const& v2); + + template<typename T, qualifier Q> + GLM_FUNC_DECL GLM_CONSTEXPR vec<4, T, Q> operator>>(vec<4, T, Q> const& v, T scalar); + + template<typename T, qualifier Q> + GLM_FUNC_DECL GLM_CONSTEXPR vec<4, T, Q> operator>>(vec<4, T, Q> const& v, vec<1, T, Q> const& scalar); + + template<typename T, qualifier Q> + GLM_FUNC_DECL GLM_CONSTEXPR vec<4, T, Q> operator>>(T scalar, vec<4, T, Q> const& v); + + template<typename T, qualifier Q> + GLM_FUNC_DECL GLM_CONSTEXPR vec<4, T, Q> operator>>(vec<1, T, Q> const& scalar, vec<4, T, Q> const& v); + + template<typename T, qualifier Q> + GLM_FUNC_DECL GLM_CONSTEXPR vec<4, T, Q> operator>>(vec<4, T, Q> const& v1, vec<4, T, Q> const& v2); + + template<typename T, qualifier Q> + GLM_FUNC_DECL GLM_CONSTEXPR vec<4, T, Q> operator~(vec<4, T, Q> const& v); + + // -- Boolean operators -- + + template<typename T, qualifier Q> + GLM_FUNC_DECL GLM_CONSTEXPR bool operator==(vec<4, T, Q> const& v1, vec<4, T, Q> const& v2); + + template<typename T, qualifier Q> + GLM_FUNC_DECL GLM_CONSTEXPR bool operator!=(vec<4, T, Q> const& v1, vec<4, T, Q> const& v2); + + template<qualifier Q> + GLM_FUNC_DECL GLM_CONSTEXPR vec<4, bool, Q> operator&&(vec<4, bool, Q> const& v1, vec<4, bool, Q> const& v2); + + template<qualifier Q> + 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 0000000000000000000000000000000000000000..3c212d98bbeb05aa98a416fb6dd4f096087b07ab --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/detail/type_vec4.inl @@ -0,0 +1,1140 @@ +/// @ref core + +#include "compute_vector_relational.hpp" + +namespace glm{ +namespace detail +{ + template<typename T, qualifier Q, bool Aligned> + 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<typename T, qualifier Q, bool Aligned> + 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<typename T, qualifier Q, bool Aligned> + 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<typename T, qualifier Q, bool Aligned> + 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<typename T, qualifier Q, bool Aligned> + 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<typename T, qualifier Q, int IsInt, std::size_t Size, bool Aligned> + 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<typename T, qualifier Q, int IsInt, std::size_t Size, bool Aligned> + 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<typename T, qualifier Q, int IsInt, std::size_t Size, bool Aligned> + 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<typename T, qualifier Q, int IsInt, std::size_t Size, bool Aligned> + 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<typename T, qualifier Q, int IsInt, std::size_t Size, bool Aligned> + 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<typename T, qualifier Q, int IsInt, std::size_t Size, bool Aligned> + 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<T, std::numeric_limits<T>::is_iec559>::call(v1.x, v2.x) && + detail::compute_equal<T, std::numeric_limits<T>::is_iec559>::call(v1.y, v2.y) && + detail::compute_equal<T, std::numeric_limits<T>::is_iec559>::call(v1.z, v2.z) && + detail::compute_equal<T, std::numeric_limits<T>::is_iec559>::call(v1.w, v2.w); + } + }; + + template<typename T, qualifier Q, int IsInt, std::size_t Size, bool Aligned> + 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<T, Q, detail::is_int<T>::value, sizeof(T) * 8, detail::is_aligned<Q>::value>::call(v1, v2); + } + }; + + template<typename T, qualifier Q, int IsInt, std::size_t Size, bool Aligned> + 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_FUNCTIONS == GLM_DISABLE + template<typename T, qualifier Q> + GLM_FUNC_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 + {} + + template<typename T, qualifier Q> + GLM_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<typename T, qualifier Q> + template<qualifier P> + 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<typename T, qualifier Q> + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<4, T, Q>::vec(T scalar) + : x(scalar), y(scalar), z(scalar), w(scalar) + {} + + template <typename T, qualifier Q> + 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<typename T, qualifier Q> + template<typename U, qualifier P> + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<4, T, Q>::vec(vec<1, U, P> const& v) + : x(static_cast<T>(v.x)) + , y(static_cast<T>(v.x)) + , z(static_cast<T>(v.x)) + , w(static_cast<T>(v.x)) + {} + + template<typename T, qualifier Q> + template<typename X, typename Y, typename Z, typename W> + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<4, T, Q>::vec(X _x, Y _y, Z _z, W _w) + : x(static_cast<T>(_x)) + , y(static_cast<T>(_y)) + , z(static_cast<T>(_z)) + , w(static_cast<T>(_w)) + {} + + template<typename T, qualifier Q> + template<typename X, typename Y, typename Z, typename W> + 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<T>(_x.x)) + , y(static_cast<T>(_y)) + , z(static_cast<T>(_z)) + , w(static_cast<T>(_w)) + {} + + template<typename T, qualifier Q> + template<typename X, typename Y, typename Z, typename W> + 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<T>(_x)) + , y(static_cast<T>(_y.x)) + , z(static_cast<T>(_z)) + , w(static_cast<T>(_w)) + {} + + template<typename T, qualifier Q> + template<typename X, typename Y, typename Z, typename W> + 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<T>(_x.x)) + , y(static_cast<T>(_y.x)) + , z(static_cast<T>(_z)) + , w(static_cast<T>(_w)) + {} + + template<typename T, qualifier Q> + template<typename X, typename Y, typename Z, typename W> + 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<T>(_x)) + , y(static_cast<T>(_y)) + , z(static_cast<T>(_z.x)) + , w(static_cast<T>(_w)) + {} + + template<typename T, qualifier Q> + template<typename X, typename Y, typename Z, typename W> + 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<T>(_x.x)) + , y(static_cast<T>(_y)) + , z(static_cast<T>(_z.x)) + , w(static_cast<T>(_w)) + {} + + template<typename T, qualifier Q> + template<typename X, typename Y, typename Z, typename W> + 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<T>(_x)) + , y(static_cast<T>(_y.x)) + , z(static_cast<T>(_z.x)) + , w(static_cast<T>(_w)) + {} + + template<typename T, qualifier Q> + template<typename X, typename Y, typename Z, typename W> + 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<T>(_x.x)) + , y(static_cast<T>(_y.x)) + , z(static_cast<T>(_z.x)) + , w(static_cast<T>(_w)) + {} + + template<typename T, qualifier Q> + template<typename X, typename Y, typename Z, typename W> + 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<T>(_x.x)) + , y(static_cast<T>(_y)) + , z(static_cast<T>(_z)) + , w(static_cast<T>(_w.x)) + {} + + template<typename T, qualifier Q> + template<typename X, typename Y, typename Z, typename W> + 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<T>(_x)) + , y(static_cast<T>(_y.x)) + , z(static_cast<T>(_z)) + , w(static_cast<T>(_w.x)) + {} + + template<typename T, qualifier Q> + template<typename X, typename Y, typename Z, typename W> + 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<T>(_x.x)) + , y(static_cast<T>(_y.x)) + , z(static_cast<T>(_z)) + , w(static_cast<T>(_w.x)) + {} + + template<typename T, qualifier Q> + template<typename X, typename Y, typename Z, typename W> + 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<T>(_x)) + , y(static_cast<T>(_y)) + , z(static_cast<T>(_z.x)) + , w(static_cast<T>(_w.x)) + {} + + template<typename T, qualifier Q> + template<typename X, typename Y, typename Z, typename W> + 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<T>(_x.x)) + , y(static_cast<T>(_y)) + , z(static_cast<T>(_z.x)) + , w(static_cast<T>(_w.x)) + {} + + template<typename T, qualifier Q> + template<typename X, typename Y, typename Z, typename W> + 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<T>(_x)) + , y(static_cast<T>(_y.x)) + , z(static_cast<T>(_z.x)) + , w(static_cast<T>(_w.x)) + {} + + template<typename T, qualifier Q> + template<typename X, typename Y, typename Z, typename W> + 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<T>(_x.x)) + , y(static_cast<T>(_y.x)) + , z(static_cast<T>(_z.x)) + , w(static_cast<T>(_w.x)) + {} + + // -- Conversion vector constructors -- + + template<typename T, qualifier Q> + template<typename A, typename B, typename C, qualifier P> + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<4, T, Q>::vec(vec<2, A, P> const& _xy, B _z, C _w) + : x(static_cast<T>(_xy.x)) + , y(static_cast<T>(_xy.y)) + , z(static_cast<T>(_z)) + , w(static_cast<T>(_w)) + {} + + template<typename T, qualifier Q> + template<typename A, typename B, typename C, qualifier P> + 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<T>(_xy.x)) + , y(static_cast<T>(_xy.y)) + , z(static_cast<T>(_z.x)) + , w(static_cast<T>(_w)) + {} + + template<typename T, qualifier Q> + template<typename A, typename B, typename C, qualifier P> + 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<T>(_xy.x)) + , y(static_cast<T>(_xy.y)) + , z(static_cast<T>(_z)) + , w(static_cast<T>(_w.x)) + {} + + template<typename T, qualifier Q> + template<typename A, typename B, typename C, qualifier P> + 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<T>(_xy.x)) + , y(static_cast<T>(_xy.y)) + , z(static_cast<T>(_z.x)) + , w(static_cast<T>(_w.x)) + {} + + template<typename T, qualifier Q> + template<typename A, typename B, typename C, qualifier P> + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<4, T, Q>::vec(A _x, vec<2, B, P> const& _yz, C _w) + : x(static_cast<T>(_x)) + , y(static_cast<T>(_yz.x)) + , z(static_cast<T>(_yz.y)) + , w(static_cast<T>(_w)) + {} + + template<typename T, qualifier Q> + template<typename A, typename B, typename C, qualifier P> + 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<T>(_x.x)) + , y(static_cast<T>(_yz.x)) + , z(static_cast<T>(_yz.y)) + , w(static_cast<T>(_w)) + {} + + template<typename T, qualifier Q> + template<typename A, typename B, typename C, qualifier P> + 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<T>(_x)) + , y(static_cast<T>(_yz.x)) + , z(static_cast<T>(_yz.y)) + , w(static_cast<T>(_w.x)) + {} + + template<typename T, qualifier Q> + template<typename A, typename B, typename C, qualifier P> + 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<T>(_x.x)) + , y(static_cast<T>(_yz.x)) + , z(static_cast<T>(_yz.y)) + , w(static_cast<T>(_w.x)) + {} + + template<typename T, qualifier Q> + template<typename A, typename B, typename C, qualifier P> + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<4, T, Q>::vec(A _x, B _y, vec<2, C, P> const& _zw) + : x(static_cast<T>(_x)) + , y(static_cast<T>(_y)) + , z(static_cast<T>(_zw.x)) + , w(static_cast<T>(_zw.y)) + {} + + template<typename T, qualifier Q> + template<typename A, typename B, typename C, qualifier P> + 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<T>(_x.x)) + , y(static_cast<T>(_y)) + , z(static_cast<T>(_zw.x)) + , w(static_cast<T>(_zw.y)) + {} + + template<typename T, qualifier Q> + template<typename A, typename B, typename C, qualifier P> + 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<T>(_x)) + , y(static_cast<T>(_y.x)) + , z(static_cast<T>(_zw.x)) + , w(static_cast<T>(_zw.y)) + {} + + template<typename T, qualifier Q> + template<typename A, typename B, typename C, qualifier P> + 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<T>(_x.x)) + , y(static_cast<T>(_y.x)) + , z(static_cast<T>(_zw.x)) + , w(static_cast<T>(_zw.y)) + {} + + template<typename T, qualifier Q> + template<typename A, typename B, qualifier P> + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<4, T, Q>::vec(vec<3, A, P> const& _xyz, B _w) + : x(static_cast<T>(_xyz.x)) + , y(static_cast<T>(_xyz.y)) + , z(static_cast<T>(_xyz.z)) + , w(static_cast<T>(_w)) + {} + + template<typename T, qualifier Q> + template<typename A, typename B, qualifier P> + 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<T>(_xyz.x)) + , y(static_cast<T>(_xyz.y)) + , z(static_cast<T>(_xyz.z)) + , w(static_cast<T>(_w.x)) + {} + + template<typename T, qualifier Q> + template<typename A, typename B, qualifier P> + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<4, T, Q>::vec(A _x, vec<3, B, P> const& _yzw) + : x(static_cast<T>(_x)) + , y(static_cast<T>(_yzw.x)) + , z(static_cast<T>(_yzw.y)) + , w(static_cast<T>(_yzw.z)) + {} + + template<typename T, qualifier Q> + template<typename A, typename B, qualifier P> + 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<T>(_x.x)) + , y(static_cast<T>(_yzw.x)) + , z(static_cast<T>(_yzw.y)) + , w(static_cast<T>(_yzw.z)) + {} + + template<typename T, qualifier Q> + template<typename A, typename B, qualifier P> + 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<T>(_xy.x)) + , y(static_cast<T>(_xy.y)) + , z(static_cast<T>(_zw.x)) + , w(static_cast<T>(_zw.y)) + {} + + template<typename T, qualifier Q> + template<typename U, qualifier P> + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<4, T, Q>::vec(vec<4, U, P> const& v) + : x(static_cast<T>(v.x)) + , y(static_cast<T>(v.y)) + , z(static_cast<T>(v.z)) + , w(static_cast<T>(v.w)) + {} + + // -- Component accesses -- + + template<typename T, qualifier Q> + GLM_FUNC_QUALIFIER GLM_CONSTEXPR T& vec<4, T, Q>::operator[](typename vec<4, T, Q>::length_type i) + { + assert(i >= 0 && i < this->length()); + switch(i) + { + default: + case 0: + return x; + case 1: + return y; + case 2: + return z; + case 3: + return w; + } + } + + template<typename T, qualifier Q> + GLM_FUNC_QUALIFIER GLM_CONSTEXPR T const& vec<4, T, Q>::operator[](typename vec<4, T, Q>::length_type i) const + { + assert(i >= 0 && 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<typename T, qualifier Q> + GLM_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<typename T, qualifier Q> + template<typename U> + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<4, T, Q>& vec<4, T, Q>::operator=(vec<4, U, Q> const& v) + { + this->x = static_cast<T>(v.x); + this->y = static_cast<T>(v.y); + this->z = static_cast<T>(v.z); + this->w = static_cast<T>(v.w); + return *this; + } + + template<typename T, qualifier Q> + template<typename U> + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<4, T, Q> & vec<4, T, Q>::operator+=(U scalar) + { + return (*this = detail::compute_vec4_add<T, Q, detail::is_aligned<Q>::value>::call(*this, vec<4, T, Q>(scalar))); + } + + template<typename T, qualifier Q> + template<typename U> + 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<T, Q, detail::is_aligned<Q>::value>::call(*this, vec<4, T, Q>(v.x))); + } + + template<typename T, qualifier Q> + template<typename U> + 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<T, Q, detail::is_aligned<Q>::value>::call(*this, vec<4, T, Q>(v))); + } + + template<typename T, qualifier Q> + template<typename U> + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<4, T, Q> & vec<4, T, Q>::operator-=(U scalar) + { + return (*this = detail::compute_vec4_sub<T, Q, detail::is_aligned<Q>::value>::call(*this, vec<4, T, Q>(scalar))); + } + + template<typename T, qualifier Q> + template<typename U> + 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<T, Q, detail::is_aligned<Q>::value>::call(*this, vec<4, T, Q>(v.x))); + } + + template<typename T, qualifier Q> + template<typename U> + 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<T, Q, detail::is_aligned<Q>::value>::call(*this, vec<4, T, Q>(v))); + } + + template<typename T, qualifier Q> + template<typename U> + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<4, T, Q> & vec<4, T, Q>::operator*=(U scalar) + { + return (*this = detail::compute_vec4_mul<T, Q, detail::is_aligned<Q>::value>::call(*this, vec<4, T, Q>(scalar))); + } + + template<typename T, qualifier Q> + template<typename U> + 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<T, Q, detail::is_aligned<Q>::value>::call(*this, vec<4, T, Q>(v.x))); + } + + template<typename T, qualifier Q> + template<typename U> + 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<T, Q, detail::is_aligned<Q>::value>::call(*this, vec<4, T, Q>(v))); + } + + template<typename T, qualifier Q> + template<typename U> + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<4, T, Q> & vec<4, T, Q>::operator/=(U scalar) + { + return (*this = detail::compute_vec4_div<T, Q, detail::is_aligned<Q>::value>::call(*this, vec<4, T, Q>(scalar))); + } + + template<typename T, qualifier Q> + template<typename U> + 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<T, Q, detail::is_aligned<Q>::value>::call(*this, vec<4, T, Q>(v.x))); + } + + template<typename T, qualifier Q> + template<typename U> + 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<T, Q, detail::is_aligned<Q>::value>::call(*this, vec<4, T, Q>(v))); + } + + // -- Increment and decrement operators -- + + template<typename T, qualifier Q> + 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<typename T, qualifier Q> + 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<typename T, qualifier Q> + 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<typename T, qualifier Q> + 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<typename T, qualifier Q> + template<typename U> + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<4, T, Q> & vec<4, T, Q>::operator%=(U scalar) + { + return (*this = detail::compute_vec4_mod<T, Q, detail::is_aligned<Q>::value>::call(*this, vec<4, T, Q>(scalar))); + } + + template<typename T, qualifier Q> + template<typename U> + 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<T, Q, detail::is_aligned<Q>::value>::call(*this, vec<4, T, Q>(v))); + } + + template<typename T, qualifier Q> + template<typename U> + 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<T, Q, detail::is_aligned<Q>::value>::call(*this, vec<4, T, Q>(v))); + } + + template<typename T, qualifier Q> + template<typename U> + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<4, T, Q> & vec<4, T, Q>::operator&=(U scalar) + { + return (*this = detail::compute_vec4_and<T, Q, detail::is_int<T>::value, sizeof(T) * 8, detail::is_aligned<Q>::value>::call(*this, vec<4, T, Q>(scalar))); + } + + template<typename T, qualifier Q> + template<typename U> + 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<T, Q, detail::is_int<T>::value, sizeof(T) * 8, detail::is_aligned<Q>::value>::call(*this, vec<4, T, Q>(v))); + } + + template<typename T, qualifier Q> + template<typename U> + 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<T, Q, detail::is_int<T>::value, sizeof(T) * 8, detail::is_aligned<Q>::value>::call(*this, vec<4, T, Q>(v))); + } + + template<typename T, qualifier Q> + template<typename U> + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<4, T, Q> & vec<4, T, Q>::operator|=(U scalar) + { + return (*this = detail::compute_vec4_or<T, Q, detail::is_int<T>::value, sizeof(T) * 8, detail::is_aligned<Q>::value>::call(*this, vec<4, T, Q>(scalar))); + } + + template<typename T, qualifier Q> + template<typename U> + 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<T, Q, detail::is_int<T>::value, sizeof(T) * 8, detail::is_aligned<Q>::value>::call(*this, vec<4, T, Q>(v))); + } + + template<typename T, qualifier Q> + template<typename U> + 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<T, Q, detail::is_int<T>::value, sizeof(T) * 8, detail::is_aligned<Q>::value>::call(*this, vec<4, T, Q>(v))); + } + + template<typename T, qualifier Q> + template<typename U> + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<4, T, Q> & vec<4, T, Q>::operator^=(U scalar) + { + return (*this = detail::compute_vec4_xor<T, Q, detail::is_int<T>::value, sizeof(T) * 8, detail::is_aligned<Q>::value>::call(*this, vec<4, T, Q>(scalar))); + } + + template<typename T, qualifier Q> + template<typename U> + 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<T, Q, detail::is_int<T>::value, sizeof(T) * 8, detail::is_aligned<Q>::value>::call(*this, vec<4, T, Q>(v))); + } + + template<typename T, qualifier Q> + template<typename U> + 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<T, Q, detail::is_int<T>::value, sizeof(T) * 8, detail::is_aligned<Q>::value>::call(*this, vec<4, T, Q>(v))); + } + + template<typename T, qualifier Q> + template<typename U> + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<4, T, Q> & vec<4, T, Q>::operator<<=(U scalar) + { + return (*this = detail::compute_vec4_shift_left<T, Q, detail::is_int<T>::value, sizeof(T) * 8, detail::is_aligned<Q>::value>::call(*this, vec<4, T, Q>(scalar))); + } + + template<typename T, qualifier Q> + template<typename U> + 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<T, Q, detail::is_int<T>::value, sizeof(T) * 8, detail::is_aligned<Q>::value>::call(*this, vec<4, T, Q>(v))); + } + + template<typename T, qualifier Q> + template<typename U> + 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<T, Q, detail::is_int<T>::value, sizeof(T) * 8, detail::is_aligned<Q>::value>::call(*this, vec<4, T, Q>(v))); + } + + template<typename T, qualifier Q> + template<typename U> + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<4, T, Q> & vec<4, T, Q>::operator>>=(U scalar) + { + return (*this = detail::compute_vec4_shift_right<T, Q, detail::is_int<T>::value, sizeof(T) * 8, detail::is_aligned<Q>::value>::call(*this, vec<4, T, Q>(scalar))); + } + + template<typename T, qualifier Q> + template<typename U> + 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<T, Q, detail::is_int<T>::value, sizeof(T) * 8, detail::is_aligned<Q>::value>::call(*this, vec<4, T, Q>(v))); + } + + template<typename T, qualifier Q> + template<typename U> + 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<T, Q, detail::is_int<T>::value, sizeof(T) * 8, detail::is_aligned<Q>::value>::call(*this, vec<4, T, Q>(v))); + } + + // -- Unary constant operators -- + + template<typename T, qualifier Q> + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<4, T, Q> operator+(vec<4, T, Q> const& v) + { + return v; + } + + template<typename T, qualifier Q> + 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<typename T, qualifier Q> + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<4, T, Q> operator+(vec<4, T, Q> const& v, T const & scalar) + { + return vec<4, T, Q>(v) += scalar; + } + + template<typename T, qualifier Q> + 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<typename T, qualifier Q> + 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<typename T, qualifier Q> + 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<typename T, qualifier Q> + 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<typename T, qualifier Q> + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<4, T, Q> operator-(vec<4, T, Q> const& v, T const & scalar) + { + return vec<4, T, Q>(v) -= scalar; + } + + template<typename T, qualifier Q> + 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<typename T, qualifier Q> + 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<typename T, qualifier Q> + 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<typename T, qualifier Q> + 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<typename T, qualifier Q> + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<4, T, Q> operator*(vec<4, T, Q> const& v, T const & scalar) + { + return vec<4, T, Q>(v) *= scalar; + } + + template<typename T, qualifier Q> + 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<typename T, qualifier Q> + 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<typename T, qualifier Q> + 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<typename T, qualifier Q> + 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<typename T, qualifier Q> + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<4, T, Q> operator/(vec<4, T, Q> const& v, T const & scalar) + { + return vec<4, T, Q>(v) /= scalar; + } + + template<typename T, qualifier Q> + 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<typename T, qualifier Q> + 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<typename T, qualifier Q> + 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<typename T, qualifier Q> + 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<typename T, qualifier Q> + 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<typename T, qualifier Q> + 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<typename T, qualifier Q> + 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<typename T, qualifier Q> + 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<typename T, qualifier Q> + 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<typename T, qualifier Q> + 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<typename T, qualifier Q> + 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<typename T, qualifier Q> + 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<typename T, qualifier Q> + 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<typename T, qualifier Q> + 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<typename T, qualifier Q> + 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<typename T, qualifier Q> + 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<typename T, qualifier Q> + 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<typename T, qualifier Q> + 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<typename T, qualifier Q> + 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<typename T, qualifier Q> + 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<typename T, qualifier Q> + 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<typename T, qualifier Q> + 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<typename T, qualifier Q> + 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<typename T, qualifier Q> + 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<typename T, qualifier Q> + 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<typename T, qualifier Q> + 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<typename T, qualifier Q> + 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<typename T, qualifier Q> + 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<typename T, qualifier Q> + 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<typename T, qualifier Q> + 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<typename T, qualifier Q> + 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<typename T, qualifier Q> + 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<typename T, qualifier Q> + 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<typename T, qualifier Q> + 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<typename T, qualifier Q> + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<4, T, Q> operator~(vec<4, T, Q> const& v) + { + return detail::compute_vec4_bitwise_not<T, Q, detail::is_int<T>::value, sizeof(T) * 8, detail::is_aligned<Q>::value>::call(v); + } + + // -- Boolean operators -- + + template<typename T, qualifier Q> + GLM_FUNC_QUALIFIER GLM_CONSTEXPR bool operator==(vec<4, T, Q> const& v1, vec<4, T, Q> const& v2) + { + return detail::compute_vec4_equal<T, Q, detail::is_int<T>::value, sizeof(T) * 8, detail::is_aligned<Q>::value>::call(v1, v2); + } + + template<typename T, qualifier Q> + GLM_FUNC_QUALIFIER GLM_CONSTEXPR bool operator!=(vec<4, T, Q> const& v1, vec<4, T, Q> const& v2) + { + return detail::compute_vec4_nequal<T, Q, detail::is_int<T>::value, sizeof(T) * 8, detail::is_aligned<Q>::value>::call(v1, v2); + } + + template<qualifier Q> + 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<qualifier Q> + 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 0000000000000000000000000000000000000000..29559b5350c2b9be6d89280360a43edb41441040 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/detail/type_vec4_simd.inl @@ -0,0 +1,775 @@ +#if GLM_ARCH & GLM_ARCH_SSE2_BIT + +namespace glm{ +namespace detail +{ +# if GLM_CONFIG_SWIZZLE == GLM_SWIZZLE_OPERATOR + template<qualifier Q, int E0, int E1, int E2, int E3> + struct _swizzle_base1<4, float, Q, E0,E1,E2,E3, true> : public _swizzle_base0<float, 4> + { + 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<qualifier Q, int E0, int E1, int E2, int E3> + struct _swizzle_base1<4, int, Q, E0,E1,E2,E3, true> : public _swizzle_base0<int, 4> + { + 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<qualifier Q, int E0, int E1, int E2, int E3> + struct _swizzle_base1<4, uint, Q, E0,E1,E2,E3, true> : public _swizzle_base0<uint, 4> + { + 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<qualifier Q> + struct compute_vec4_add<float, Q, true> + { + 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<qualifier Q> + struct compute_vec4_add<double, Q, true> + { + 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<qualifier Q> + struct compute_vec4_sub<float, Q, true> + { + 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<qualifier Q> + struct compute_vec4_sub<double, Q, true> + { + 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<qualifier Q> + struct compute_vec4_mul<float, Q, true> + { + 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<qualifier Q> + struct compute_vec4_mul<double, Q, true> + { + 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<qualifier Q> + struct compute_vec4_div<float, Q, true> + { + 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<qualifier Q> + struct compute_vec4_div<double, Q, true> + { + 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<float, aligned_lowp, true> + { + 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<typename T, qualifier Q> + struct compute_vec4_and<T, Q, true, 32, true> + { + 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<typename T, qualifier Q> + struct compute_vec4_and<T, Q, true, 64, true> + { + 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<typename T, qualifier Q> + struct compute_vec4_or<T, Q, true, 32, true> + { + 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<typename T, qualifier Q> + struct compute_vec4_or<T, Q, true, 64, true> + { + 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<typename T, qualifier Q> + struct compute_vec4_xor<T, Q, true, 32, true> + { + 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<typename T, qualifier Q> + struct compute_vec4_xor<T, Q, true, 64, true> + { + 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<typename T, qualifier Q> + struct compute_vec4_shift_left<T, Q, true, 32, true> + { + 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<typename T, qualifier Q> + struct compute_vec4_shift_left<T, Q, true, 64, true> + { + 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<typename T, qualifier Q> + struct compute_vec4_shift_right<T, Q, true, 32, true> + { + 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<typename T, qualifier Q> + struct compute_vec4_shift_right<T, Q, true, 64, true> + { + 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<typename T, qualifier Q> + struct compute_vec4_bitwise_not<T, Q, true, 32, true> + { + 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<typename T, qualifier Q> + struct compute_vec4_bitwise_not<T, Q, true, 64, true> + { + 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<qualifier Q> + struct compute_vec4_equal<float, Q, false, 32, true> + { + static bool call(vec<4, float, Q> const& v1, vec<4, float, Q> const& v2) + { + return _mm_movemask_ps(_mm_cmpeq_ps(v1.data, v2.data)) != 0; + } + }; + +# if GLM_ARCH & GLM_ARCH_SSE41_BIT + template<qualifier Q> + struct compute_vec4_equal<int, Q, true, 32, true> + { + 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<qualifier Q> + struct compute_vec4_nequal<float, Q, false, 32, true> + { + 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<qualifier Q> + struct compute_vec4_nequal<int, Q, true, 32, true> + { + 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<qualifier Q> + struct compute_vec4_add<float, Q, true> + { + 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<qualifier Q> + struct compute_vec4_add<uint, Q, true> + { + 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<qualifier Q> + struct compute_vec4_add<int, Q, true> + { + static + vec<4, int, Q> + call(vec<4, int, Q> const& a, vec<4, int, Q> const& b) + { + vec<4, uint, Q> Result; + Result.data = vaddq_s32(a.data, b.data); + return Result; + } + }; + + template<qualifier Q> + struct compute_vec4_sub<float, Q, true> + { + 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<qualifier Q> + struct compute_vec4_sub<uint, Q, true> + { + 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<qualifier Q> + struct compute_vec4_sub<int, Q, true> + { + 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<qualifier Q> + struct compute_vec4_mul<float, Q, true> + { + 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<qualifier Q> + struct compute_vec4_mul<uint, Q, true> + { + 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<qualifier Q> + struct compute_vec4_mul<int, Q, true> + { + 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<qualifier Q> + struct compute_vec4_div<float, Q, true> + { + 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 = vdivq_f32(a.data, b.data); + return Result; + } + }; + + template<qualifier Q> + struct compute_vec4_equal<float, Q, false, 32, true> + { + 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_f32(cmp), vget_high_f32(cmp)); + cmpx2 = vpmin_u32(cmpx2, cmpx2); + uint32_t r = cmpx2[0]; +#endif + return r == ~0u; + } + }; + + template<qualifier Q> + struct compute_vec4_equal<uint, Q, false, 32, true> + { + 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_f32(cmp), vget_high_f32(cmp)); + cmpx2 = vpmin_u32(cmpx2, cmpx2); + uint32_t r = cmpx2[0]; +#endif + return r == ~0u; + } + }; + + template<qualifier Q> + struct compute_vec4_equal<int, Q, false, 32, true> + { + 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_f32(cmp), vget_high_f32(cmp)); + cmpx2 = vpmin_u32(cmpx2, cmpx2); + uint32_t r = cmpx2[0]; +#endif + return r == ~0u; + } + }; + + template<qualifier Q> + struct compute_vec4_nequal<float, Q, false, 32, true> + { + static bool call(vec<4, float, Q> const& v1, vec<4, float, Q> const& v2) + { + return !compute_vec4_equal<float, Q, false, 32, true>::call(v1, v2); + } + }; + + template<qualifier Q> + struct compute_vec4_nequal<uint, Q, false, 32, true> + { + static bool call(vec<4, uint, Q> const& v1, vec<4, uint, Q> const& v2) + { + return !compute_vec4_equal<uint, Q, false, 32, true>::call(v1, v2); + } + }; + + template<qualifier Q> + struct compute_vec4_nequal<int, Q, false, 32, true> + { + static bool call(vec<4, int, Q> const& v1, vec<4, int, Q> const& v2) + { + return !compute_vec4_equal<int, Q, false, 32, true>::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 0000000000000000000000000000000000000000..f8fb886f6ed8a1b8f5ba29a86dba6719af05caff --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/exponential.hpp @@ -0,0 +1,110 @@ +/// @ref core +/// @file glm/exponential.hpp +/// +/// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 8.2 Exponential Functions</a> +/// +/// @defgroup core_func_exponential Exponential functions +/// @ingroup core +/// +/// Provides GLSL exponential functions +/// +/// These all operate component-wise. The description is per component. +/// +/// Include <glm/exponential.hpp> 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 <cmath> + +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 <a href="http://www.opengl.org/sdk/docs/manglsl/xhtml/pow.xml">GLSL pow man page</a> + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 8.2 Exponential Functions</a> + template<length_t L, typename T, qualifier Q> + GLM_FUNC_DECL vec<L, T, Q> pow(vec<L, T, Q> const& base, vec<L, T, Q> const& exponent); + + /// Returns the natural exponentiation of x, i.e., e^x. + /// + /// @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 <a href="http://www.opengl.org/sdk/docs/manglsl/xhtml/exp.xml">GLSL exp man page</a> + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 8.2 Exponential Functions</a> + template<length_t L, typename T, qualifier Q> + GLM_FUNC_DECL vec<L, T, Q> exp(vec<L, T, Q> 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 <a href="http://www.opengl.org/sdk/docs/manglsl/xhtml/log.xml">GLSL log man page</a> + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 8.2 Exponential Functions</a> + template<length_t L, typename T, qualifier Q> + GLM_FUNC_DECL vec<L, T, Q> log(vec<L, T, Q> 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 <a href="http://www.opengl.org/sdk/docs/manglsl/xhtml/exp2.xml">GLSL exp2 man page</a> + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 8.2 Exponential Functions</a> + template<length_t L, typename T, qualifier Q> + GLM_FUNC_DECL vec<L, T, Q> exp2(vec<L, T, Q> 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 <a href="http://www.opengl.org/sdk/docs/manglsl/xhtml/log2.xml">GLSL log2 man page</a> + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 8.2 Exponential Functions</a> + template<length_t L, typename T, qualifier Q> + GLM_FUNC_DECL vec<L, T, Q> log2(vec<L, T, Q> 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 <a href="http://www.opengl.org/sdk/docs/manglsl/xhtml/sqrt.xml">GLSL sqrt man page</a> + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 8.2 Exponential Functions</a> + template<length_t L, typename T, qualifier Q> + GLM_FUNC_DECL vec<L, T, Q> sqrt(vec<L, T, Q> 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 <a href="http://www.opengl.org/sdk/docs/manglsl/xhtml/inversesqrt.xml">GLSL inversesqrt man page</a> + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 8.2 Exponential Functions</a> + template<length_t L, typename T, qualifier Q> + GLM_FUNC_DECL vec<L, T, Q> inversesqrt(vec<L, T, Q> 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 0000000000000000000000000000000000000000..3249fb991cef0d9967fb1dd4250ccfaeaf5e865e --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/ext.hpp @@ -0,0 +1,253 @@ +/// @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_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_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/compatibility.hpp" +#include "./gtx/component_wise.hpp" +#include "./gtx/dual_quaternion.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" +#include "./gtx/integer.hpp" +#include "./gtx/intersect.hpp" +#include "./gtx/log_base.hpp" +#include "./gtx/matrix_cross_product.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/perpendicular.hpp" +#include "./gtx/polar_coordinates.hpp" +#include "./gtx/projection.hpp" +#include "./gtx/quaternion.hpp" +#include "./gtx/raw_data.hpp" +#include "./gtx/rotate_vector.hpp" +#include "./gtx/spline.hpp" +#include "./gtx/std_based_type.hpp" +#if !(GLM_COMPILER & GLM_COMPILER_CUDA) +# 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_clip_space.hpp b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/ext/matrix_clip_space.hpp new file mode 100644 index 0000000000000000000000000000000000000000..c3874f2f8d753268e6f20618b9d448a6eb62c0d4 --- /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 <glm/ext/matrix_clip_space.hpp> 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 <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl2.1/xhtml/gluOrtho2D.xml">gluOrtho2D man page</a> + template<typename T> + 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<typename T> + 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 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<typename T> + 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 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<typename T> + 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<typename T> + 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<typename T> + 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<typename T> + 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<typename T> + 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<typename T> + 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 <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl2.1/xhtml/glOrtho.xml">glOrtho man page</a> + template<typename T> + 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<typename T> + 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<typename T> + 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<typename T> + 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<typename T> + 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<typename T> + 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<typename T> + 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<typename T> + 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<typename T> + 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 <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl2.1/xhtml/glFrustum.xml">glFrustum man page</a> + template<typename T> + 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, symetric 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<typename T> + 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, symetric 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<typename T> + 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, symetric 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<typename T> + 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, symetric 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<typename T> + GLM_FUNC_DECL mat<4, 4, T, defaultp> perspectiveLH_NO( + T fovy, T aspect, T near, T far); + + /// Creates a matrix for a symetric 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<typename T> + GLM_FUNC_DECL mat<4, 4, T, defaultp> perspectiveZO( + T fovy, T aspect, T near, T far); + + /// Creates a matrix for a symetric 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<typename T> + GLM_FUNC_DECL mat<4, 4, T, defaultp> perspectiveNO( + T fovy, T aspect, T near, T far); + + /// Creates a matrix for a right handed, symetric 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<typename T> + GLM_FUNC_DECL mat<4, 4, T, defaultp> perspectiveRH( + T fovy, T aspect, T near, T far); + + /// Creates a matrix for a left handed, symetric 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<typename T> + GLM_FUNC_DECL mat<4, 4, T, defaultp> perspectiveLH( + T fovy, T aspect, T near, T far); + + /// Creates a matrix for a symetric 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 <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl2.1/xhtml/gluPerspective.xml">gluPerspective man page</a> + template<typename T> + 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<typename T> + 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<typename T> + 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<typename T> + 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<typename T> + 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<typename T> + 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<typename T> + 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<typename T> + 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<typename T> + 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<typename T> + 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<typename T> + 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<typename T> + 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<typename T> + 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<typename T> + 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<typename T> + 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 0000000000000000000000000000000000000000..7e4df33004ef55bcb4ae01136c94ac97a5157b94 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/ext/matrix_clip_space.inl @@ -0,0 +1,555 @@ +namespace glm +{ + template<typename T> + 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<T>(1)); + Result[0][0] = static_cast<T>(2) / (right - left); + Result[1][1] = static_cast<T>(2) / (top - bottom); + Result[2][2] = - static_cast<T>(1); + Result[3][0] = - (right + left) / (right - left); + Result[3][1] = - (top + bottom) / (top - bottom); + return Result; + } + + template<typename T> + 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<T>(2) / (right - left); + Result[1][1] = static_cast<T>(2) / (top - bottom); + Result[2][2] = static_cast<T>(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<typename T> + 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<T>(2) / (right - left); + Result[1][1] = static_cast<T>(2) / (top - bottom); + Result[2][2] = static_cast<T>(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<typename T> + 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<T>(2) / (right - left); + Result[1][1] = static_cast<T>(2) / (top - bottom); + Result[2][2] = - static_cast<T>(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<typename T> + 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<T>(2) / (right - left); + Result[1][1] = static_cast<T>(2) / (top - bottom); + Result[2][2] = - static_cast<T>(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<typename T> + 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<typename T> + 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<typename T> + 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<typename T> + 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<typename T> + 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<typename T> + 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<T>(2) * nearVal) / (right - left); + Result[1][1] = (static_cast<T>(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<T>(1); + Result[3][2] = -(farVal * nearVal) / (farVal - nearVal); + return Result; + } + + template<typename T> + 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<T>(2) * nearVal) / (right - left); + Result[1][1] = (static_cast<T>(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<T>(1); + Result[3][2] = - (static_cast<T>(2) * farVal * nearVal) / (farVal - nearVal); + return Result; + } + + template<typename T> + 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<T>(2) * nearVal) / (right - left); + Result[1][1] = (static_cast<T>(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<T>(-1); + Result[3][2] = -(farVal * nearVal) / (farVal - nearVal); + return Result; + } + + template<typename T> + 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<T>(2) * nearVal) / (right - left); + Result[1][1] = (static_cast<T>(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<T>(-1); + Result[3][2] = - (static_cast<T>(2) * farVal * nearVal) / (farVal - nearVal); + return Result; + } + + template<typename T> + 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<typename T> + 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<typename T> + 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<typename T> + 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<typename T> + 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<typename T> + GLM_FUNC_QUALIFIER mat<4, 4, T, defaultp> perspectiveRH_ZO(T fovy, T aspect, T zNear, T zFar) + { + assert(abs(aspect - std::numeric_limits<T>::epsilon()) > static_cast<T>(0)); + + T const tanHalfFovy = tan(fovy / static_cast<T>(2)); + + mat<4, 4, T, defaultp> Result(static_cast<T>(0)); + Result[0][0] = static_cast<T>(1) / (aspect * tanHalfFovy); + Result[1][1] = static_cast<T>(1) / (tanHalfFovy); + Result[2][2] = zFar / (zNear - zFar); + Result[2][3] = - static_cast<T>(1); + Result[3][2] = -(zFar * zNear) / (zFar - zNear); + return Result; + } + + template<typename T> + GLM_FUNC_QUALIFIER mat<4, 4, T, defaultp> perspectiveRH_NO(T fovy, T aspect, T zNear, T zFar) + { + assert(abs(aspect - std::numeric_limits<T>::epsilon()) > static_cast<T>(0)); + + T const tanHalfFovy = tan(fovy / static_cast<T>(2)); + + mat<4, 4, T, defaultp> Result(static_cast<T>(0)); + Result[0][0] = static_cast<T>(1) / (aspect * tanHalfFovy); + Result[1][1] = static_cast<T>(1) / (tanHalfFovy); + Result[2][2] = - (zFar + zNear) / (zFar - zNear); + Result[2][3] = - static_cast<T>(1); + Result[3][2] = - (static_cast<T>(2) * zFar * zNear) / (zFar - zNear); + return Result; + } + + template<typename T> + GLM_FUNC_QUALIFIER mat<4, 4, T, defaultp> perspectiveLH_ZO(T fovy, T aspect, T zNear, T zFar) + { + assert(abs(aspect - std::numeric_limits<T>::epsilon()) > static_cast<T>(0)); + + T const tanHalfFovy = tan(fovy / static_cast<T>(2)); + + mat<4, 4, T, defaultp> Result(static_cast<T>(0)); + Result[0][0] = static_cast<T>(1) / (aspect * tanHalfFovy); + Result[1][1] = static_cast<T>(1) / (tanHalfFovy); + Result[2][2] = zFar / (zFar - zNear); + Result[2][3] = static_cast<T>(1); + Result[3][2] = -(zFar * zNear) / (zFar - zNear); + return Result; + } + + template<typename T> + GLM_FUNC_QUALIFIER mat<4, 4, T, defaultp> perspectiveLH_NO(T fovy, T aspect, T zNear, T zFar) + { + assert(abs(aspect - std::numeric_limits<T>::epsilon()) > static_cast<T>(0)); + + T const tanHalfFovy = tan(fovy / static_cast<T>(2)); + + mat<4, 4, T, defaultp> Result(static_cast<T>(0)); + Result[0][0] = static_cast<T>(1) / (aspect * tanHalfFovy); + Result[1][1] = static_cast<T>(1) / (tanHalfFovy); + Result[2][2] = (zFar + zNear) / (zFar - zNear); + Result[2][3] = static_cast<T>(1); + Result[3][2] = - (static_cast<T>(2) * zFar * zNear) / (zFar - zNear); + return Result; + } + + template<typename T> + 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<typename T> + 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<typename T> + 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<typename T> + 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<typename T> + 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<typename T> + GLM_FUNC_QUALIFIER mat<4, 4, T, defaultp> perspectiveFovRH_ZO(T fov, T width, T height, T zNear, T zFar) + { + assert(width > static_cast<T>(0)); + assert(height > static_cast<T>(0)); + assert(fov > static_cast<T>(0)); + + T const rad = fov; + T const h = glm::cos(static_cast<T>(0.5) * rad) / glm::sin(static_cast<T>(0.5) * rad); + T const w = h * height / width; ///todo max(width , Height) / min(width , Height)? + + mat<4, 4, T, defaultp> Result(static_cast<T>(0)); + Result[0][0] = w; + Result[1][1] = h; + Result[2][2] = zFar / (zNear - zFar); + Result[2][3] = - static_cast<T>(1); + Result[3][2] = -(zFar * zNear) / (zFar - zNear); + return Result; + } + + template<typename T> + GLM_FUNC_QUALIFIER mat<4, 4, T, defaultp> perspectiveFovRH_NO(T fov, T width, T height, T zNear, T zFar) + { + assert(width > static_cast<T>(0)); + assert(height > static_cast<T>(0)); + assert(fov > static_cast<T>(0)); + + T const rad = fov; + T const h = glm::cos(static_cast<T>(0.5) * rad) / glm::sin(static_cast<T>(0.5) * rad); + T const w = h * height / width; ///todo max(width , Height) / min(width , Height)? + + mat<4, 4, T, defaultp> Result(static_cast<T>(0)); + Result[0][0] = w; + Result[1][1] = h; + Result[2][2] = - (zFar + zNear) / (zFar - zNear); + Result[2][3] = - static_cast<T>(1); + Result[3][2] = - (static_cast<T>(2) * zFar * zNear) / (zFar - zNear); + return Result; + } + + template<typename T> + GLM_FUNC_QUALIFIER mat<4, 4, T, defaultp> perspectiveFovLH_ZO(T fov, T width, T height, T zNear, T zFar) + { + assert(width > static_cast<T>(0)); + assert(height > static_cast<T>(0)); + assert(fov > static_cast<T>(0)); + + T const rad = fov; + T const h = glm::cos(static_cast<T>(0.5) * rad) / glm::sin(static_cast<T>(0.5) * rad); + T const w = h * height / width; ///todo max(width , Height) / min(width , Height)? + + mat<4, 4, T, defaultp> Result(static_cast<T>(0)); + Result[0][0] = w; + Result[1][1] = h; + Result[2][2] = zFar / (zFar - zNear); + Result[2][3] = static_cast<T>(1); + Result[3][2] = -(zFar * zNear) / (zFar - zNear); + return Result; + } + + template<typename T> + GLM_FUNC_QUALIFIER mat<4, 4, T, defaultp> perspectiveFovLH_NO(T fov, T width, T height, T zNear, T zFar) + { + assert(width > static_cast<T>(0)); + assert(height > static_cast<T>(0)); + assert(fov > static_cast<T>(0)); + + T const rad = fov; + T const h = glm::cos(static_cast<T>(0.5) * rad) / glm::sin(static_cast<T>(0.5) * rad); + T const w = h * height / width; ///todo max(width , Height) / min(width , Height)? + + mat<4, 4, T, defaultp> Result(static_cast<T>(0)); + Result[0][0] = w; + Result[1][1] = h; + Result[2][2] = (zFar + zNear) / (zFar - zNear); + Result[2][3] = static_cast<T>(1); + Result[3][2] = - (static_cast<T>(2) * zFar * zNear) / (zFar - zNear); + return Result; + } + + template<typename T> + 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<typename T> + 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<typename T> + 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<typename T> + 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<typename T> + 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<typename T> + GLM_FUNC_QUALIFIER mat<4, 4, T, defaultp> infinitePerspectiveRH(T fovy, T aspect, T zNear) + { + T const range = tan(fovy / static_cast<T>(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<T>(0)); + Result[0][0] = (static_cast<T>(2) * zNear) / (right - left); + Result[1][1] = (static_cast<T>(2) * zNear) / (top - bottom); + Result[2][2] = - static_cast<T>(1); + Result[2][3] = - static_cast<T>(1); + Result[3][2] = - static_cast<T>(2) * zNear; + return Result; + } + + template<typename T> + GLM_FUNC_QUALIFIER mat<4, 4, T, defaultp> infinitePerspectiveLH(T fovy, T aspect, T zNear) + { + T const range = tan(fovy / static_cast<T>(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<T>(2) * zNear) / (right - left); + Result[1][1] = (static_cast<T>(2) * zNear) / (top - bottom); + Result[2][2] = static_cast<T>(1); + Result[2][3] = static_cast<T>(1); + Result[3][2] = - static_cast<T>(2) * zNear; + return Result; + } + + template<typename T> + GLM_FUNC_QUALIFIER mat<4, 4, T, defaultp> infinitePerspective(T fovy, T aspect, T zNear) + { +# if GLM_CONFIG_CLIP_CONTROL & GLM_CLIP_CONTROL_LH_BIT + return infinitePerspectiveLH(fovy, aspect, zNear); +# else + return infinitePerspectiveRH(fovy, aspect, zNear); +# endif + } + + // Infinite projection matrix: http://www.terathon.com/gdc07_lengyel.pdf + template<typename T> + GLM_FUNC_QUALIFIER mat<4, 4, T, defaultp> tweakedInfinitePerspective(T fovy, T aspect, T zNear, T ep) + { + T const range = tan(fovy / static_cast<T>(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<T>(0)); + Result[0][0] = (static_cast<T>(2) * zNear) / (right - left); + Result[1][1] = (static_cast<T>(2) * zNear) / (top - bottom); + Result[2][2] = ep - static_cast<T>(1); + Result[2][3] = static_cast<T>(-1); + Result[3][2] = (ep - static_cast<T>(2)) * zNear; + return Result; + } + + template<typename T> + GLM_FUNC_QUALIFIER mat<4, 4, T, defaultp> tweakedInfinitePerspective(T fovy, T aspect, T zNear) + { + return tweakedInfinitePerspective(fovy, aspect, zNear, epsilon<T>()); + } +}//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 0000000000000000000000000000000000000000..05c37991c5d6e4d1e3c90f469ceffd9cce57e1a6 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/ext/matrix_common.hpp @@ -0,0 +1,36 @@ +/// @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 <glm/ext/matrix_common.hpp> 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_transform extension included") +#endif + +namespace glm +{ + /// @addtogroup ext_matrix_common + /// @{ + + template<length_t C, length_t R, typename T, typename U, qualifier Q> + GLM_FUNC_DECL mat<C, R, T, Q> mix(mat<C, R, T, Q> const& x, mat<C, R, T, Q> const& y, mat<C, R, U, Q> const& a); + + template<length_t C, length_t R, typename T, typename U, qualifier Q> + GLM_FUNC_DECL mat<C, R, T, Q> mix(mat<C, R, T, Q> const& x, mat<C, R, T, Q> const& y, U a); + + /// @} +}//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 0000000000000000000000000000000000000000..9d508485b866c1a64b7d9db67792f50b61357b1f --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/ext/matrix_common.inl @@ -0,0 +1,16 @@ +#include "../matrix.hpp" + +namespace glm +{ + template<length_t C, length_t R, typename T, typename U, qualifier Q> + GLM_FUNC_QUALIFIER mat<C, R, T, Q> mix(mat<C, R, T, Q> const& x, mat<C, R, T, Q> const& y, U a) + { + return mat<C, R, U, Q>(x) * (static_cast<U>(1) - a) + mat<C, R, U, Q>(y) * a; + } + + template<length_t C, length_t R, typename T, typename U, qualifier Q> + GLM_FUNC_QUALIFIER mat<C, R, T, Q> mix(mat<C, R, T, Q> const& x, mat<C, R, T, Q> const& y, mat<C, R, U, Q> const& a) + { + return matrixCompMult(mat<C, R, U, Q>(x), static_cast<U>(1) - a) + matrixCompMult(mat<C, R, U, Q>(y), a); + } +}//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 0000000000000000000000000000000000000000..94dca54b59bd00e36e28a37816525f59c8eb2a56 --- /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 <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 4.1.6 Matrices</a> + typedef mat<2, 2, double, defaultp> dmat2x2; + + /// 2 columns of 2 components matrix of double-precision floating-point numbers. + /// + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 4.1.6 Matrices</a> + 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 0000000000000000000000000000000000000000..9e2c174e43be2dea558bbe45b75c19a4351c12bc --- /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 <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 4.1.6 Matrices</a> + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 4.7.2 Precision Qualifier</a> + 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 <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 4.1.6 Matrices</a> + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 4.7.2 Precision Qualifier</a> + 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 <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 4.1.6 Matrices</a> + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 4.7.2 Precision Qualifier</a> + 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 <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 4.1.6 Matrices</a> + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 4.7.2 Precision Qualifier</a> + 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 <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 4.1.6 Matrices</a> + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 4.7.2 Precision Qualifier</a> + 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 <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 4.1.6 Matrices</a> + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 4.7.2 Precision Qualifier</a> + 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 0000000000000000000000000000000000000000..bfef87a666c1346ef7053f44b8e0d862b86e3af0 --- /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 <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 4.1.6 Matrices</a> + 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 0000000000000000000000000000000000000000..098fb6046e889cf7e2b19039c08ffd9a51bf2fda --- /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 <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 4.1.6 Matrices</a> + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 4.7.2 Precision Qualifier</a> + 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 <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 4.1.6 Matrices</a> + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 4.7.2 Precision Qualifier</a> + 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 <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 4.1.6 Matrices</a> + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 4.7.2 Precision Qualifier</a> + 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 0000000000000000000000000000000000000000..499284bce161de74be5cb0ab7798d45c69d682e2 --- /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 <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 4.1.6 Matrices</a> + 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 0000000000000000000000000000000000000000..9b61ebcee1efbb63b0d95b2fe9e88c804ecb631a --- /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 <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 4.1.6 Matrices</a> + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 4.7.2 Precision Qualifier</a> + 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 <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 4.1.6 Matrices</a> + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 4.7.2 Precision Qualifier</a> + 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 <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 4.1.6 Matrices</a> + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 4.7.2 Precision Qualifier</a> + 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 0000000000000000000000000000000000000000..dd23f36cdbb2530d9305f4e6e037eb2f88ecb544 --- /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 <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 4.1.6 Matrices</a> + 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 0000000000000000000000000000000000000000..068d9e911721623bfb7c5d5ac3ac5591581907e2 --- /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 <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 4.1.6 Matrices</a> + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 4.7.2 Precision Qualifier</a> + 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 <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 4.1.6 Matrices</a> + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 4.7.2 Precision Qualifier</a> + 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 <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 4.1.6 Matrices</a> + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 4.7.2 Precision Qualifier</a> + 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 0000000000000000000000000000000000000000..53572b735626e224c52eb386a794353308574b6a --- /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 <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 4.1.6 Matrices</a> + typedef mat<3, 3, double, defaultp> dmat3x3; + + /// 3 columns of 3 components matrix of double-precision floating-point numbers. + /// + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 4.1.6 Matrices</a> + 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 0000000000000000000000000000000000000000..8691e7808dc95b7f4466ec9b6c829f54f9416edf --- /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 <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 4.1.6 Matrices</a> + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 4.7.2 Precision Qualifier</a> + 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 <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 4.1.6 Matrices</a> + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 4.7.2 Precision Qualifier</a> + 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 <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 4.1.6 Matrices</a> + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 4.7.2 Precision Qualifier</a> + 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 <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 4.1.6 Matrices</a> + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 4.7.2 Precision Qualifier</a> + 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 <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 4.1.6 Matrices</a> + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 4.7.2 Precision Qualifier</a> + 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 <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 4.1.6 Matrices</a> + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 4.7.2 Precision Qualifier</a> + 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 0000000000000000000000000000000000000000..c572d637cd2dce86aa0d8d45c4457498880a95ca --- /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 <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 4.1.6 Matrices</a> + 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 0000000000000000000000000000000000000000..f040217e748ab7b56a8a292b4825c5926716b176 --- /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 <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 4.1.6 Matrices</a> + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 4.7.2 Precision Qualifier</a> + 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 <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 4.1.6 Matrices</a> + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 4.7.2 Precision Qualifier</a> + 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 <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 4.1.6 Matrices</a> + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 4.7.2 Precision Qualifier</a> + 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 0000000000000000000000000000000000000000..9b229f471e8d4904c7135e7a27719820dfe5225b --- /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 <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 4.1.6 Matrices</a> + 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 0000000000000000000000000000000000000000..6ad18ba9e65e108090e8354e5a55a5ac1c5f3b8f --- /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 <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 4.1.6 Matrices</a> + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 4.7.2 Precision Qualifier</a> + 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 <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 4.1.6 Matrices</a> + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 4.7.2 Precision Qualifier</a> + 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 <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 4.1.6 Matrices</a> + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 4.7.2 Precision Qualifier</a> + 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 0000000000000000000000000000000000000000..dca4cf956f9189b7b74cece7fc3f2af9501ae49f --- /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 <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 4.1.6 Matrices</a> + 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 0000000000000000000000000000000000000000..f7371de84942ac21b33e7eb81e97352c6a4ec449 --- /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 <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 4.1.6 Matrices</a> + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 4.7.2 Precision Qualifier</a> + 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 <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 4.1.6 Matrices</a> + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 4.7.2 Precision Qualifier</a> + 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 <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 4.1.6 Matrices</a> + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 4.7.2 Precision Qualifier</a> + 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 0000000000000000000000000000000000000000..81e1bf65cb5c4b071a394b6dc1d9d53e04b21500 --- /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 <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 4.1.6 Matrices</a> + typedef mat<4, 4, double, defaultp> dmat4x4; + + /// 4 columns of 4 components matrix of double-precision floating-point numbers. + /// + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 4.1.6 Matrices</a> + 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 0000000000000000000000000000000000000000..4c36a8486c72988f4d0d1f8a822a69c4e477fa95 --- /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 <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 4.1.6 Matrices</a> + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 4.7.2 Precision Qualifier</a> + 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 <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 4.1.6 Matrices</a> + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 4.7.2 Precision Qualifier</a> + 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 <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 4.1.6 Matrices</a> + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 4.7.2 Precision Qualifier</a> + 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 <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 4.1.6 Matrices</a> + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 4.7.2 Precision Qualifier</a> + 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 <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 4.1.6 Matrices</a> + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 4.7.2 Precision Qualifier</a> + 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 <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 4.1.6 Matrices</a> + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 4.7.2 Precision Qualifier</a> + 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 0000000000000000000000000000000000000000..53df921fe216b575c92239c478301db803416a14 --- /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 <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 4.1.6 Matrices</a> + typedef mat<2, 2, float, defaultp> mat2x2; + + /// 2 columns of 2 components matrix of single-precision floating-point numbers. + /// + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 4.1.6 Matrices</a> + 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 0000000000000000000000000000000000000000..898b6db7140807bc0d30b676724827d623c64da3 --- /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 <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 4.1.6 Matrices</a> + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 4.7.2 Precision Qualifier</a> + 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 <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 4.1.6 Matrices</a> + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 4.7.2 Precision Qualifier</a> + 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 <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 4.1.6 Matrices</a> + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 4.7.2 Precision Qualifier</a> + 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 <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 4.1.6 Matrices</a> + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 4.7.2 Precision Qualifier</a> + 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 <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 4.1.6 Matrices</a> + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 4.7.2 Precision Qualifier</a> + 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 <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 4.1.6 Matrices</a> + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 4.7.2 Precision Qualifier</a> + 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 0000000000000000000000000000000000000000..6f68822dbf1e742431163115f4bafc35b6896606 --- /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 <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 4.1.6 Matrices</a> + 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 0000000000000000000000000000000000000000..50c103245c3a177b958de4df333245d09f4d1e28 --- /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 <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 4.1.6 Matrices</a> + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 4.7.2 Precision Qualifier</a> + 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 <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 4.1.6 Matrices</a> + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 4.7.2 Precision Qualifier</a> + 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 <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 4.1.6 Matrices</a> + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 4.7.2 Precision Qualifier</a> + 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 0000000000000000000000000000000000000000..30f30de3cbd4c12cc642a6ac211e40876bdca525 --- /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 <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 4.1.6 Matrices</a> + 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 0000000000000000000000000000000000000000..079d6382863172411ae6a82837bb34ea6e2096c9 --- /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 <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 4.1.6 Matrices</a> + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 4.7.2 Precision Qualifier</a> + 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 <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 4.1.6 Matrices</a> + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 4.7.2 Precision Qualifier</a> + 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 <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 4.1.6 Matrices</a> + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 4.7.2 Precision Qualifier</a> + 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 0000000000000000000000000000000000000000..d39dd2fedd670f353f4ad9b5f9246475e2e69686 --- /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 + /// @{ + + /// 3 columns of 2 components matrix of single-precision floating-point numbers. + /// + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 4.1.6 Matrices</a> + 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 0000000000000000000000000000000000000000..8572c2a1b20e5a1e47bedd72ec6d0009fd15d9bf --- /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 <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 4.1.6 Matrices</a> + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 4.7.2 Precision Qualifier</a> + 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 <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 4.1.6 Matrices</a> + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 4.7.2 Precision Qualifier</a> + 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 <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 4.1.6 Matrices</a> + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 4.7.2 Precision Qualifier</a> + 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 0000000000000000000000000000000000000000..177d809ff9f4c157beda61885ad3994fe3e3d141 --- /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 <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 4.1.6 Matrices</a> + typedef mat<3, 3, float, defaultp> mat3x3; + + /// 3 columns of 3 components matrix of single-precision floating-point numbers. + /// + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 4.1.6 Matrices</a> + 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 0000000000000000000000000000000000000000..8a900c16420006f110c9bfeaf186156d9fc135c3 --- /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 <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 4.1.6 Matrices</a> + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 4.7.2 Precision Qualifier</a> + 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 <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 4.1.6 Matrices</a> + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 4.7.2 Precision Qualifier</a> + 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 <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 4.1.6 Matrices</a> + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 4.7.2 Precision Qualifier</a> + 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 <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 4.1.6 Matrices</a> + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 4.7.2 Precision Qualifier</a> + 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 <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 4.1.6 Matrices</a> + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 4.7.2 Precision Qualifier</a> + 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 <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 4.1.6 Matrices</a> + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 4.7.2 Precision Qualifier</a> + 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 0000000000000000000000000000000000000000..64b8459dcdd2d489a7a8fc93c1282f7cf1ec2673 --- /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 <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 4.1.6 Matrices</a> + 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 0000000000000000000000000000000000000000..bc36bf13a1e957ab625e3162312f311a9d5a287e --- /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 <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 4.1.6 Matrices</a> + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 4.7.2 Precision Qualifier</a> + 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 <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 4.1.6 Matrices</a> + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 4.7.2 Precision Qualifier</a> + 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 <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 4.1.6 Matrices</a> + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 4.7.2 Precision Qualifier</a> + 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 0000000000000000000000000000000000000000..1ed5227bf58000e7c2d822014b29b49d685f6972 --- /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 <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 4.1.6 Matrices</a> + 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 0000000000000000000000000000000000000000..88fd069630a802ab8c7d80791ae91f98969098a4 --- /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 <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 4.1.6 Matrices</a> + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 4.7.2 Precision Qualifier</a> + 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 <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 4.1.6 Matrices</a> + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 4.7.2 Precision Qualifier</a> + 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 <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 4.1.6 Matrices</a> + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 4.7.2 Precision Qualifier</a> + 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 0000000000000000000000000000000000000000..5dbe7657043f704017228a0ebc03ed5a7a0c9e40 --- /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 <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 4.1.6 Matrices</a> + 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 0000000000000000000000000000000000000000..846ed4fc8d9ccb0de18374fa039cffb823d3586a --- /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 <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 4.1.6 Matrices</a> + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 4.7.2 Precision Qualifier</a> + 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 <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 4.1.6 Matrices</a> + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 4.7.2 Precision Qualifier</a> + 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 <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 4.1.6 Matrices</a> + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 4.7.2 Precision Qualifier</a> + 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 0000000000000000000000000000000000000000..5ba111de048171ae0f9849a2c5e375f9351a8bbc --- /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 <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 4.1.6 Matrices</a> + typedef mat<4, 4, float, defaultp> mat4x4; + + /// 4 columns of 4 components matrix of single-precision floating-point numbers. + /// + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 4.1.6 Matrices</a> + 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 0000000000000000000000000000000000000000..597149bcf90fcd34e1b22e970fbd01cc45742fa5 --- /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 <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 4.1.6 Matrices</a> + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 4.7.2 Precision Qualifier</a> + 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 <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 4.1.6 Matrices</a> + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 4.7.2 Precision Qualifier</a> + 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 <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 4.1.6 Matrices</a> + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 4.7.2 Precision Qualifier</a> + 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 <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 4.1.6 Matrices</a> + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 4.7.2 Precision Qualifier</a> + 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 <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 4.1.6 Matrices</a> + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 4.7.2 Precision Qualifier</a> + 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 <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 4.1.6 Matrices</a> + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 4.7.2 Precision Qualifier</a> + 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 0000000000000000000000000000000000000000..c6aa0686ae78e5778c087c665ee6ab44384e1aa2 --- /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 <glm/ext/matrix_int2x2.hpp> 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 0000000000000000000000000000000000000000..70c0c2106acdb5bdaf14d74364cb0a8040e3ca8f --- /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 <glm/ext/matrix_int2x2_sized.hpp> 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 0000000000000000000000000000000000000000..aee415caa6e1dd9658c12e91c0be07dc858baf70 --- /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 <glm/ext/matrix_int2x3.hpp> 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 0000000000000000000000000000000000000000..b5526fe55143cf872978a4c2c13a2bda2b2bcd27 --- /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 <glm/ext/matrix_int2x3_sized.hpp> 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 0000000000000000000000000000000000000000..4f36331d66023619a6f296644d243ad61f5411c0 --- /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 <glm/ext/matrix_int2x4.hpp> 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 0000000000000000000000000000000000000000..a66a5e72688139b620784c4908c8db9cf7da5024 --- /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 <glm/ext/matrix_int2x4_sized.hpp> 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 0000000000000000000000000000000000000000..3bd563b7de9c7b5487868ae21c4cc885219f4130 --- /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 <glm/ext/matrix_int3x2.hpp> 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 0000000000000000000000000000000000000000..7e34c5240f401cae66d5d6536862bc9bc84d8dce --- /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 <glm/ext/matrix_int3x2_sized.hpp> 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 0000000000000000000000000000000000000000..287488da0343cf12207cea1dbba0bd8727342ef2 --- /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 <glm/ext/matrix_int3x3.hpp> 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 0000000000000000000000000000000000000000..577e305aa7f74ab3418f92e728e740c6a5c437f3 --- /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 <glm/ext/matrix_int3x3_sized.hpp> 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 0000000000000000000000000000000000000000..08e534d9c4d5b7fbd8c815d0bc4639c7a7f7ae5b --- /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 <glm/ext/matrix_int3x4.hpp> 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 0000000000000000000000000000000000000000..692c48c439e7bfcd1016eb8f871833eda432913b --- /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 <glm/ext/matrix_int3x4_sized.hpp> 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 0000000000000000000000000000000000000000..f756ef2804c81278d2c78aea85ad0e0fe3db468f --- /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 <glm/ext/matrix_int4x2.hpp> 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 0000000000000000000000000000000000000000..63a99d604dc5c02a132b9e61ce120c7dfd7ccd90 --- /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 <glm/ext/matrix_int4x2_sized.hpp> 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 0000000000000000000000000000000000000000..d5d97a7a37cf976fbff71ee29dc6953cdd65db90 --- /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 <glm/ext/matrix_int4x3.hpp> 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 0000000000000000000000000000000000000000..55078fadc60f8c98be996a74ee62fc407d7fa444 --- /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 <glm/ext/matrix_int4x3_sized.hpp> 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 0000000000000000000000000000000000000000..e17cff17f9fb2fb444badc4ca08b9623acaa559c --- /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 <glm/ext/matrix_int4x4.hpp> 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 0000000000000000000000000000000000000000..4a11203eb25b1fd7adf3311c770aaffd1527e16b --- /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 <glm/ext/matrix_int4x4_sized.hpp> 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_projection.hpp b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/ext/matrix_projection.hpp new file mode 100644 index 0000000000000000000000000000000000000000..51fd01bd8ee7fb28c992579c31c6200bfff98cf0 --- /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 <glm/ext/matrix_projection.hpp> 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 <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl2.1/xhtml/gluProject.xml">gluProject man page</a> + template<typename T, typename U, qualifier Q> + 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 <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl2.1/xhtml/gluProject.xml">gluProject man page</a> + template<typename T, typename U, qualifier Q> + 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 <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl2.1/xhtml/gluProject.xml">gluProject man page</a> + template<typename T, typename U, qualifier Q> + 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 <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl2.1/xhtml/gluUnProject.xml">gluUnProject man page</a> + template<typename T, typename U, qualifier Q> + 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 <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl2.1/xhtml/gluUnProject.xml">gluUnProject man page</a> + template<typename T, typename U, qualifier Q> + 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 <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl2.1/xhtml/gluUnProject.xml">gluUnProject man page</a> + template<typename T, typename U, qualifier Q> + 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 <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl2.1/xhtml/gluPickMatrix.xml">gluPickMatrix man page</a> + template<typename T, qualifier Q, typename U> + 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 0000000000000000000000000000000000000000..2f2c196aac5f2018c70ac579cb31c558e9d20139 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/ext/matrix_projection.inl @@ -0,0 +1,106 @@ +namespace glm +{ + template<typename T, typename U, qualifier Q> + 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<T>(1)); + tmp = model * tmp; + tmp = proj * tmp; + + tmp /= tmp.w; + tmp.x = tmp.x * static_cast<T>(0.5) + static_cast<T>(0.5); + tmp.y = tmp.y * static_cast<T>(0.5) + static_cast<T>(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<typename T, typename U, qualifier Q> + 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<T>(1)); + tmp = model * tmp; + tmp = proj * tmp; + + tmp /= tmp.w; + tmp = tmp * static_cast<T>(0.5) + static_cast<T>(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<typename T, typename U, qualifier Q> + 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<typename T, typename U, qualifier Q> + 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<T>(2) - static_cast<T>(1); + tmp.y = tmp.y * static_cast<T>(2) - static_cast<T>(1); + + vec<4, T, Q> obj = Inverse * tmp; + obj /= obj.w; + + return vec<3, T, Q>(obj); + } + + template<typename T, typename U, qualifier Q> + 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<T>(2) - static_cast<T>(1); + + vec<4, T, Q> obj = Inverse * tmp; + obj /= obj.w; + + return vec<3, T, Q>(obj); + } + + template<typename T, typename U, qualifier Q> + 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<typename T, qualifier Q, typename U> + 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<T>(0) && delta.y > static_cast<T>(0)); + mat<4, 4, T, Q> Result(static_cast<T>(1)); + + if(!(delta.x > static_cast<T>(0) && delta.y > static_cast<T>(0))) + return Result; // Error + + vec<3, T, Q> Temp( + (static_cast<T>(viewport[2]) - static_cast<T>(2) * (center.x - static_cast<T>(viewport[0]))) / delta.x, + (static_cast<T>(viewport[3]) - static_cast<T>(2) * (center.y - static_cast<T>(viewport[1]))) / delta.y, + static_cast<T>(0)); + + // Translate and scale the picked region to the entire window + Result = translate(Result, Temp); + return scale(Result, vec<3, T, Q>(static_cast<T>(viewport[2]) / delta.x, static_cast<T>(viewport[3]) / delta.y, static_cast<T>(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 0000000000000000000000000000000000000000..20023ad89a0ce6fa19b1294212ab78d0dff479b3 --- /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 <glm/ext/matrix_relational.hpp> 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<length_t C, length_t R, typename T, qualifier Q> + GLM_FUNC_DECL GLM_CONSTEXPR vec<C, bool, Q> equal(mat<C, R, T, Q> const& x, mat<C, R, T, Q> 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<length_t C, length_t R, typename T, qualifier Q> + GLM_FUNC_DECL GLM_CONSTEXPR vec<C, bool, Q> notEqual(mat<C, R, T, Q> const& x, mat<C, R, T, Q> 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<length_t C, length_t R, typename T, qualifier Q> + GLM_FUNC_DECL GLM_CONSTEXPR vec<C, bool, Q> equal(mat<C, R, T, Q> const& x, mat<C, R, T, Q> 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<length_t C, length_t R, typename T, qualifier Q> + GLM_FUNC_DECL GLM_CONSTEXPR vec<C, bool, Q> equal(mat<C, R, T, Q> const& x, mat<C, R, T, Q> const& y, vec<C, T, Q> 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<length_t C, length_t R, typename T, qualifier Q> + GLM_FUNC_DECL GLM_CONSTEXPR vec<C, bool, Q> notEqual(mat<C, R, T, Q> const& x, mat<C, R, T, Q> 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<length_t C, length_t R, typename T, qualifier Q> + GLM_FUNC_DECL GLM_CONSTEXPR vec<C, bool, Q> notEqual(mat<C, R, T, Q> const& x, mat<C, R, T, Q> const& y, vec<C, T, Q> 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<length_t C, length_t R, typename T, qualifier Q> + GLM_FUNC_DECL GLM_CONSTEXPR vec<C, bool, Q> equal(mat<C, R, T, Q> const& x, mat<C, R, T, Q> 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<length_t C, length_t R, typename T, qualifier Q> + GLM_FUNC_DECL GLM_CONSTEXPR vec<C, bool, Q> equal(mat<C, R, T, Q> const& x, mat<C, R, T, Q> const& y, vec<C, int, Q> 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<length_t C, length_t R, typename T, qualifier Q> + GLM_FUNC_DECL GLM_CONSTEXPR vec<C, bool, Q> notEqual(mat<C, R, T, Q> const& x, mat<C, R, T, Q> 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<length_t C, length_t R, typename T, qualifier Q> + GLM_FUNC_DECL GLM_CONSTEXPR vec<C, bool, Q> notEqual(mat<C, R, T, Q> const& x, mat<C, R, T, Q> const& y, vec<C, int, Q> 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 0000000000000000000000000000000000000000..b2b875309decbe275ca68432f4b4992ca55a6409 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/ext/matrix_relational.inl @@ -0,0 +1,82 @@ +/// @ref ext_vector_relational +/// @file glm/ext/vector_relational.inl + +// Dependency: +#include "../ext/vector_relational.hpp" +#include "../common.hpp" + +namespace glm +{ + template<length_t C, length_t R, typename T, qualifier Q> + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<C, bool, Q> equal(mat<C, R, T, Q> const& a, mat<C, R, T, Q> const& b) + { + return equal(a, b, static_cast<T>(0)); + } + + template<length_t C, length_t R, typename T, qualifier Q> + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<C, bool, Q> equal(mat<C, R, T, Q> const& a, mat<C, R, T, Q> const& b, T Epsilon) + { + return equal(a, b, vec<C, T, Q>(Epsilon)); + } + + template<length_t C, length_t R, typename T, qualifier Q> + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<C, bool, Q> equal(mat<C, R, T, Q> const& a, mat<C, R, T, Q> const& b, vec<C, T, Q> const& Epsilon) + { + vec<C, bool, Q> Result(true); + for(length_t i = 0; i < C; ++i) + Result[i] = all(equal(a[i], b[i], Epsilon[i])); + return Result; + } + + template<length_t C, length_t R, typename T, qualifier Q> + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<C, bool, Q> notEqual(mat<C, R, T, Q> const& x, mat<C, R, T, Q> const& y) + { + return notEqual(x, y, static_cast<T>(0)); + } + + template<length_t C, length_t R, typename T, qualifier Q> + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<C, bool, Q> notEqual(mat<C, R, T, Q> const& x, mat<C, R, T, Q> const& y, T Epsilon) + { + return notEqual(x, y, vec<C, T, Q>(Epsilon)); + } + + template<length_t C, length_t R, typename T, qualifier Q> + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<C, bool, Q> notEqual(mat<C, R, T, Q> const& a, mat<C, R, T, Q> const& b, vec<C, T, Q> const& Epsilon) + { + vec<C, bool, Q> Result(true); + for(length_t i = 0; i < C; ++i) + Result[i] = any(notEqual(a[i], b[i], Epsilon[i])); + return Result; + } + + template<length_t C, length_t R, typename T, qualifier Q> + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<C, bool, Q> equal(mat<C, R, T, Q> const& a, mat<C, R, T, Q> const& b, int MaxULPs) + { + return equal(a, b, vec<C, int, Q>(MaxULPs)); + } + + template<length_t C, length_t R, typename T, qualifier Q> + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<C, bool, Q> equal(mat<C, R, T, Q> const& a, mat<C, R, T, Q> const& b, vec<C, int, Q> const& MaxULPs) + { + vec<C, bool, Q> Result(true); + for(length_t i = 0; i < C; ++i) + Result[i] = all(equal(a[i], b[i], MaxULPs[i])); + return Result; + } + + template<length_t C, length_t R, typename T, qualifier Q> + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<C, bool, Q> notEqual(mat<C, R, T, Q> const& x, mat<C, R, T, Q> const& y, int MaxULPs) + { + return notEqual(x, y, vec<C, int, Q>(MaxULPs)); + } + + template<length_t C, length_t R, typename T, qualifier Q> + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<C, bool, Q> notEqual(mat<C, R, T, Q> const& a, mat<C, R, T, Q> const& b, vec<C, int, Q> const& MaxULPs) + { + vec<C, bool, Q> 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 0000000000000000000000000000000000000000..cbd187efd85015605dc7d33e4f919b99070ade44 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/ext/matrix_transform.hpp @@ -0,0 +1,144 @@ +/// @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 <glm/ext/matrix_transform.hpp> 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<typename genType> + 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 <glm/glm.hpp> + /// #include <glm/gtc/matrix_transform.hpp> + /// ... + /// 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 <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl2.1/xhtml/glTranslate.xml">glTranslate man page</a> + template<typename T, qualifier Q> + GLM_FUNC_DECL 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 <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl2.1/xhtml/glRotate.xml">glRotate man page</a> + template<typename T, qualifier Q> + 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 <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl2.1/xhtml/glScale.xml">glScale man page</a> + template<typename T, qualifier Q> + GLM_FUNC_DECL mat<4, 4, T, Q> scale( + mat<4, 4, T, Q> const& m, vec<3, T, Q> const& v); + + /// 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<typename T, qualifier Q> + 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<typename T, qualifier Q> + 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 <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl2.1/xhtml/gluLookAt.xml">gluLookAt man page</a> + template<typename T, qualifier Q> + 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 0000000000000000000000000000000000000000..a415157e0d9ef2f1d709cbbe6a3d10c1778b8a5c --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/ext/matrix_transform.inl @@ -0,0 +1,152 @@ +namespace glm +{ + template<typename genType> + GLM_FUNC_QUALIFIER GLM_CONSTEXPR genType identity() + { + return detail::init_gentype<genType, detail::genTypeTrait<genType>::GENTYPE>::identity(); + } + + template<typename T, qualifier Q> + GLM_FUNC_QUALIFIER 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<typename T, qualifier Q> + 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<typename T, qualifier Q> + 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<T>(1) - c) * axis.x * axis.x; + Result[0][1] = (static_cast<T>(1) - c) * axis.x * axis.y + s * axis.z; + Result[0][2] = (static_cast<T>(1) - c) * axis.x * axis.z - s * axis.y; + Result[0][3] = static_cast<T>(0); + + Result[1][0] = (static_cast<T>(1) - c) * axis.y * axis.x - s * axis.z; + Result[1][1] = c + (static_cast<T>(1) - c) * axis.y * axis.y; + Result[1][2] = (static_cast<T>(1) - c) * axis.y * axis.z + s * axis.x; + Result[1][3] = static_cast<T>(0); + + Result[2][0] = (static_cast<T>(1) - c) * axis.z * axis.x + s * axis.y; + Result[2][1] = (static_cast<T>(1) - c) * axis.z * axis.y - s * axis.x; + Result[2][2] = c + (static_cast<T>(1) - c) * axis.z * axis.z; + Result[2][3] = static_cast<T>(0); + + Result[3] = vec<4, T, Q>(0, 0, 0, 1); + return m * Result; + } + + template<typename T, qualifier Q> + 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<typename T, qualifier Q> + 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<typename T, qualifier Q> + 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<typename T, qualifier Q> + 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<typename T, qualifier Q> + 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) + { + GLM_IF_CONSTEXPR(GLM_CONFIG_CLIP_CONTROL & GLM_CLIP_CONTROL_LH_BIT) + return lookAtLH(eye, center, up); + else + return lookAtRH(eye, center, up); + } +}//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 0000000000000000000000000000000000000000..034771ae52256fd2d94ce0b7a3dd6eaf4b23a386 --- /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 <glm/ext/matrix_uint2x2.hpp> 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 0000000000000000000000000000000000000000..4555324d2b52e140cc5392487ef123d2f6408e58 --- /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 <glm/ext/matrix_uint2x2_sized.hpp> 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 0000000000000000000000000000000000000000..7de62f6ff5c9481aa62d9902043501f38417de34 --- /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_int2x3 GLM_EXT_matrix_uint2x3 +/// @ingroup ext +/// +/// Include <glm/ext/matrix_uint2x3.hpp> 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 0000000000000000000000000000000000000000..db7939c94658de2277b2af422a1ba0642228588c --- /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 <glm/ext/matrix_uint2x3_sized.hpp> 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 0000000000000000000000000000000000000000..0f993509c23b271d2230ef8d7fbd2c007ac1980b --- /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 <glm/ext/matrix_uint2x4.hpp> 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 0000000000000000000000000000000000000000..5cb8e546fe467ff6178dd153adce9872c8f0c070 --- /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/matrixu_uint2x4_sized.hpp +/// +/// @see core (dependence) +/// +/// @defgroup ext_matrix_uint2x4_sized GLM_EXT_matrix_uint2x4_sized +/// @ingroup ext +/// +/// Include <glm/ext/matrix_uint2x4_sized.hpp> 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 0000000000000000000000000000000000000000..47f48737cce32cda8337ca967220651c2aab4cd3 --- /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_int3x2 GLM_EXT_matrix_uint3x2 +/// @ingroup ext +/// +/// Include <glm/ext/matrix_uint3x2.hpp> 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 0000000000000000000000000000000000000000..c81af8f968d6ee45a13295915a8f6b220f77b9cf --- /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 <glm/ext/matrix_uint3x2_sized.hpp> 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 0000000000000000000000000000000000000000..1004c0d2d541a9fd796b28a7b9b93054776a4ab1 --- /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 <glm/ext/matrix_uint3x3.hpp> 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 0000000000000000000000000000000000000000..41a8be748660fdf568608baa724bea58c6fe2814 --- /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 <glm/ext/matrix_uint3x3_sized.hpp> 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 0000000000000000000000000000000000000000..c6dd78c4a0535b21d30aec53ce1e93ec5b05496a --- /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 <glm/ext/matrix_uint3x4.hpp> 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 0000000000000000000000000000000000000000..2ce28ad816fc03f1ba82c80860f2c95d57b83d3c --- /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 <glm/ext/matrix_uint3x4_sized.hpp> 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 0000000000000000000000000000000000000000..0446f5745bdeb7b6999ab7d8c5461b1cc739a61a --- /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 <glm/ext/matrix_uint4x2.hpp> 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 0000000000000000000000000000000000000000..57a66bf9b8b0c52b7a7564b7ce47660c08cdfc57 --- /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 <glm/ext/matrix_uint4x2_sized.hpp> 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 0000000000000000000000000000000000000000..54c24e4e50b170328e881753c9d8537ca9630605 --- /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 <glm/ext/matrix_uint4x3.hpp> 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 0000000000000000000000000000000000000000..2e61124d63b47e6361e47b38249ca48a9070f266 --- /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 <glm/ext/matrix_uint4x3_sized.hpp> 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 0000000000000000000000000000000000000000..5cc84553d9366c8a621a9a67a3b28d15ba5e70de --- /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 <glm/ext/matrix_uint4x4.hpp> 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 0000000000000000000000000000000000000000..bb10bd2b77d1212949e084fa0aae5abc9647c89c --- /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 <glm/ext/matrix_uint4x4_sized.hpp> 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 0000000000000000000000000000000000000000..f519d5591852ece21c1dc90bfdd3c26164fad030 --- /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 <glm/ext/quaternion_common.hpp> 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 <limits> + +#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<T, Q> const& x, qua<T, Q> const& y, T const& a) + template<typename T, qualifier Q> + GLM_FUNC_DECL qua<T, Q> mix(qua<T, Q> const& x, qua<T, Q> 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<typename T, qualifier Q> + GLM_FUNC_DECL qua<T, Q> lerp(qua<T, Q> const& x, qua<T, Q> 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<typename T, qualifier Q> + GLM_FUNC_DECL qua<T, Q> slerp(qua<T, Q> const& x, qua<T, Q> 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<typename T, typename S, qualifier Q> + GLM_FUNC_DECL qua<T, Q> slerp(qua<T, Q> const& x, qua<T, Q> 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<typename T, qualifier Q> + GLM_FUNC_DECL qua<T, Q> conjugate(qua<T, Q> const& q); + + /// Returns the q inverse. + /// + /// @tparam T A floating-point scalar type + /// @tparam Q A value from qualifier enum + template<typename T, qualifier Q> + GLM_FUNC_DECL qua<T, Q> inverse(qua<T, Q> 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<typename T, qualifier Q> + GLM_FUNC_DECL vec<4, bool, Q> isnan(qua<T, Q> 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<typename T, qualifier Q> + GLM_FUNC_DECL vec<4, bool, Q> isinf(qua<T, Q> 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 0000000000000000000000000000000000000000..0e4a3bb2a3ccbdd1fc8faeb809a07fe35ad4c1a3 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/ext/quaternion_common.inl @@ -0,0 +1,144 @@ +namespace glm +{ + template<typename T, qualifier Q> + GLM_FUNC_QUALIFIER qua<T, Q> mix(qua<T, Q> const& x, qua<T, Q> const& y, T a) + { + GLM_STATIC_ASSERT(std::numeric_limits<T>::is_iec559, "'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<T>(1) - epsilon<T>()) + { + // Linear interpolation + return qua<T, Q>( + 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<T>(1) - a) * angle) * x + sin(a * angle) * y) / sin(angle); + } + } + + template<typename T, qualifier Q> + GLM_FUNC_QUALIFIER qua<T, Q> lerp(qua<T, Q> const& x, qua<T, Q> const& y, T a) + { + GLM_STATIC_ASSERT(std::numeric_limits<T>::is_iec559, "'lerp' only accept floating-point inputs"); + + // Lerp is only defined in [0, 1] + assert(a >= static_cast<T>(0)); + assert(a <= static_cast<T>(1)); + + return x * (static_cast<T>(1) - a) + (y * a); + } + + template<typename T, qualifier Q> + GLM_FUNC_QUALIFIER qua<T, Q> slerp(qua<T, Q> const& x, qua<T, Q> const& y, T a) + { + GLM_STATIC_ASSERT(std::numeric_limits<T>::is_iec559, "'slerp' only accept floating-point inputs"); + + qua<T, Q> 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<T>(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<T>(1) - epsilon<T>()) + { + // Linear interpolation + return qua<T, Q>( + 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<T>(1) - a) * angle) * x + sin(a * angle) * z) / sin(angle); + } + } + + template<typename T, typename S, qualifier Q> + GLM_FUNC_QUALIFIER qua<T, Q> slerp(qua<T, Q> const& x, qua<T, Q> const& y, T a, S k) + { + GLM_STATIC_ASSERT(std::numeric_limits<T>::is_iec559, "'slerp' only accept floating-point inputs"); + GLM_STATIC_ASSERT(std::numeric_limits<S>::is_integer, "'slerp' only accept integer for spin count"); + + qua<T, Q> 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<T>(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<T>(1) - epsilon<T>()) + { + // Linear interpolation + return qua<T, Q>( + 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 + k * glm::pi<T>(); + return (sin(angle - a * phi)* x + sin(a * phi) * z) / sin(angle); + } + } + + template<typename T, qualifier Q> + GLM_FUNC_QUALIFIER qua<T, Q> conjugate(qua<T, Q> const& q) + { + return qua<T, Q>(q.w, -q.x, -q.y, -q.z); + } + + template<typename T, qualifier Q> + GLM_FUNC_QUALIFIER qua<T, Q> inverse(qua<T, Q> const& q) + { + return conjugate(q) / dot(q, q); + } + + template<typename T, qualifier Q> + GLM_FUNC_QUALIFIER vec<4, bool, Q> isnan(qua<T, Q> const& q) + { + GLM_STATIC_ASSERT(std::numeric_limits<T>::is_iec559, "'isnan' only accept floating-point inputs"); + + return vec<4, bool, Q>(isnan(q.x), isnan(q.y), isnan(q.z), isnan(q.w)); + } + + template<typename T, qualifier Q> + GLM_FUNC_QUALIFIER vec<4, bool, Q> isinf(qua<T, Q> const& q) + { + GLM_STATIC_ASSERT(std::numeric_limits<T>::is_iec559, "'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 0000000000000000000000000000000000000000..ddfc8a44f6a32774ff092201bc9ee2fd2a11b80b --- /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<qualifier Q> + struct compute_dot<qua<float, Q>, float, true> + { + static GLM_FUNC_QUALIFIER float call(qua<float, Q> const& x, qua<float, Q> 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 0000000000000000000000000000000000000000..63b24de4d52afb415cdaf8a8077cbb95e5a01d90 --- /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 <glm/ext/quaternion_double.hpp> 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<double, defaultp> 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 0000000000000000000000000000000000000000..8aa24a17752dfd04aa05bc80ff179c0b02d58fbb --- /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 <glm/ext/quaternion_double_precision.hpp> 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<double, lowp> 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<double, mediump> 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<double, highp> 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 0000000000000000000000000000000000000000..affe2979aad5bcc7a475d8293bab6421ae0c7bba --- /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 <glm/ext/quaternion_exponential.hpp> 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<typename T, qualifier Q> + GLM_FUNC_DECL qua<T, Q> exp(qua<T, Q> const& q); + + /// Returns a logarithm of a quaternion + /// + /// @tparam T A floating-point scalar type + /// @tparam Q A value from qualifier enum + template<typename T, qualifier Q> + GLM_FUNC_DECL qua<T, Q> log(qua<T, Q> const& q); + + /// Returns a quaternion raised to a power. + /// + /// @tparam T A floating-point scalar type + /// @tparam Q A value from qualifier enum + template<typename T, qualifier Q> + GLM_FUNC_DECL qua<T, Q> pow(qua<T, Q> 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<typename T, qualifier Q> + GLM_FUNC_DECL qua<T, Q> sqrt(qua<T, Q> 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 0000000000000000000000000000000000000000..8456c00aff6a05d7a8d3357fa24440f5bbe1671a --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/ext/quaternion_exponential.inl @@ -0,0 +1,85 @@ +#include "scalar_constants.hpp" + +namespace glm +{ + template<typename T, qualifier Q> + GLM_FUNC_QUALIFIER qua<T, Q> exp(qua<T, Q> const& q) + { + vec<3, T, Q> u(q.x, q.y, q.z); + T const Angle = glm::length(u); + if (Angle < epsilon<T>()) + return qua<T, Q>(); + + vec<3, T, Q> const v(u / Angle); + return qua<T, Q>(cos(Angle), sin(Angle) * v); + } + + template<typename T, qualifier Q> + GLM_FUNC_QUALIFIER qua<T, Q> log(qua<T, Q> const& q) + { + vec<3, T, Q> u(q.x, q.y, q.z); + T Vec3Len = length(u); + + if (Vec3Len < epsilon<T>()) + { + if(q.w > static_cast<T>(0)) + return qua<T, Q>(log(q.w), static_cast<T>(0), static_cast<T>(0), static_cast<T>(0)); + else if(q.w < static_cast<T>(0)) + return qua<T, Q>(log(-q.w), pi<T>(), static_cast<T>(0), static_cast<T>(0)); + else + return qua<T, Q>(std::numeric_limits<T>::infinity(), std::numeric_limits<T>::infinity(), std::numeric_limits<T>::infinity(), std::numeric_limits<T>::infinity()); + } + else + { + T t = atan(Vec3Len, T(q.w)) / Vec3Len; + T QuatLen2 = Vec3Len * Vec3Len + q.w * q.w; + return qua<T, Q>(static_cast<T>(0.5) * log(QuatLen2), t * q.x, t * q.y, t * q.z); + } + } + + template<typename T, qualifier Q> + GLM_FUNC_QUALIFIER qua<T, Q> pow(qua<T, Q> 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<T>() && y < epsilon<T>()) + return qua<T, Q>(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<T>()) + { + //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; + if (glm::abs(VectorMagnitude - static_cast<T>(0)) < glm::epsilon<T>()) { + //Equivalent to raising a real number to a power + return qua<T, Q>(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<T>(1)); + return qua<T, Q>(cos(NewAngle) * magnitude * Mag, x.x * Div * Mag, x.y * Div * Mag, x.z * Div * Mag); + } + + template<typename T, qualifier Q> + GLM_FUNC_QUALIFIER qua<T, Q> sqrt(qua<T, Q> const& x) + { + return pow(x, static_cast<T>(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 0000000000000000000000000000000000000000..ca42a60597f43d241f7e6a82bf6d0b98c2161621 --- /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 <glm/ext/quaternion_float.hpp> 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<float, defaultp> 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 0000000000000000000000000000000000000000..f9e4f5c21d9075fbd6cf3d684774a62a39c0d15b --- /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 <glm/ext/quaternion_float_precision.hpp> 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<float, lowp> lowp_quat; + + /// Quaternion of single-precision floating-point numbers using high precision arithmetic in term of ULPs. + typedef qua<float, mediump> mediump_quat; + + /// Quaternion of single-precision floating-point numbers using high precision arithmetic in term of ULPs. + typedef qua<float, highp> 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 0000000000000000000000000000000000000000..6d98bbe93fc6b0ea0f2e082a51793379682b7eb2 --- /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 <glm/ext/quaternion_geometric.hpp> to use the features of this extension. +/// +/// @see core_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<typename T, qualifier Q> + GLM_FUNC_DECL T length(qua<T, Q> const& q); + + /// Returns the normalized quaternion. + /// + /// @tparam T Floating-point scalar types + /// @tparam Q Value from qualifier enum + /// + /// @see ext_quaternion_geometric + template<typename T, qualifier Q> + GLM_FUNC_DECL qua<T, Q> normalize(qua<T, Q> 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<typename T, qualifier Q> + GLM_FUNC_DECL T dot(qua<T, Q> const& x, qua<T, Q> const& y); + + /// Compute a cross product. + /// + /// @tparam T Floating-point scalar types + /// @tparam Q Value from qualifier enum + /// + /// @see ext_quaternion_geometric + template<typename T, qualifier Q> + GLM_FUNC_QUALIFIER qua<T, Q> cross(qua<T, Q> const& q1, qua<T, Q> 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 0000000000000000000000000000000000000000..e155ac5218075dfc37aa0720ace9b0bce901c071 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/ext/quaternion_geometric.inl @@ -0,0 +1,36 @@ +namespace glm +{ + template<typename T, qualifier Q> + GLM_FUNC_QUALIFIER T dot(qua<T, Q> const& x, qua<T, Q> const& y) + { + GLM_STATIC_ASSERT(std::numeric_limits<T>::is_iec559, "'dot' accepts only floating-point inputs"); + return detail::compute_dot<qua<T, Q>, T, detail::is_aligned<Q>::value>::call(x, y); + } + + template<typename T, qualifier Q> + GLM_FUNC_QUALIFIER T length(qua<T, Q> const& q) + { + return glm::sqrt(dot(q, q)); + } + + template<typename T, qualifier Q> + GLM_FUNC_QUALIFIER qua<T, Q> normalize(qua<T, Q> const& q) + { + T len = length(q); + if(len <= static_cast<T>(0)) // Problem + return qua<T, Q>(static_cast<T>(1), static_cast<T>(0), static_cast<T>(0), static_cast<T>(0)); + T oneOverLen = static_cast<T>(1) / len; + return qua<T, Q>(q.w * oneOverLen, q.x * oneOverLen, q.y * oneOverLen, q.z * oneOverLen); + } + + template<typename T, qualifier Q> + GLM_FUNC_QUALIFIER qua<T, Q> cross(qua<T, Q> const& q1, qua<T, Q> const& q2) + { + return qua<T, Q>( + 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 0000000000000000000000000000000000000000..7aa121da0a1570460ecf379cf3d4b3ae7c9941c3 --- /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 <glm/ext/quaternion_relational.hpp> 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<typename T, qualifier Q> + GLM_FUNC_DECL vec<4, bool, Q> equal(qua<T, Q> const& x, qua<T, Q> const& y); + + /// Returns the component-wise comparison of |x - y| < epsilon. + /// + /// @tparam T Floating-point scalar types + /// @tparam Q Value from qualifier enum + template<typename T, qualifier Q> + GLM_FUNC_DECL vec<4, bool, Q> equal(qua<T, Q> const& x, qua<T, Q> 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<typename T, qualifier Q> + GLM_FUNC_DECL vec<4, bool, Q> notEqual(qua<T, Q> const& x, qua<T, Q> const& y); + + /// Returns the component-wise comparison of |x - y| >= epsilon. + /// + /// @tparam T Floating-point scalar types + /// @tparam Q Value from qualifier enum + template<typename T, qualifier Q> + GLM_FUNC_DECL vec<4, bool, Q> notEqual(qua<T, Q> const& x, qua<T, Q> 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 0000000000000000000000000000000000000000..b1713e95c6c5b9dffb8f49aeeb659d7e82a7dbc6 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/ext/quaternion_relational.inl @@ -0,0 +1,35 @@ +namespace glm +{ + template<typename T, qualifier Q> + GLM_FUNC_QUALIFIER vec<4, bool, Q> equal(qua<T, Q> const& x, qua<T, Q> 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<typename T, qualifier Q> + GLM_FUNC_QUALIFIER vec<4, bool, Q> equal(qua<T, Q> const& x, qua<T, Q> 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<typename T, qualifier Q> + GLM_FUNC_QUALIFIER vec<4, bool, Q> notEqual(qua<T, Q> const& x, qua<T, Q> 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<typename T, qualifier Q> + GLM_FUNC_QUALIFIER vec<4, bool, Q> notEqual(qua<T, Q> const& x, qua<T, Q> 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 0000000000000000000000000000000000000000..a9cc5c2b59ff883d1de1b2bc2a0b57ca57144089 --- /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 <glm/ext/quaternion_transform.hpp> 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<typename T, qualifier Q> + GLM_FUNC_DECL qua<T, Q> rotate(qua<T, Q> 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 0000000000000000000000000000000000000000..b87ecb65d9f7ce739f5f3eeb1e57d5b4f4edf9e6 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/ext/quaternion_transform.inl @@ -0,0 +1,24 @@ +namespace glm +{ + template<typename T, qualifier Q> + GLM_FUNC_QUALIFIER qua<T, Q> rotate(qua<T, Q> 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<T>(1)) > static_cast<T>(0.001)) + { + T oneOverLen = static_cast<T>(1) / len; + Tmp.x *= oneOverLen; + Tmp.y *= oneOverLen; + Tmp.z *= oneOverLen; + } + + T const AngleRad(angle); + T const Sin = sin(AngleRad * static_cast<T>(0.5)); + + return q * qua<T, Q>(cos(AngleRad * static_cast<T>(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 0000000000000000000000000000000000000000..76cea27add64c4d32ec8dd0e164132090e1a43c7 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/ext/quaternion_trigonometric.hpp @@ -0,0 +1,63 @@ +/// @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 <glm/ext/quaternion_trigonometric.hpp> 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 <limits> + +#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. + /// + /// @tparam T A floating-point scalar type + /// @tparam Q A value from qualifier enum + template<typename T, qualifier Q> + GLM_FUNC_DECL T angle(qua<T, Q> const& x); + + /// Returns the q rotation axis. + /// + /// @tparam T A floating-point scalar type + /// @tparam Q A value from qualifier enum + template<typename T, qualifier Q> + GLM_FUNC_DECL vec<3, T, Q> axis(qua<T, Q> 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<typename T, qualifier Q> + GLM_FUNC_DECL qua<T, Q> 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 0000000000000000000000000000000000000000..06b7c4c3c98c1617926bb80cd37c9cad02170181 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/ext/quaternion_trigonometric.inl @@ -0,0 +1,34 @@ +#include "scalar_constants.hpp" + +namespace glm +{ + template<typename T, qualifier Q> + GLM_FUNC_QUALIFIER T angle(qua<T, Q> const& x) + { + if (abs(x.w) > cos_one_over_two<T>()) + { + return asin(sqrt(x.x * x.x + x.y * x.y + x.z * x.z)) * static_cast<T>(2); + } + + return acos(x.w) * static_cast<T>(2); + } + + template<typename T, qualifier Q> + GLM_FUNC_QUALIFIER vec<3, T, Q> axis(qua<T, Q> const& x) + { + T const tmp1 = static_cast<T>(1) - x.w * x.w; + if(tmp1 <= static_cast<T>(0)) + return vec<3, T, Q>(0, 0, 1); + T const tmp2 = static_cast<T>(1) / sqrt(tmp1); + return vec<3, T, Q>(x.x * tmp2, x.y * tmp2, x.z * tmp2); + } + + template<typename T, qualifier Q> + GLM_FUNC_QUALIFIER qua<T, Q> angleAxis(T const& angle, vec<3, T, Q> const& v) + { + T const a(angle); + T const s = glm::sin(a * static_cast<T>(0.5)); + + return qua<T, Q>(glm::cos(a * static_cast<T>(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 0000000000000000000000000000000000000000..aa5a180797da8d5927bec8f7da94412460266cf6 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/ext/scalar_common.hpp @@ -0,0 +1,157 @@ +/// @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 <glm/ext/scalar_common.hpp> 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<typename T> + 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<typename T> + 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<typename T> + 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<typename T> + 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 <a href="http://en.cppreference.com/w/cpp/numeric/math/fmin">std::fmin documentation</a> + /// @see ext_scalar_common + template<typename T> + 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 <a href="http://en.cppreference.com/w/cpp/numeric/math/fmin">std::fmin documentation</a> + /// @see ext_scalar_common + template<typename T> + 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 <a href="http://en.cppreference.com/w/cpp/numeric/math/fmin">std::fmin documentation</a> + /// @see ext_scalar_common + template<typename T> + 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 <a href="http://en.cppreference.com/w/cpp/numeric/math/fmax">std::fmax documentation</a> + /// @see ext_scalar_common + template<typename T> + 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 <a href="http://en.cppreference.com/w/cpp/numeric/math/fmax">std::fmax documentation</a> + /// @see ext_scalar_common + template<typename T> + 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 <a href="http://en.cppreference.com/w/cpp/numeric/math/fmax">std::fmax documentation</a> + /// @see ext_scalar_common + template<typename T> + 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<typename genType> + 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<typename genType> + 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<typename genType> + 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<typename genType> + 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<typename genType> + GLM_FUNC_DECL genType mirrorRepeat(genType const& Texcoord); + + /// @} +}//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 0000000000000000000000000000000000000000..7d9207afccf842e780d5da5ac6379d01eec095da --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/ext/scalar_common.inl @@ -0,0 +1,152 @@ +namespace glm +{ + template<typename T> + GLM_FUNC_QUALIFIER T min(T a, T b, T c) + { + return glm::min(glm::min(a, b), c); + } + + template<typename T> + 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<typename T> + GLM_FUNC_QUALIFIER T max(T a, T b, T c) + { + return glm::max(glm::max(a, b), c); + } + + template<typename T> + 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<typename T> + GLM_FUNC_QUALIFIER T fmin(T a, T b) + { + GLM_STATIC_ASSERT(std::numeric_limits<T>::is_iec559, "'fmin' only accept floating-point input"); + + if (isnan(a)) + return b; + return min(a, b); + } +# endif + + template<typename T> + GLM_FUNC_QUALIFIER T fmin(T a, T b, T c) + { + GLM_STATIC_ASSERT(std::numeric_limits<T>::is_iec559, "'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<typename T> + GLM_FUNC_QUALIFIER T fmin(T a, T b, T c, T d) + { + GLM_STATIC_ASSERT(std::numeric_limits<T>::is_iec559, "'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<typename T> + GLM_FUNC_QUALIFIER T fmax(T a, T b) + { + GLM_STATIC_ASSERT(std::numeric_limits<T>::is_iec559, "'fmax' only accept floating-point input"); + + if (isnan(a)) + return b; + return max(a, b); + } +# endif + + template<typename T> + GLM_FUNC_QUALIFIER T fmax(T a, T b, T c) + { + GLM_STATIC_ASSERT(std::numeric_limits<T>::is_iec559, "'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<typename T> + GLM_FUNC_QUALIFIER T fmax(T a, T b, T c, T d) + { + GLM_STATIC_ASSERT(std::numeric_limits<T>::is_iec559, "'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<typename genType> + GLM_FUNC_QUALIFIER genType fclamp(genType x, genType minVal, genType maxVal) + { + GLM_STATIC_ASSERT(std::numeric_limits<genType>::is_iec559, "'fclamp' only accept floating-point or integer inputs"); + return fmin(fmax(x, minVal), maxVal); + } + + template<typename genType> + GLM_FUNC_QUALIFIER genType clamp(genType const& Texcoord) + { + return glm::clamp(Texcoord, static_cast<genType>(0), static_cast<genType>(1)); + } + + template<typename genType> + GLM_FUNC_QUALIFIER genType repeat(genType const& Texcoord) + { + return glm::fract(Texcoord); + } + + template<typename genType> + GLM_FUNC_QUALIFIER genType mirrorClamp(genType const& Texcoord) + { + return glm::fract(glm::abs(Texcoord)); + } + + template<typename genType> + GLM_FUNC_QUALIFIER genType mirrorRepeat(genType const& Texcoord) + { + genType const Abs = glm::abs(Texcoord); + genType const Clamp = glm::mod(glm::floor(Abs), static_cast<genType>(2)); + genType const Floor = glm::floor(Abs); + genType const Rest = Abs - Floor; + genType const Mirror = Clamp + Rest; + return mix(Rest, static_cast<genType>(1) - Rest, Mirror >= static_cast<genType>(1)); + } +}//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 0000000000000000000000000000000000000000..74e210d9c09ec9440ce0dd8b843ba6b294c13ccd --- /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 <glm/ext/scalar_constants.hpp> 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<typename genType> + GLM_FUNC_DECL GLM_CONSTEXPR genType epsilon(); + + /// Return the pi constant for floating point types. + template<typename genType> + GLM_FUNC_DECL GLM_CONSTEXPR genType pi(); + + /// Return the value of cos(1 / 2) for floating point types. + template<typename genType> + 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 0000000000000000000000000000000000000000..b475adf83b6e248e0736e12963aef4c8562272c0 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/ext/scalar_constants.inl @@ -0,0 +1,24 @@ +#include <limits> + +namespace glm +{ + template<typename genType> + GLM_FUNC_QUALIFIER GLM_CONSTEXPR genType epsilon() + { + GLM_STATIC_ASSERT(std::numeric_limits<genType>::is_iec559, "'epsilon' only accepts floating-point inputs"); + return std::numeric_limits<genType>::epsilon(); + } + + template<typename genType> + GLM_FUNC_QUALIFIER GLM_CONSTEXPR genType pi() + { + GLM_STATIC_ASSERT(std::numeric_limits<genType>::is_iec559, "'pi' only accepts floating-point inputs"); + return static_cast<genType>(3.14159265358979323846264338327950288); + } + + template<typename genType> + 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 0000000000000000000000000000000000000000..8e9c511c9cb51010b4063882e14477d71eb3c7eb --- /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 <glm/ext/scalar_int_sized.hpp> 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<int8> + { + enum test {value = ~0}; + }; + + template<> + struct is_int<int16> + { + enum test {value = ~0}; + }; + + template<> + struct is_int<int64> + { + 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 0000000000000000000000000000000000000000..a2ca8a2ae37c6fe87997e66515ffead64fea23c7 --- /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 <glm/ext/scalar_integer.hpp> 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 <limits> + +#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<typename genIUType> + 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<typename genIUType> + 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<typename genIUType> + GLM_FUNC_DECL genIUType prevPowerOfTwo(genIUType v); + + /// Return true if the 'Value' is a multiple of 'Multiple'. + /// + /// @see ext_scalar_integer + template<typename genIUType> + 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<typename genIUType> + 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<typename genIUType> + 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<typename genIUType> + 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 0000000000000000000000000000000000000000..efba960097514ed1b3e4a33f55f49605f0d3d2dd --- /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<length_t L, typename T, qualifier Q, bool compute = false> + struct compute_ceilShift + { + GLM_FUNC_QUALIFIER static vec<L, T, Q> call(vec<L, T, Q> const& v, T) + { + return v; + } + }; + + template<length_t L, typename T, qualifier Q> + struct compute_ceilShift<L, T, Q, true> + { + GLM_FUNC_QUALIFIER static vec<L, T, Q> call(vec<L, T, Q> const& v, T Shift) + { + return v | (v >> Shift); + } + }; + + template<length_t L, typename T, qualifier Q, bool isSigned = true> + struct compute_ceilPowerOfTwo + { + GLM_FUNC_QUALIFIER static vec<L, T, Q> call(vec<L, T, Q> const& x) + { + GLM_STATIC_ASSERT(!std::numeric_limits<T>::is_iec559, "'ceilPowerOfTwo' only accept integer scalar or vector inputs"); + + vec<L, T, Q> const Sign(sign(x)); + + vec<L, T, Q> v(abs(x)); + + v = v - static_cast<T>(1); + v = v | (v >> static_cast<T>(1)); + v = v | (v >> static_cast<T>(2)); + v = v | (v >> static_cast<T>(4)); + v = compute_ceilShift<L, T, Q, sizeof(T) >= 2>::call(v, 8); + v = compute_ceilShift<L, T, Q, sizeof(T) >= 4>::call(v, 16); + v = compute_ceilShift<L, T, Q, sizeof(T) >= 8>::call(v, 32); + return (v + static_cast<T>(1)) * Sign; + } + }; + + template<length_t L, typename T, qualifier Q> + struct compute_ceilPowerOfTwo<L, T, Q, false> + { + GLM_FUNC_QUALIFIER static vec<L, T, Q> call(vec<L, T, Q> const& x) + { + GLM_STATIC_ASSERT(!std::numeric_limits<T>::is_iec559, "'ceilPowerOfTwo' only accept integer scalar or vector inputs"); + + vec<L, T, Q> v(x); + + v = v - static_cast<T>(1); + v = v | (v >> static_cast<T>(1)); + v = v | (v >> static_cast<T>(2)); + v = v | (v >> static_cast<T>(4)); + v = compute_ceilShift<L, T, Q, sizeof(T) >= 2>::call(v, 8); + v = compute_ceilShift<L, T, Q, sizeof(T) >= 4>::call(v, 16); + v = compute_ceilShift<L, T, Q, sizeof(T) >= 8>::call(v, 32); + return v + static_cast<T>(1); + } + }; + + template<bool is_float, bool is_signed> + struct compute_ceilMultiple{}; + + template<> + struct compute_ceilMultiple<true, true> + { + template<typename genType> + 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<false, false> + { + template<typename genType> + GLM_FUNC_QUALIFIER static genType call(genType Source, genType Multiple) + { + genType Tmp = Source - genType(1); + return Tmp + (Multiple - (Tmp % Multiple)); + } + }; + + template<> + struct compute_ceilMultiple<false, true> + { + template<typename genType> + 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<bool is_float, bool is_signed> + struct compute_floorMultiple{}; + + template<> + struct compute_floorMultiple<true, true> + { + template<typename genType> + 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<false, false> + { + template<typename genType> + 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<false, true> + { + template<typename genType> + 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<typename genIUType> + GLM_FUNC_QUALIFIER bool isPowerOfTwo(genIUType Value) + { + GLM_STATIC_ASSERT(std::numeric_limits<genIUType>::is_integer, "'isPowerOfTwo' only accept integer inputs"); + + genIUType const Result = glm::abs(Value); + return !(Result & (Result - 1)); + } + + template<typename genIUType> + GLM_FUNC_QUALIFIER genIUType nextPowerOfTwo(genIUType value) + { + GLM_STATIC_ASSERT(std::numeric_limits<genIUType>::is_integer, "'nextPowerOfTwo' only accept integer inputs"); + + return detail::compute_ceilPowerOfTwo<1, genIUType, defaultp, std::numeric_limits<genIUType>::is_signed>::call(vec<1, genIUType, defaultp>(value)).x; + } + + template<typename genIUType> + GLM_FUNC_QUALIFIER genIUType prevPowerOfTwo(genIUType value) + { + GLM_STATIC_ASSERT(std::numeric_limits<genIUType>::is_integer, "'prevPowerOfTwo' only accept integer inputs"); + + return isPowerOfTwo(value) ? value : static_cast<genIUType>(static_cast<genIUType>(1) << static_cast<genIUType>(findMSB(value))); + } + + template<typename genIUType> + GLM_FUNC_QUALIFIER bool isMultiple(genIUType Value, genIUType Multiple) + { + GLM_STATIC_ASSERT(std::numeric_limits<genIUType>::is_integer, "'isMultiple' only accept integer inputs"); + + return isMultiple(vec<1, genIUType>(Value), vec<1, genIUType>(Multiple)).x; + } + + template<typename genIUType> + GLM_FUNC_QUALIFIER genIUType nextMultiple(genIUType Source, genIUType Multiple) + { + GLM_STATIC_ASSERT(std::numeric_limits<genIUType>::is_integer, "'nextMultiple' only accept integer inputs"); + + return detail::compute_ceilMultiple<std::numeric_limits<genIUType>::is_iec559, std::numeric_limits<genIUType>::is_signed>::call(Source, Multiple); + } + + template<typename genIUType> + GLM_FUNC_QUALIFIER genIUType prevMultiple(genIUType Source, genIUType Multiple) + { + GLM_STATIC_ASSERT(std::numeric_limits<genIUType>::is_integer, "'prevMultiple' only accept integer inputs"); + + return detail::compute_floorMultiple<std::numeric_limits<genIUType>::is_iec559, std::numeric_limits<genIUType>::is_signed>::call(Source, Multiple); + } + + template<typename genIUType> + GLM_FUNC_QUALIFIER int findNSB(genIUType x, int significantBitCount) + { + GLM_STATIC_ASSERT(std::numeric_limits<genIUType>::is_integer, "'findNSB' only accept integer inputs"); + + if(bitCount(x) < significantBitCount) + return -1; + + genIUType const One = static_cast<genIUType>(1); + int bitPos = 0; + + genIUType key = x; + int nBitCount = significantBitCount; + int Step = sizeof(x) * 8 / 2; + while (key > One) + { + genIUType Mask = static_cast<genIUType>((One << Step) - One); + genIUType currentKey = key & Mask; + int currentBitCount = bitCount(currentKey); + if (nBitCount > currentBitCount) + { + nBitCount -= currentBitCount; + bitPos += Step; + key >>= static_cast<genIUType>(Step); + } + else + { + key = key & Mask; + } + + Step >>= 1; + } + + return static_cast<int>(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 0000000000000000000000000000000000000000..18b85b72a404b7a9bba50d88812dce114671969a --- /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 <glm/ext/scalar_packing.hpp> 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 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 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 0000000000000000000000000000000000000000..3076a5e63f93112b9a60974b8b33388272df96e8 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/ext/scalar_relational.hpp @@ -0,0 +1,65 @@ +/// @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 <glm/ext/scalar_relational.hpp> 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 +{ + /// Returns the component-wise comparison of |x - y| < epsilon. + /// True if this expression is satisfied. + /// + /// @tparam genType Floating-point or integer scalar types + template<typename genType> + 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<typename genType> + 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<typename genType> + 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<typename genType> + 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 0000000000000000000000000000000000000000..c85583ef5bbd476161be8a5b1d2b1b1e90675b2b --- /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<typename genType> + GLM_FUNC_QUALIFIER GLM_CONSTEXPR bool equal(genType const& x, genType const& y, genType const& epsilon) + { + return abs(x - y) <= epsilon; + } + + template<typename genType> + GLM_FUNC_QUALIFIER GLM_CONSTEXPR bool notEqual(genType const& x, genType const& y, genType const& epsilon) + { + return abs(x - y) > epsilon; + } + + template<typename genType> + GLM_FUNC_QUALIFIER GLM_CONSTEXPR bool equal(genType const& x, genType const& y, int MaxULPs) + { + detail::float_t<genType> const a(x); + detail::float_t<genType> 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<genType>::int_type const DiffULPs = abs(a.i - b.i); + return DiffULPs <= MaxULPs; + } + + template<typename genType> + 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 0000000000000000000000000000000000000000..fd5267fad7c16dc5670f1622b3328ea5089d5a66 --- /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 <glm/ext/scalar_uint_sized.hpp> 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<uint8> + { + enum test {value = ~0}; + }; + + template<> + struct is_int<uint16> + { + enum test {value = ~0}; + }; + + template<> + struct is_int<uint64> + { + 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 0000000000000000000000000000000000000000..941ada3e8cb3d4b490d4a40055c46b286acfbc7b --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/ext/scalar_ulp.hpp @@ -0,0 +1,74 @@ +/// @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 <glm/ext/scalar_ulp.hpp> 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 +{ + /// Return the next ULP value(s) after the input value(s). + /// + /// @tparam genType A floating-point scalar type. + /// + /// @see ext_scalar_ulp + template<typename genType> + 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<typename genType> + 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<typename genType> + 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<typename genType> + 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 0000000000000000000000000000000000000000..308df150687c033bcd36d3ce5dd0a4e2d841150e --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/ext/scalar_ulp.inl @@ -0,0 +1,284 @@ +/// 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 <cmath> +#include <cfloat> + +#if(GLM_COMPILER & GLM_COMPILER_VC) +# pragma warning(push) +# pragma warning(disable : 4127) +#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) = gf_u.word; \ + } while (0) + +#define GLM_SET_FLOAT_WORD(d,i) \ + do { \ + ieee_float_shape_type sf_u; \ + sf_u.word = (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<float>()) + 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<float>()) + 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<float>()) + { // 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<double>()) + 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<double>()) + 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<double>()) + { // 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) +#endif + +namespace glm +{ + template<> + GLM_FUNC_QUALIFIER float nextFloat(float x) + { +# if GLM_HAS_CXX11_STL + return std::nextafter(x, std::numeric_limits<float>::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<double>::max()); +# elif((GLM_COMPILER & GLM_COMPILER_VC) || ((GLM_COMPILER & GLM_COMPILER_INTEL) && (GLM_PLATFORM & GLM_PLATFORM_WINDOWS))) + return detail::nextafter(x, std::numeric_limits<double>::max()); +# elif(GLM_PLATFORM & GLM_PLATFORM_ANDROID) + return __builtin_nextafter(x, DBL_MAX); +# else + return nextafter(x, DBL_MAX); +# endif + } + + template<typename T> + GLM_FUNC_QUALIFIER T nextFloat(T x, int ULPs) + { + GLM_STATIC_ASSERT(std::numeric_limits<T>::is_iec559, "'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<float>::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<double>::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<typename T> + GLM_FUNC_QUALIFIER T prevFloat(T x, int ULPs) + { + GLM_STATIC_ASSERT(std::numeric_limits<T>::is_iec559, "'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<float> const a(x); + detail::float_t<float> const b(y); + + return abs(a.i - b.i); + } + + GLM_FUNC_QUALIFIER int64 floatDistance(double x, double y) + { + detail::float_t<double> const a(x); + detail::float_t<double> 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 0000000000000000000000000000000000000000..002c3202adf0dfbb2db1eedf23f2f677d343c6f3 --- /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 <glm/ext/vector_bool1.hpp> 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 0000000000000000000000000000000000000000..e62d3cfb5fd4c6f31e9bb22cc4129c7bf7f28e01 --- /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 <glm/ext/vector_bool1_precision.hpp> 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 0000000000000000000000000000000000000000..52288b75c6973f49aabb5b8a15ddd1036b172f84 --- /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 <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 4.1.5 Vectors</a> + 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 0000000000000000000000000000000000000000..43709332c6298ff345ab3b061917272aa954f655 --- /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 <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 4.1.5 Vectors</a> + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 4.7.2 Precision Qualifier</a> + typedef vec<2, bool, highp> highp_bvec2; + + /// 2 components vector of medium qualifier bool numbers. + /// + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 4.1.5 Vectors</a> + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 4.7.2 Precision Qualifier</a> + typedef vec<2, bool, mediump> mediump_bvec2; + + /// 2 components vector of low qualifier bool numbers. + /// + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 4.1.5 Vectors</a> + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 4.7.2 Precision Qualifier</a> + 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 0000000000000000000000000000000000000000..90a0b7ea5ac048f264dff79fe8d270993e55d414 --- /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 <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 4.1.5 Vectors</a> + 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 0000000000000000000000000000000000000000..89cd2d3207a168545f98a3d0af69b9c772a7c965 --- /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 <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 4.1.5 Vectors</a> + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 4.7.2 Precision Qualifier</a> + typedef vec<3, bool, highp> highp_bvec3; + + /// 3 components vector of medium qualifier bool numbers. + /// + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 4.1.5 Vectors</a> + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 4.7.2 Precision Qualifier</a> + typedef vec<3, bool, mediump> mediump_bvec3; + + /// 3 components vector of low qualifier bool numbers. + /// + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 4.1.5 Vectors</a> + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 4.7.2 Precision Qualifier</a> + 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 0000000000000000000000000000000000000000..18aa71bd0f49851cac489520c4df893370ddeb6e --- /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 <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 4.1.5 Vectors</a> + 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 0000000000000000000000000000000000000000..79786e54206b9cb3e92c6ba3d9d69f35200e552b --- /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 <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 4.1.5 Vectors</a> + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 4.7.2 Precision Qualifier</a> + typedef vec<4, bool, highp> highp_bvec4; + + /// 4 components vector of medium qualifier bool numbers. + /// + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 4.1.5 Vectors</a> + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 4.7.2 Precision Qualifier</a> + typedef vec<4, bool, mediump> mediump_bvec4; + + /// 4 components vector of low qualifier bool numbers. + /// + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 4.1.5 Vectors</a> + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 4.7.2 Precision Qualifier</a> + 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 0000000000000000000000000000000000000000..521ec01e7624763d42eaa158f3b140d84c2d127b --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/ext/vector_common.hpp @@ -0,0 +1,204 @@ +/// @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 <glm/ext/vector_common.hpp> 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<length_t L, typename T, qualifier Q> + GLM_FUNC_DECL GLM_CONSTEXPR vec<L, T, Q> min(vec<L, T, Q> const& a, vec<L, T, Q> const& b, vec<L, T, Q> 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<length_t L, typename T, qualifier Q> + GLM_FUNC_DECL GLM_CONSTEXPR vec<L, T, Q> min(vec<L, T, Q> const& a, vec<L, T, Q> const& b, vec<L, T, Q> const& c, vec<L, T, Q> 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<length_t L, typename T, qualifier Q> + GLM_FUNC_DECL GLM_CONSTEXPR vec<L, T, Q> max(vec<L, T, Q> const& x, vec<L, T, Q> const& y, vec<L, T, Q> 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<length_t L, typename T, qualifier Q> + GLM_FUNC_DECL GLM_CONSTEXPR vec<L, T, Q> max( vec<L, T, Q> const& x, vec<L, T, Q> const& y, vec<L, T, Q> const& z, vec<L, T, Q> 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 <a href="http://en.cppreference.com/w/cpp/numeric/math/fmin">std::fmin documentation</a> + template<length_t L, typename T, qualifier Q> + GLM_FUNC_DECL vec<L, T, Q> fmin(vec<L, T, Q> 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 <a href="http://en.cppreference.com/w/cpp/numeric/math/fmin">std::fmin documentation</a> + template<length_t L, typename T, qualifier Q> + GLM_FUNC_DECL vec<L, T, Q> fmin(vec<L, T, Q> const& x, vec<L, T, Q> 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 <a href="http://en.cppreference.com/w/cpp/numeric/math/fmin">std::fmin documentation</a> + template<length_t L, typename T, qualifier Q> + GLM_FUNC_DECL vec<L, T, Q> fmin(vec<L, T, Q> const& a, vec<L, T, Q> const& b, vec<L, T, Q> 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 <a href="http://en.cppreference.com/w/cpp/numeric/math/fmin">std::fmin documentation</a> + template<length_t L, typename T, qualifier Q> + GLM_FUNC_DECL vec<L, T, Q> fmin(vec<L, T, Q> const& a, vec<L, T, Q> const& b, vec<L, T, Q> const& c, vec<L, T, Q> 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 <a href="http://en.cppreference.com/w/cpp/numeric/math/fmax">std::fmax documentation</a> + template<length_t L, typename T, qualifier Q> + GLM_FUNC_DECL vec<L, T, Q> fmax(vec<L, T, Q> 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 <a href="http://en.cppreference.com/w/cpp/numeric/math/fmax">std::fmax documentation</a> + template<length_t L, typename T, qualifier Q> + GLM_FUNC_DECL vec<L, T, Q> fmax(vec<L, T, Q> const& a, vec<L, T, Q> 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 <a href="http://en.cppreference.com/w/cpp/numeric/math/fmax">std::fmax documentation</a> + template<length_t L, typename T, qualifier Q> + GLM_FUNC_DECL vec<L, T, Q> fmax(vec<L, T, Q> const& a, vec<L, T, Q> const& b, vec<L, T, Q> 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 <a href="http://en.cppreference.com/w/cpp/numeric/math/fmax">std::fmax documentation</a> + template<length_t L, typename T, qualifier Q> + GLM_FUNC_DECL vec<L, T, Q> fmax(vec<L, T, Q> const& a, vec<L, T, Q> const& b, vec<L, T, Q> const& c, vec<L, T, Q> 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<length_t L, typename T, qualifier Q> + GLM_FUNC_DECL vec<L, T, Q> fclamp(vec<L, T, Q> 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<length_t L, typename T, qualifier Q> + GLM_FUNC_DECL vec<L, T, Q> fclamp(vec<L, T, Q> const& x, vec<L, T, Q> const& minVal, vec<L, T, Q> 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<length_t L, typename T, qualifier Q> + GLM_FUNC_DECL vec<L, T, Q> clamp(vec<L, T, Q> 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<length_t L, typename T, qualifier Q> + GLM_FUNC_DECL vec<L, T, Q> repeat(vec<L, T, Q> 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<length_t L, typename T, qualifier Q> + GLM_FUNC_DECL vec<L, T, Q> mirrorClamp(vec<L, T, Q> 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<length_t L, typename T, qualifier Q> + GLM_FUNC_DECL vec<L, T, Q> mirrorRepeat(vec<L, T, Q> const& Texcoord); + + /// @} +}//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 0000000000000000000000000000000000000000..e2747be7b2bf65ab7d60c3d45c623f793019cbf9 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/ext/vector_common.inl @@ -0,0 +1,129 @@ +#include "../detail/_vectorize.hpp" + +namespace glm +{ + template<length_t L, typename T, qualifier Q> + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<L, T, Q> min(vec<L, T, Q> const& x, vec<L, T, Q> const& y, vec<L, T, Q> const& z) + { + GLM_STATIC_ASSERT(std::numeric_limits<T>::is_iec559, "'min' only accept floating-point or integer inputs"); + return glm::min(glm::min(x, y), z); + } + + template<length_t L, typename T, qualifier Q> + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<L, T, Q> min(vec<L, T, Q> const& x, vec<L, T, Q> const& y, vec<L, T, Q> const& z, vec<L, T, Q> const& w) + { + GLM_STATIC_ASSERT(std::numeric_limits<T>::is_iec559, "'min' only accept floating-point or integer inputs"); + return glm::min(glm::min(x, y), glm::min(z, w)); + } + + template<length_t L, typename T, qualifier Q> + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<L, T, Q> max(vec<L, T, Q> const& x, vec<L, T, Q> const& y, vec<L, T, Q> const& z) + { + GLM_STATIC_ASSERT(std::numeric_limits<T>::is_iec559, "'max' only accept floating-point or integer inputs"); + return glm::max(glm::max(x, y), z); + } + + template<length_t L, typename T, qualifier Q> + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<L, T, Q> max(vec<L, T, Q> const& x, vec<L, T, Q> const& y, vec<L, T, Q> const& z, vec<L, T, Q> const& w) + { + GLM_STATIC_ASSERT(std::numeric_limits<T>::is_iec559, "'max' only accept floating-point or integer inputs"); + return glm::max(glm::max(x, y), glm::max(z, w)); + } + + template<length_t L, typename T, qualifier Q> + GLM_FUNC_QUALIFIER vec<L, T, Q> fmin(vec<L, T, Q> const& a, T b) + { + GLM_STATIC_ASSERT(std::numeric_limits<T>::is_iec559, "'fmin' only accept floating-point inputs"); + return detail::functor2<vec, L, T, Q>::call(fmin, a, vec<L, T, Q>(b)); + } + + template<length_t L, typename T, qualifier Q> + GLM_FUNC_QUALIFIER vec<L, T, Q> fmin(vec<L, T, Q> const& a, vec<L, T, Q> const& b) + { + GLM_STATIC_ASSERT(std::numeric_limits<T>::is_iec559, "'fmin' only accept floating-point inputs"); + return detail::functor2<vec, L, T, Q>::call(fmin, a, b); + } + + template<length_t L, typename T, qualifier Q> + GLM_FUNC_QUALIFIER vec<L, T, Q> fmin(vec<L, T, Q> const& a, vec<L, T, Q> const& b, vec<L, T, Q> const& c) + { + GLM_STATIC_ASSERT(std::numeric_limits<T>::is_iec559, "'fmin' only accept floating-point inputs"); + return fmin(fmin(a, b), c); + } + + template<length_t L, typename T, qualifier Q> + GLM_FUNC_QUALIFIER vec<L, T, Q> fmin(vec<L, T, Q> const& a, vec<L, T, Q> const& b, vec<L, T, Q> const& c, vec<L, T, Q> const& d) + { + GLM_STATIC_ASSERT(std::numeric_limits<T>::is_iec559, "'fmin' only accept floating-point inputs"); + return fmin(fmin(a, b), fmin(c, d)); + } + + template<length_t L, typename T, qualifier Q> + GLM_FUNC_QUALIFIER vec<L, T, Q> fmax(vec<L, T, Q> const& a, T b) + { + GLM_STATIC_ASSERT(std::numeric_limits<T>::is_iec559, "'fmax' only accept floating-point inputs"); + return detail::functor2<vec, L, T, Q>::call(fmax, a, vec<L, T, Q>(b)); + } + + template<length_t L, typename T, qualifier Q> + GLM_FUNC_QUALIFIER vec<L, T, Q> fmax(vec<L, T, Q> const& a, vec<L, T, Q> const& b) + { + GLM_STATIC_ASSERT(std::numeric_limits<T>::is_iec559, "'fmax' only accept floating-point inputs"); + return detail::functor2<vec, L, T, Q>::call(fmax, a, b); + } + + template<length_t L, typename T, qualifier Q> + GLM_FUNC_QUALIFIER vec<L, T, Q> fmax(vec<L, T, Q> const& a, vec<L, T, Q> const& b, vec<L, T, Q> const& c) + { + GLM_STATIC_ASSERT(std::numeric_limits<T>::is_iec559, "'fmax' only accept floating-point inputs"); + return fmax(fmax(a, b), c); + } + + template<length_t L, typename T, qualifier Q> + GLM_FUNC_QUALIFIER vec<L, T, Q> fmax(vec<L, T, Q> const& a, vec<L, T, Q> const& b, vec<L, T, Q> const& c, vec<L, T, Q> const& d) + { + GLM_STATIC_ASSERT(std::numeric_limits<T>::is_iec559, "'fmax' only accept floating-point inputs"); + return fmax(fmax(a, b), fmax(c, d)); + } + + template<length_t L, typename T, qualifier Q> + GLM_FUNC_QUALIFIER vec<L, T, Q> fclamp(vec<L, T, Q> const& x, T minVal, T maxVal) + { + return fmin(fmax(x, vec<L, T, Q>(minVal)), vec<L, T, Q>(maxVal)); + } + + template<length_t L, typename T, qualifier Q> + GLM_FUNC_QUALIFIER vec<L, T, Q> fclamp(vec<L, T, Q> const& x, vec<L, T, Q> const& minVal, vec<L, T, Q> const& maxVal) + { + return fmin(fmax(x, minVal), maxVal); + } + + template<length_t L, typename T, qualifier Q> + GLM_FUNC_QUALIFIER vec<L, T, Q> clamp(vec<L, T, Q> const& Texcoord) + { + return glm::clamp(Texcoord, vec<L, T, Q>(0), vec<L, T, Q>(1)); + } + + template<length_t L, typename T, qualifier Q> + GLM_FUNC_QUALIFIER vec<L, T, Q> repeat(vec<L, T, Q> const& Texcoord) + { + return glm::fract(Texcoord); + } + + template<length_t L, typename T, qualifier Q> + GLM_FUNC_QUALIFIER vec<L, T, Q> mirrorClamp(vec<L, T, Q> const& Texcoord) + { + return glm::fract(glm::abs(Texcoord)); + } + + template<length_t L, typename T, qualifier Q> + GLM_FUNC_QUALIFIER vec<L, T, Q> mirrorRepeat(vec<L, T, Q> const& Texcoord) + { + vec<L, T, Q> const Abs = glm::abs(Texcoord); + vec<L, T, Q> const Clamp = glm::mod(glm::floor(Abs), vec<L, T, Q>(2)); + vec<L, T, Q> const Floor = glm::floor(Abs); + vec<L, T, Q> const Rest = Abs - Floor; + vec<L, T, Q> const Mirror = Clamp + Rest; + return mix(Rest, vec<L, T, Q>(1) - Rest, glm::greaterThanEqual(Mirror, vec<L, T, Q>(1))); + } +}//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 0000000000000000000000000000000000000000..388266774d8b3371be46da89e13af7b1edde240c --- /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 <glm/ext/vector_double1.hpp> 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 0000000000000000000000000000000000000000..1d4719595481adf57c071e0fbf6df4716447a55a --- /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 <glm/ext/vector_double1_precision.hpp> 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 0000000000000000000000000000000000000000..60e357750b675415da9d8911b92ba702b7aa8390 --- /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 <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 4.1.5 Vectors</a> + 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 0000000000000000000000000000000000000000..fa53940f6bbed061a7f3fc4162877b68b96c9388 --- /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 <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 4.1.5 Vectors</a> + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 4.7.2 Precision Qualifier</a> + typedef vec<2, double, highp> highp_dvec2; + + /// 2 components vector of medium double-qualifier floating-point numbers. + /// + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 4.1.5 Vectors</a> + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 4.7.2 Precision Qualifier</a> + typedef vec<2, double, mediump> mediump_dvec2; + + /// 2 components vector of low double-qualifier floating-point numbers. + /// + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 4.1.5 Vectors</a> + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 4.7.2 Precision Qualifier</a> + 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 0000000000000000000000000000000000000000..6dfe4c675b5d7af1f3538f5c32203065453b4025 --- /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 <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 4.1.5 Vectors</a> + 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 0000000000000000000000000000000000000000..a8cfa37a8c78009bd18ddfbfff7e4a658300e712 --- /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 <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 4.1.5 Vectors</a> + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 4.7.2 Precision Qualifier</a> + 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 <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 4.1.5 Vectors</a> + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 4.7.2 Precision Qualifier</a> + 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 <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 4.1.5 Vectors</a> + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 4.7.2 Precision Qualifier</a> + 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 0000000000000000000000000000000000000000..87f225f64d4ab38b0d7212174308e606e2c9ad18 --- /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 <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 4.1.5 Vectors</a> + 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 0000000000000000000000000000000000000000..09cafa1ebafdd72b85c4f01746bf315ddee1c02a --- /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 <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 4.1.5 Vectors</a> + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 4.7.2 Precision Qualifier</a> + 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 <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 4.1.5 Vectors</a> + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 4.7.2 Precision Qualifier</a> + 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 <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 4.1.5 Vectors</a> + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 4.7.2 Precision Qualifier</a> + 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 0000000000000000000000000000000000000000..28acc2c9ca59619ba1401032141ed223d347650f --- /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 <glm/ext/vector_float1.hpp> 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 0000000000000000000000000000000000000000..6e8dad8d17c8e0e2765aa53323a1c093c685279e --- /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 <glm/ext/vector_float1_precision.hpp> 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 0000000000000000000000000000000000000000..d31545dcc966b37c0c942a9d248bb337c4b178a5 --- /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 <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 4.1.5 Vectors</a> + 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 0000000000000000000000000000000000000000..23c0820d0ae8445f4539bf0b7f7c18886eb8ae41 --- /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 <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 4.1.5 Vectors</a> + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 4.7.2 Precision Qualifier</a> + typedef vec<2, float, highp> highp_vec2; + + /// 2 components vector of medium single-qualifier floating-point numbers. + /// + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 4.1.5 Vectors</a> + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 4.7.2 Precision Qualifier</a> + typedef vec<2, float, mediump> mediump_vec2; + + /// 2 components vector of low single-qualifier floating-point numbers. + /// + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 4.1.5 Vectors</a> + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 4.7.2 Precision Qualifier</a> + 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 0000000000000000000000000000000000000000..cd79a62004e41ebb2798363235b7573496eacf05 --- /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 <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 4.1.5 Vectors</a> + 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 0000000000000000000000000000000000000000..be640b53168387c07c3c2f8640794699a8e5953c --- /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 <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 4.1.5 Vectors</a> + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 4.7.2 Precision Qualifier</a> + typedef vec<3, float, highp> highp_vec3; + + /// 3 components vector of medium single-qualifier floating-point numbers. + /// + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 4.1.5 Vectors</a> + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 4.7.2 Precision Qualifier</a> + typedef vec<3, float, mediump> mediump_vec3; + + /// 3 components vector of low single-qualifier floating-point numbers. + /// + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 4.1.5 Vectors</a> + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 4.7.2 Precision Qualifier</a> + 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 0000000000000000000000000000000000000000..d84adcc22fd2b2e914ab6f56af92d534a00ddbd7 --- /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 <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 4.1.5 Vectors</a> + 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 0000000000000000000000000000000000000000..aede83882e55140fa53adde2ea0b72be29c77490 --- /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 <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 4.1.5 Vectors</a> + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 4.7.2 Precision Qualifier</a> + typedef vec<4, float, highp> highp_vec4; + + /// 4 components vector of medium single-qualifier floating-point numbers. + /// + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 4.1.5 Vectors</a> + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 4.7.2 Precision Qualifier</a> + typedef vec<4, float, mediump> mediump_vec4; + + /// 4 components vector of low single-qualifier floating-point numbers. + /// + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 4.1.5 Vectors</a> + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 4.7.2 Precision Qualifier</a> + 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 0000000000000000000000000000000000000000..dc8603891a9967bace26b4c23f4c5485b22f6ba4 --- /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 <glm/ext/vector_int1.hpp> 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 0000000000000000000000000000000000000000..de0d4cf82e633bc8a1139f770a9f17349462433f --- /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 <glm/ext/vector_int1_sized.hpp> 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 0000000000000000000000000000000000000000..aef803e91b736a1f2a3a32deefecdebbbc70fe5d --- /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 <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 4.1.5 Vectors</a> + 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 0000000000000000000000000000000000000000..1fd57eef310d7522f0969f2ca3f71857aa40f596 --- /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 <glm/ext/vector_int2_sized.hpp> 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 0000000000000000000000000000000000000000..4767e61e88c08a38696700ab9d2517bcde346085 --- /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 <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 4.1.5 Vectors</a> + 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 0000000000000000000000000000000000000000..085a3febbffdf31a2b35637f403dfb366c0b03de --- /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 <glm/ext/vector_int3_sized.hpp> 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 0000000000000000000000000000000000000000..bb23adf706c226d13cb3291f7ab9ded06c30e945 --- /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 <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 4.1.5 Vectors</a> + 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 0000000000000000000000000000000000000000..c63d46540b3e149429c4afa540fac28792b0a00f --- /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 <glm/ext/vector_int4_sized.hpp> 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 0000000000000000000000000000000000000000..1304dd8d660f0e051500cd3ff8a905221f94fd12 --- /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 <glm/ext/vector_integer.hpp> 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 <limits> + +#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<length_t L, typename T, qualifier Q> + GLM_FUNC_DECL vec<L, bool, Q> isPowerOfTwo(vec<L, T, Q> 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<length_t L, typename T, qualifier Q> + GLM_FUNC_DECL vec<L, T, Q> nextPowerOfTwo(vec<L, T, Q> 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<length_t L, typename T, qualifier Q> + GLM_FUNC_DECL vec<L, T, Q> prevPowerOfTwo(vec<L, T, Q> 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<length_t L, typename T, qualifier Q> + GLM_FUNC_DECL vec<L, bool, Q> isMultiple(vec<L, T, Q> 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<length_t L, typename T, qualifier Q> + GLM_FUNC_DECL vec<L, bool, Q> isMultiple(vec<L, T, Q> const& v, vec<L, T, Q> 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<length_t L, typename T, qualifier Q> + GLM_FUNC_DECL vec<L, T, Q> nextMultiple(vec<L, T, Q> 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<length_t L, typename T, qualifier Q> + GLM_FUNC_DECL vec<L, T, Q> nextMultiple(vec<L, T, Q> const& v, vec<L, T, Q> 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<length_t L, typename T, qualifier Q> + GLM_FUNC_DECL vec<L, T, Q> prevMultiple(vec<L, T, Q> 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<length_t L, typename T, qualifier Q> + GLM_FUNC_DECL vec<L, T, Q> prevMultiple(vec<L, T, Q> const& v, vec<L, T, Q> 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<length_t L, typename T, qualifier Q> + GLM_FUNC_DECL vec<L, int, Q> findNSB(vec<L, T, Q> const& Source, vec<L, int, Q> 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 0000000000000000000000000000000000000000..939ff5e2aca4cf2fa2fc445f03ecb92295861558 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/ext/vector_integer.inl @@ -0,0 +1,85 @@ +#include "scalar_integer.hpp" + +namespace glm +{ + template<length_t L, typename T, qualifier Q> + GLM_FUNC_QUALIFIER vec<L, bool, Q> isPowerOfTwo(vec<L, T, Q> const& Value) + { + GLM_STATIC_ASSERT(std::numeric_limits<T>::is_integer, "'isPowerOfTwo' only accept integer inputs"); + + vec<L, T, Q> const Result(abs(Value)); + return equal(Result & (Result - vec<L, T, Q>(1)), vec<L, T, Q>(0)); + } + + template<length_t L, typename T, qualifier Q> + GLM_FUNC_QUALIFIER vec<L, T, Q> nextPowerOfTwo(vec<L, T, Q> const& v) + { + GLM_STATIC_ASSERT(std::numeric_limits<T>::is_integer, "'nextPowerOfTwo' only accept integer inputs"); + + return detail::compute_ceilPowerOfTwo<L, T, Q, std::numeric_limits<T>::is_signed>::call(v); + } + + template<length_t L, typename T, qualifier Q> + GLM_FUNC_QUALIFIER vec<L, T, Q> prevPowerOfTwo(vec<L, T, Q> const& v) + { + GLM_STATIC_ASSERT(std::numeric_limits<T>::is_integer, "'prevPowerOfTwo' only accept integer inputs"); + + return detail::functor1<vec, L, T, T, Q>::call(prevPowerOfTwo, v); + } + + template<length_t L, typename T, qualifier Q> + GLM_FUNC_QUALIFIER vec<L, bool, Q> isMultiple(vec<L, T, Q> const& Value, T Multiple) + { + GLM_STATIC_ASSERT(std::numeric_limits<T>::is_integer, "'isMultiple' only accept integer inputs"); + + return (Value % Multiple) == vec<L, T, Q>(0); + } + + template<length_t L, typename T, qualifier Q> + GLM_FUNC_QUALIFIER vec<L, bool, Q> isMultiple(vec<L, T, Q> const& Value, vec<L, T, Q> const& Multiple) + { + GLM_STATIC_ASSERT(std::numeric_limits<T>::is_integer, "'isMultiple' only accept integer inputs"); + + return (Value % Multiple) == vec<L, T, Q>(0); + } + + template<length_t L, typename T, qualifier Q> + GLM_FUNC_QUALIFIER vec<L, T, Q> nextMultiple(vec<L, T, Q> const& Source, T Multiple) + { + GLM_STATIC_ASSERT(std::numeric_limits<T>::is_integer, "'nextMultiple' only accept integer inputs"); + + return detail::functor2<vec, L, T, Q>::call(nextMultiple, Source, vec<L, T, Q>(Multiple)); + } + + template<length_t L, typename T, qualifier Q> + GLM_FUNC_QUALIFIER vec<L, T, Q> nextMultiple(vec<L, T, Q> const& Source, vec<L, T, Q> const& Multiple) + { + GLM_STATIC_ASSERT(std::numeric_limits<T>::is_integer, "'nextMultiple' only accept integer inputs"); + + return detail::functor2<vec, L, T, Q>::call(nextMultiple, Source, Multiple); + } + + template<length_t L, typename T, qualifier Q> + GLM_FUNC_QUALIFIER vec<L, T, Q> prevMultiple(vec<L, T, Q> const& Source, T Multiple) + { + GLM_STATIC_ASSERT(std::numeric_limits<T>::is_integer, "'prevMultiple' only accept integer inputs"); + + return detail::functor2<vec, L, T, Q>::call(prevMultiple, Source, vec<L, T, Q>(Multiple)); + } + + template<length_t L, typename T, qualifier Q> + GLM_FUNC_QUALIFIER vec<L, T, Q> prevMultiple(vec<L, T, Q> const& Source, vec<L, T, Q> const& Multiple) + { + GLM_STATIC_ASSERT(std::numeric_limits<T>::is_integer, "'prevMultiple' only accept integer inputs"); + + return detail::functor2<vec, L, T, Q>::call(prevMultiple, Source, Multiple); + } + + template<length_t L, typename T, qualifier Q> + GLM_FUNC_QUALIFIER vec<L, int, Q> findNSB(vec<L, T, Q> const& Source, vec<L, int, Q> SignificantBitCount) + { + GLM_STATIC_ASSERT(std::numeric_limits<T>::is_integer, "'findNSB' only accept integer inputs"); + + return detail::functor2_vec_int<L, T, Q>::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 0000000000000000000000000000000000000000..76e5d0cc6c2f0c8d6a6cbcbc176a1fc7b90b9b32 --- /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 <glm/ext/vector_packing.hpp> 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 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 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 0000000000000000000000000000000000000000..1c2367dc023103160ec68dee0590d32f8be70550 --- /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 <glm/ext/vector_relational.hpp> 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<length_t L, typename T, qualifier Q> + GLM_FUNC_DECL GLM_CONSTEXPR vec<L, bool, Q> equal(vec<L, T, Q> const& x, vec<L, T, Q> 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<length_t L, typename T, qualifier Q> + GLM_FUNC_DECL GLM_CONSTEXPR vec<L, bool, Q> equal(vec<L, T, Q> const& x, vec<L, T, Q> const& y, vec<L, T, Q> 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<length_t L, typename T, qualifier Q> + GLM_FUNC_DECL GLM_CONSTEXPR vec<L, bool, Q> notEqual(vec<L, T, Q> const& x, vec<L, T, Q> 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<length_t L, typename T, qualifier Q> + GLM_FUNC_DECL GLM_CONSTEXPR vec<L, bool, Q> notEqual(vec<L, T, Q> const& x, vec<L, T, Q> const& y, vec<L, T, Q> 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<length_t L, typename T, qualifier Q> + GLM_FUNC_DECL GLM_CONSTEXPR vec<L, bool, Q> equal(vec<L, T, Q> const& x, vec<L, T, Q> 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<length_t L, typename T, qualifier Q> + GLM_FUNC_DECL GLM_CONSTEXPR vec<L, bool, Q> equal(vec<L, T, Q> const& x, vec<L, T, Q> const& y, vec<L, int, Q> 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<length_t L, typename T, qualifier Q> + GLM_FUNC_DECL GLM_CONSTEXPR vec<L, bool, Q> notEqual(vec<L, T, Q> const& x, vec<L, T, Q> 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<length_t L, typename T, qualifier Q> + GLM_FUNC_DECL GLM_CONSTEXPR vec<L, bool, Q> notEqual(vec<L, T, Q> const& x, vec<L, T, Q> const& y, vec<L, int, Q> 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 0000000000000000000000000000000000000000..7a39ab50897e35588cf226c741df6e7beb00e884 --- /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<length_t L, typename T, qualifier Q> + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<L, bool, Q> equal(vec<L, T, Q> const& x, vec<L, T, Q> const& y, T Epsilon) + { + return equal(x, y, vec<L, T, Q>(Epsilon)); + } + + template<length_t L, typename T, qualifier Q> + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<L, bool, Q> equal(vec<L, T, Q> const& x, vec<L, T, Q> const& y, vec<L, T, Q> const& Epsilon) + { + return lessThanEqual(abs(x - y), Epsilon); + } + + template<length_t L, typename T, qualifier Q> + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<L, bool, Q> notEqual(vec<L, T, Q> const& x, vec<L, T, Q> const& y, T Epsilon) + { + return notEqual(x, y, vec<L, T, Q>(Epsilon)); + } + + template<length_t L, typename T, qualifier Q> + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<L, bool, Q> notEqual(vec<L, T, Q> const& x, vec<L, T, Q> const& y, vec<L, T, Q> const& Epsilon) + { + return greaterThan(abs(x - y), Epsilon); + } + + + template<length_t L, typename T, qualifier Q> + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<L, bool, Q> equal(vec<L, T, Q> const& x, vec<L, T, Q> const& y, int MaxULPs) + { + return equal(x, y, vec<L, int, Q>(MaxULPs)); + } + + template<length_t L, typename T, qualifier Q> + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<L, bool, Q> equal(vec<L, T, Q> const& x, vec<L, T, Q> const& y, vec<L, int, Q> const& MaxULPs) + { + vec<L, bool, Q> Result(false); + for(length_t i = 0; i < L; ++i) + { + detail::float_t<T> const a(x[i]); + detail::float_t<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<T>::int_type const DiffULPs = abs(a.i - b.i); + Result[i] = DiffULPs <= MaxULPs[i]; + } + } + return Result; + } + + template<length_t L, typename T, qualifier Q> + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<L, bool, Q> notEqual(vec<L, T, Q> const& x, vec<L, T, Q> const& y, int MaxULPs) + { + return notEqual(x, y, vec<L, int, Q>(MaxULPs)); + } + + template<length_t L, typename T, qualifier Q> + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<L, bool, Q> notEqual(vec<L, T, Q> const& x, vec<L, T, Q> const& y, vec<L, int, Q> 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 0000000000000000000000000000000000000000..eb8a7049761f0bb7c735ba689faac84ea5eb65d8 --- /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 <glm/ext/vector_uvec1.hpp> 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 0000000000000000000000000000000000000000..2a938bbaf61662b648c0886565911eff4a51a9ef --- /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 <glm/ext/vector_uint1_sized.hpp> 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 0000000000000000000000000000000000000000..03c00f5ff584d48baf6aab0ed8c5a794138f3219 --- /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 <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 4.1.5 Vectors</a> + 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 0000000000000000000000000000000000000000..620fdc6ece39396568745882180d89d4d3391acb --- /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 <glm/ext/vector_uint2_sized.hpp> 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 0000000000000000000000000000000000000000..f5b41c40882ac5fda0c1440956c8bcd8f7c098d4 --- /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 <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 4.1.5 Vectors</a> + 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 0000000000000000000000000000000000000000..6f96b98e276fb10a896ad9ff42e1df0455b07997 --- /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 <glm/ext/vector_uint3_sized.hpp> 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 0000000000000000000000000000000000000000..32ced58a8f03f902acae6e0fd0e79a0efdb0653a --- /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 <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 4.1.5 Vectors</a> + 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 0000000000000000000000000000000000000000..da992ea2da86ad2c15ab834dd0acf6fa19fd19e3 --- /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 <glm/ext/vector_uint4_sized.hpp> 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 0000000000000000000000000000000000000000..6210396b87f30013069f4313ef49286ab2134f8e --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/ext/vector_ulp.hpp @@ -0,0 +1,109 @@ +/// @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 <glm/ext/vector_ulp.hpp> 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 +{ + /// 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<length_t L, typename T, qualifier Q> + GLM_FUNC_DECL vec<L, T, Q> nextFloat(vec<L, T, Q> 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<length_t L, typename T, qualifier Q> + GLM_FUNC_DECL vec<L, T, Q> nextFloat(vec<L, T, Q> 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<length_t L, typename T, qualifier Q> + GLM_FUNC_DECL vec<L, T, Q> nextFloat(vec<L, T, Q> const& x, vec<L, int, Q> 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<length_t L, typename T, qualifier Q> + GLM_FUNC_DECL vec<L, T, Q> prevFloat(vec<L, T, Q> 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<length_t L, typename T, qualifier Q> + GLM_FUNC_DECL vec<L, T, Q> prevFloat(vec<L, T, Q> 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<length_t L, typename T, qualifier Q> + GLM_FUNC_DECL vec<L, T, Q> prevFloat(vec<L, T, Q> const& x, vec<L, int, Q> 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<length_t L, typename T, qualifier Q> + GLM_FUNC_DECL vec<L, int, Q> floatDistance(vec<L, float, Q> const& x, vec<L, float, Q> 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<length_t L, typename T, qualifier Q> + GLM_FUNC_DECL vec<L, int64, Q> floatDistance(vec<L, double, Q> const& x, vec<L, double, Q> 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 0000000000000000000000000000000000000000..91565ce510742bfd98b470976fae19d60c3f2947 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/ext/vector_ulp.inl @@ -0,0 +1,74 @@ +namespace glm +{ + template<length_t L, typename T, qualifier Q> + GLM_FUNC_QUALIFIER vec<L, T, Q> nextFloat(vec<L, T, Q> const& x) + { + vec<L, T, Q> Result; + for(length_t i = 0, n = Result.length(); i < n; ++i) + Result[i] = nextFloat(x[i]); + return Result; + } + + template<length_t L, typename T, qualifier Q> + GLM_FUNC_QUALIFIER vec<L, T, Q> nextFloat(vec<L, T, Q> const& x, int ULPs) + { + vec<L, T, Q> Result; + for(length_t i = 0, n = Result.length(); i < n; ++i) + Result[i] = nextFloat(x[i], ULPs); + return Result; + } + + template<length_t L, typename T, qualifier Q> + GLM_FUNC_QUALIFIER vec<L, T, Q> nextFloat(vec<L, T, Q> const& x, vec<L, int, Q> const& ULPs) + { + vec<L, T, Q> Result; + for(length_t i = 0, n = Result.length(); i < n; ++i) + Result[i] = nextFloat(x[i], ULPs[i]); + return Result; + } + + template<length_t L, typename T, qualifier Q> + GLM_FUNC_QUALIFIER vec<L, T, Q> prevFloat(vec<L, T, Q> const& x) + { + vec<L, T, Q> Result; + for(length_t i = 0, n = Result.length(); i < n; ++i) + Result[i] = prevFloat(x[i]); + return Result; + } + + template<length_t L, typename T, qualifier Q> + GLM_FUNC_QUALIFIER vec<L, T, Q> prevFloat(vec<L, T, Q> const& x, int ULPs) + { + vec<L, T, Q> Result; + for(length_t i = 0, n = Result.length(); i < n; ++i) + Result[i] = prevFloat(x[i], ULPs); + return Result; + } + + template<length_t L, typename T, qualifier Q> + GLM_FUNC_QUALIFIER vec<L, T, Q> prevFloat(vec<L, T, Q> const& x, vec<L, int, Q> const& ULPs) + { + vec<L, T, Q> Result; + for(length_t i = 0, n = Result.length(); i < n; ++i) + Result[i] = prevFloat(x[i], ULPs[i]); + return Result; + } + + template<length_t L, qualifier Q> + GLM_FUNC_QUALIFIER vec<L, int, Q> floatDistance(vec<L, float, Q> const& x, vec<L, float, Q> const& y) + { + vec<L, int, Q> Result; + for(length_t i = 0, n = Result.length(); i < n; ++i) + Result[i] = floatDistance(x[i], y[i]); + return Result; + } + + template<length_t L, qualifier Q> + GLM_FUNC_QUALIFIER vec<L, int64, Q> floatDistance(vec<L, double, Q> const& x, vec<L, double, Q> const& y) + { + vec<L, int64, Q> Result; + 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 0000000000000000000000000000000000000000..89177f46ca797b26f78ddef746426de527f649db --- /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<3, 2, f32, defaultp> mat3x2; + typedef mat<4, 2, f32, defaultp> mat4x2; + typedef mat<2, 3, f32, defaultp> mat2x3; + typedef mat<3, 3, f32, defaultp> mat3x3; + typedef mat<4, 3, f32, defaultp> mat4x3; + typedef mat<2, 4, f32, defaultp> mat2x4; + typedef mat<3, 4, f32, defaultp> mat3x4; + 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<3, 2, f32, defaultp> fmat3x2; + typedef mat<4, 2, f32, defaultp> fmat4x2; + typedef mat<2, 3, f32, defaultp> fmat2x3; + typedef mat<3, 3, f32, defaultp> fmat3x3; + typedef mat<4, 3, f32, defaultp> fmat4x3; + typedef mat<2, 4, f32, defaultp> fmat2x4; + typedef mat<3, 4, f32, defaultp> fmat3x4; + 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<3, 2, f32, defaultp> f32mat3x2; + typedef mat<4, 2, f32, defaultp> f32mat4x2; + typedef mat<2, 3, f32, defaultp> f32mat2x3; + typedef mat<3, 3, f32, defaultp> f32mat3x3; + typedef mat<4, 3, f32, defaultp> f32mat4x3; + typedef mat<2, 4, f32, defaultp> f32mat2x4; + typedef mat<3, 4, f32, defaultp> f32mat3x4; + 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<3, 2, double, defaultp> dmat3x2; + typedef mat<4, 2, double, defaultp> dmat4x2; + typedef mat<2, 3, double, defaultp> dmat2x3; + typedef mat<3, 3, double, defaultp> dmat3x3; + typedef mat<4, 3, double, defaultp> dmat4x3; + typedef mat<2, 4, double, defaultp> dmat2x4; + typedef mat<3, 4, double, defaultp> dmat3x4; + 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<3, 2, f64, defaultp> f64mat3x2; + typedef mat<4, 2, f64, defaultp> f64mat4x2; + typedef mat<2, 3, f64, defaultp> f64mat2x3; + typedef mat<3, 3, f64, defaultp> f64mat3x3; + typedef mat<4, 3, f64, defaultp> f64mat4x3; + typedef mat<2, 4, f64, defaultp> f64mat2x4; + typedef mat<3, 4, f64, defaultp> f64mat3x4; + 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<3, 2, int, defaultp> imat3x2; + typedef mat<4, 2, int, defaultp> imat4x2; + typedef mat<2, 3, int, defaultp> imat2x3; + typedef mat<3, 3, int, defaultp> imat3x3; + typedef mat<4, 3, int, defaultp> imat4x3; + typedef mat<2, 4, int, defaultp> imat2x4; + typedef mat<3, 4, int, defaultp> imat3x4; + 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<3, 2, int8, defaultp> i8mat3x2; + typedef mat<4, 2, int8, defaultp> i8mat4x2; + typedef mat<2, 3, int8, defaultp> i8mat2x3; + typedef mat<3, 3, int8, defaultp> i8mat3x3; + typedef mat<4, 3, int8, defaultp> i8mat4x3; + typedef mat<2, 4, int8, defaultp> i8mat2x4; + typedef mat<3, 4, int8, defaultp> i8mat3x4; + 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<3, 2, int16, defaultp> i16mat3x2; + typedef mat<4, 2, int16, defaultp> i16mat4x2; + typedef mat<2, 3, int16, defaultp> i16mat2x3; + typedef mat<3, 3, int16, defaultp> i16mat3x3; + typedef mat<4, 3, int16, defaultp> i16mat4x3; + typedef mat<2, 4, int16, defaultp> i16mat2x4; + typedef mat<3, 4, int16, defaultp> i16mat3x4; + 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<3, 2, int32, defaultp> i32mat3x2; + typedef mat<4, 2, int32, defaultp> i32mat4x2; + typedef mat<2, 3, int32, defaultp> i32mat2x3; + typedef mat<3, 3, int32, defaultp> i32mat3x3; + typedef mat<4, 3, int32, defaultp> i32mat4x3; + typedef mat<2, 4, int32, defaultp> i32mat2x4; + typedef mat<3, 4, int32, defaultp> i32mat3x4; + 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<3, 2, int64, defaultp> i64mat3x2; + typedef mat<4, 2, int64, defaultp> i64mat4x2; + typedef mat<2, 3, int64, defaultp> i64mat2x3; + typedef mat<3, 3, int64, defaultp> i64mat3x3; + typedef mat<4, 3, int64, defaultp> i64mat4x3; + typedef mat<2, 4, int64, defaultp> i64mat2x4; + typedef mat<3, 4, int64, defaultp> i64mat3x4; + 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<3, 2, uint, defaultp> umat3x2; + typedef mat<4, 2, uint, defaultp> umat4x2; + typedef mat<2, 3, uint, defaultp> umat2x3; + typedef mat<3, 3, uint, defaultp> umat3x3; + typedef mat<4, 3, uint, defaultp> umat4x3; + typedef mat<2, 4, uint, defaultp> umat2x4; + typedef mat<3, 4, uint, defaultp> umat3x4; + 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<3, 2, uint8, defaultp> u8mat3x2; + typedef mat<4, 2, uint8, defaultp> u8mat4x2; + typedef mat<2, 3, uint8, defaultp> u8mat2x3; + typedef mat<3, 3, uint8, defaultp> u8mat3x3; + typedef mat<4, 3, uint8, defaultp> u8mat4x3; + typedef mat<2, 4, uint8, defaultp> u8mat2x4; + typedef mat<3, 4, uint8, defaultp> u8mat3x4; + 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<3, 2, uint16, defaultp> u16mat3x2; + typedef mat<4, 2, uint16, defaultp> u16mat4x2; + typedef mat<2, 3, uint16, defaultp> u16mat2x3; + typedef mat<3, 3, uint16, defaultp> u16mat3x3; + typedef mat<4, 3, uint16, defaultp> u16mat4x3; + typedef mat<2, 4, uint16, defaultp> u16mat2x4; + typedef mat<3, 4, uint16, defaultp> u16mat3x4; + 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<3, 2, uint32, defaultp> u32mat3x2; + typedef mat<4, 2, uint32, defaultp> u32mat4x2; + typedef mat<2, 3, uint32, defaultp> u32mat2x3; + typedef mat<3, 3, uint32, defaultp> u32mat3x3; + typedef mat<4, 3, uint32, defaultp> u32mat4x3; + typedef mat<2, 4, uint32, defaultp> u32mat2x4; + typedef mat<3, 4, uint32, defaultp> u32mat3x4; + 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<3, 2, uint64, defaultp> u64mat3x2; + typedef mat<4, 2, uint64, defaultp> u64mat4x2; + typedef mat<2, 3, uint64, defaultp> u64mat2x3; + typedef mat<3, 3, uint64, defaultp> u64mat3x3; + typedef mat<4, 3, uint64, defaultp> u64mat4x3; + typedef mat<2, 4, uint64, defaultp> u64mat2x4; + typedef mat<3, 4, uint64, defaultp> u64mat3x4; + typedef mat<4, 4, uint64, defaultp> u64mat4x4; + + // Quaternion + + typedef qua<float, lowp> lowp_quat; + typedef qua<float, mediump> mediump_quat; + typedef qua<float, highp> highp_quat; + typedef qua<float, defaultp> quat; + + typedef qua<float, lowp> lowp_fquat; + typedef qua<float, mediump> mediump_fquat; + typedef qua<float, highp> highp_fquat; + typedef qua<float, defaultp> fquat; + + typedef qua<f32, lowp> lowp_f32quat; + typedef qua<f32, mediump> mediump_f32quat; + typedef qua<f32, highp> highp_f32quat; + typedef qua<f32, defaultp> f32quat; + + typedef qua<double, lowp> lowp_dquat; + typedef qua<double, mediump> mediump_dquat; + typedef qua<double, highp> highp_dquat; + typedef qua<double, defaultp> dquat; + + typedef qua<f64, lowp> lowp_f64quat; + typedef qua<f64, mediump> mediump_f64quat; + typedef qua<f64, highp> highp_f64quat; + typedef qua<f64, defaultp> 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 0000000000000000000000000000000000000000..c068a3cbdb58b2b3826f4924de6420936527cbae --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/geometric.hpp @@ -0,0 +1,116 @@ +/// @ref core +/// @file glm/geometric.hpp +/// +/// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 8.5 Geometric Functions</a> +/// +/// @defgroup core_func_geometric Geometric functions +/// @ingroup core +/// +/// These operate on vectors as vectors, not component-wise. +/// +/// Include <glm/geometric.hpp> 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 <a href="http://www.opengl.org/sdk/docs/manglsl/xhtml/length.xml">GLSL length man page</a> + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 8.5 Geometric Functions</a> + template<length_t L, typename T, qualifier Q> + GLM_FUNC_DECL T length(vec<L, T, Q> const& x); + + /// Returns the distance betwwen 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 <a href="http://www.opengl.org/sdk/docs/manglsl/xhtml/distance.xml">GLSL distance man page</a> + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 8.5 Geometric Functions</a> + template<length_t L, typename T, qualifier Q> + GLM_FUNC_DECL T distance(vec<L, T, Q> const& p0, vec<L, T, Q> 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 <a href="http://www.opengl.org/sdk/docs/manglsl/xhtml/dot.xml">GLSL dot man page</a> + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 8.5 Geometric Functions</a> + template<length_t L, typename T, qualifier Q> + GLM_FUNC_DECL T dot(vec<L, T, Q> const& x, vec<L, T, Q> const& y); + + /// Returns the cross product of x and y. + /// + /// @tparam T Floating-point scalar types. + /// + /// @see <a href="http://www.opengl.org/sdk/docs/manglsl/xhtml/cross.xml">GLSL cross man page</a> + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 8.5 Geometric Functions</a> + template<typename T, qualifier Q> + GLM_FUNC_DECL 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 <a href="http://www.opengl.org/sdk/docs/manglsl/xhtml/normalize.xml">GLSL normalize man page</a> + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 8.5 Geometric Functions</a> + template<length_t L, typename T, qualifier Q> + GLM_FUNC_DECL vec<L, T, Q> normalize(vec<L, T, Q> 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 <a href="http://www.opengl.org/sdk/docs/manglsl/xhtml/faceforward.xml">GLSL faceforward man page</a> + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 8.5 Geometric Functions</a> + template<length_t L, typename T, qualifier Q> + GLM_FUNC_DECL vec<L, T, Q> faceforward( + vec<L, T, Q> const& N, + vec<L, T, Q> const& I, + vec<L, T, Q> 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 <a href="http://www.opengl.org/sdk/docs/manglsl/xhtml/reflect.xml">GLSL reflect man page</a> + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 8.5 Geometric Functions</a> + template<length_t L, typename T, qualifier Q> + GLM_FUNC_DECL vec<L, T, Q> reflect( + vec<L, T, Q> const& I, + vec<L, T, Q> 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 <a href="http://www.opengl.org/sdk/docs/manglsl/xhtml/refract.xml">GLSL refract man page</a> + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 8.5 Geometric Functions</a> + template<length_t L, typename T, qualifier Q> + GLM_FUNC_DECL vec<L, T, Q> refract( + vec<L, T, Q> const& I, + vec<L, T, Q> const& N, + T eta); + + /// @} +}//namespace glm + +#include "detail/func_geometric.inl" 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 0000000000000000000000000000000000000000..8b61064968032e6ef56a0f7e572b4b1abc5976c7 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/glm.hpp @@ -0,0 +1,136 @@ +/// @ref core +/// @file glm/glm.hpp +/// +/// @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, +/// <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.clean.pdf">version 4.2 +/// (pdf file)</a>. +/// +/// GLM core functionalities require <glm/glm.hpp> 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 <glm/ext.hpp>. 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 <glm/ext.hpp>. 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 <glm/ext.hpp>. Otherwise, each extension needs to be +/// included a specific file. +/// +/// @mainpage OpenGL Mathematics (GLM) +/// - Website: <a href="https://glm.g-truc.net">glm.g-truc.net</a> +/// - <a href="modules.html">GLM API documentation</a> +/// - <a href="https://github.com/g-truc/glm/blob/master/manual.md">GLM Manual</a> + +#include "detail/_fixes.hpp" + +#include "detail/setup.hpp" + +#pragma once + +#include <cmath> +#include <climits> +#include <cfloat> +#include <limits> +#include <cassert> +#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 0000000000000000000000000000000000000000..084fbe75ff144c36e700d9f800fdfba6a0106c30 --- /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 <glm/gtc/bitfield.hpp> 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 <limits> + +#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<typename genIUType> + 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<length_t L, typename T, qualifier Q> + GLM_FUNC_DECL vec<L, T, Q> mask(vec<L, T, Q> 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<typename genIUType> + 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<length_t L, typename T, qualifier Q> + GLM_FUNC_DECL vec<L, T, Q> bitfieldRotateRight(vec<L, T, Q> 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<typename genIUType> + 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<length_t L, typename T, qualifier Q> + GLM_FUNC_DECL vec<L, T, Q> bitfieldRotateLeft(vec<L, T, Q> const& In, int Shift); + + /// Set to 1 a range of bits. + /// + /// @see gtc_bitfield + template<typename genIUType> + 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<length_t L, typename T, qualifier Q> + GLM_FUNC_DECL vec<L, T, Q> bitfieldFillOne(vec<L, T, Q> const& Value, int FirstBit, int BitCount); + + /// Set to 0 a range of bits. + /// + /// @see gtc_bitfield + template<typename genIUType> + 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<length_t L, typename T, qualifier Q> + GLM_FUNC_DECL vec<L, T, Q> bitfieldFillZero(vec<L, T, Q> 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 0000000000000000000000000000000000000000..06cf1889cd40b366882a1f408c8c7ca40da5b680 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/gtc/bitfield.inl @@ -0,0 +1,626 @@ +/// @ref gtc_bitfield + +#include "../simd/integer.h" + +namespace glm{ +namespace detail +{ + template<typename PARAM, typename RET> + GLM_FUNC_DECL RET bitfieldInterleave(PARAM x, PARAM y); + + template<typename PARAM, typename RET> + GLM_FUNC_DECL RET bitfieldInterleave(PARAM x, PARAM y, PARAM z); + + template<typename PARAM, typename RET> + 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<glm::uint16>(0x0F0F); + REG2 = ((REG2 << 4) | REG2) & static_cast<glm::uint16>(0x0F0F); + + REG1 = ((REG1 << 2) | REG1) & static_cast<glm::uint16>(0x3333); + REG2 = ((REG2 << 2) | REG2) & static_cast<glm::uint16>(0x3333); + + REG1 = ((REG1 << 1) | REG1) & static_cast<glm::uint16>(0x5555); + REG2 = ((REG2 << 1) | REG2) & static_cast<glm::uint16>(0x5555); + + return REG1 | static_cast<glm::uint16>(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<glm::uint32>(0x00FF00FF); + REG2 = ((REG2 << 8) | REG2) & static_cast<glm::uint32>(0x00FF00FF); + + REG1 = ((REG1 << 4) | REG1) & static_cast<glm::uint32>(0x0F0F0F0F); + REG2 = ((REG2 << 4) | REG2) & static_cast<glm::uint32>(0x0F0F0F0F); + + REG1 = ((REG1 << 2) | REG1) & static_cast<glm::uint32>(0x33333333); + REG2 = ((REG2 << 2) | REG2) & static_cast<glm::uint32>(0x33333333); + + REG1 = ((REG1 << 1) | REG1) & static_cast<glm::uint32>(0x55555555); + REG2 = ((REG2 << 1) | REG2) & static_cast<glm::uint32>(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<glm::uint64>(0x0000FFFF0000FFFFull); + REG2 = ((REG2 << 16) | REG2) & static_cast<glm::uint64>(0x0000FFFF0000FFFFull); + + REG1 = ((REG1 << 8) | REG1) & static_cast<glm::uint64>(0x00FF00FF00FF00FFull); + REG2 = ((REG2 << 8) | REG2) & static_cast<glm::uint64>(0x00FF00FF00FF00FFull); + + REG1 = ((REG1 << 4) | REG1) & static_cast<glm::uint64>(0x0F0F0F0F0F0F0F0Full); + REG2 = ((REG2 << 4) | REG2) & static_cast<glm::uint64>(0x0F0F0F0F0F0F0F0Full); + + REG1 = ((REG1 << 2) | REG1) & static_cast<glm::uint64>(0x3333333333333333ull); + REG2 = ((REG2 << 2) | REG2) & static_cast<glm::uint64>(0x3333333333333333ull); + + REG1 = ((REG1 << 1) | REG1) & static_cast<glm::uint64>(0x5555555555555555ull); + REG2 = ((REG2 << 1) | REG2) & static_cast<glm::uint64>(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<glm::uint32>(0xFF0000FFu); + REG2 = ((REG2 << 16) | REG2) & static_cast<glm::uint32>(0xFF0000FFu); + REG3 = ((REG3 << 16) | REG3) & static_cast<glm::uint32>(0xFF0000FFu); + + REG1 = ((REG1 << 8) | REG1) & static_cast<glm::uint32>(0x0F00F00Fu); + REG2 = ((REG2 << 8) | REG2) & static_cast<glm::uint32>(0x0F00F00Fu); + REG3 = ((REG3 << 8) | REG3) & static_cast<glm::uint32>(0x0F00F00Fu); + + REG1 = ((REG1 << 4) | REG1) & static_cast<glm::uint32>(0xC30C30C3u); + REG2 = ((REG2 << 4) | REG2) & static_cast<glm::uint32>(0xC30C30C3u); + REG3 = ((REG3 << 4) | REG3) & static_cast<glm::uint32>(0xC30C30C3u); + + REG1 = ((REG1 << 2) | REG1) & static_cast<glm::uint32>(0x49249249u); + REG2 = ((REG2 << 2) | REG2) & static_cast<glm::uint32>(0x49249249u); + REG3 = ((REG3 << 2) | REG3) & static_cast<glm::uint32>(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<glm::uint64>(0xFFFF00000000FFFFull); + REG2 = ((REG2 << 32) | REG2) & static_cast<glm::uint64>(0xFFFF00000000FFFFull); + REG3 = ((REG3 << 32) | REG3) & static_cast<glm::uint64>(0xFFFF00000000FFFFull); + + REG1 = ((REG1 << 16) | REG1) & static_cast<glm::uint64>(0x00FF0000FF0000FFull); + REG2 = ((REG2 << 16) | REG2) & static_cast<glm::uint64>(0x00FF0000FF0000FFull); + REG3 = ((REG3 << 16) | REG3) & static_cast<glm::uint64>(0x00FF0000FF0000FFull); + + REG1 = ((REG1 << 8) | REG1) & static_cast<glm::uint64>(0xF00F00F00F00F00Full); + REG2 = ((REG2 << 8) | REG2) & static_cast<glm::uint64>(0xF00F00F00F00F00Full); + REG3 = ((REG3 << 8) | REG3) & static_cast<glm::uint64>(0xF00F00F00F00F00Full); + + REG1 = ((REG1 << 4) | REG1) & static_cast<glm::uint64>(0x30C30C30C30C30C3ull); + REG2 = ((REG2 << 4) | REG2) & static_cast<glm::uint64>(0x30C30C30C30C30C3ull); + REG3 = ((REG3 << 4) | REG3) & static_cast<glm::uint64>(0x30C30C30C30C30C3ull); + + REG1 = ((REG1 << 2) | REG1) & static_cast<glm::uint64>(0x9249249249249249ull); + REG2 = ((REG2 << 2) | REG2) & static_cast<glm::uint64>(0x9249249249249249ull); + REG3 = ((REG3 << 2) | REG3) & static_cast<glm::uint64>(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<glm::uint64>(0xFFFF00000000FFFFull); + REG2 = ((REG2 << 32) | REG2) & static_cast<glm::uint64>(0xFFFF00000000FFFFull); + REG3 = ((REG3 << 32) | REG3) & static_cast<glm::uint64>(0xFFFF00000000FFFFull); + + REG1 = ((REG1 << 16) | REG1) & static_cast<glm::uint64>(0x00FF0000FF0000FFull); + REG2 = ((REG2 << 16) | REG2) & static_cast<glm::uint64>(0x00FF0000FF0000FFull); + REG3 = ((REG3 << 16) | REG3) & static_cast<glm::uint64>(0x00FF0000FF0000FFull); + + REG1 = ((REG1 << 8) | REG1) & static_cast<glm::uint64>(0xF00F00F00F00F00Full); + REG2 = ((REG2 << 8) | REG2) & static_cast<glm::uint64>(0xF00F00F00F00F00Full); + REG3 = ((REG3 << 8) | REG3) & static_cast<glm::uint64>(0xF00F00F00F00F00Full); + + REG1 = ((REG1 << 4) | REG1) & static_cast<glm::uint64>(0x30C30C30C30C30C3ull); + REG2 = ((REG2 << 4) | REG2) & static_cast<glm::uint64>(0x30C30C30C30C30C3ull); + REG3 = ((REG3 << 4) | REG3) & static_cast<glm::uint64>(0x30C30C30C30C30C3ull); + + REG1 = ((REG1 << 2) | REG1) & static_cast<glm::uint64>(0x9249249249249249ull); + REG2 = ((REG2 << 2) | REG2) & static_cast<glm::uint64>(0x9249249249249249ull); + REG3 = ((REG3 << 2) | REG3) & static_cast<glm::uint64>(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<glm::uint32>(0x000F000Fu); + REG2 = ((REG2 << 12) | REG2) & static_cast<glm::uint32>(0x000F000Fu); + REG3 = ((REG3 << 12) | REG3) & static_cast<glm::uint32>(0x000F000Fu); + REG4 = ((REG4 << 12) | REG4) & static_cast<glm::uint32>(0x000F000Fu); + + REG1 = ((REG1 << 6) | REG1) & static_cast<glm::uint32>(0x03030303u); + REG2 = ((REG2 << 6) | REG2) & static_cast<glm::uint32>(0x03030303u); + REG3 = ((REG3 << 6) | REG3) & static_cast<glm::uint32>(0x03030303u); + REG4 = ((REG4 << 6) | REG4) & static_cast<glm::uint32>(0x03030303u); + + REG1 = ((REG1 << 3) | REG1) & static_cast<glm::uint32>(0x11111111u); + REG2 = ((REG2 << 3) | REG2) & static_cast<glm::uint32>(0x11111111u); + REG3 = ((REG3 << 3) | REG3) & static_cast<glm::uint32>(0x11111111u); + REG4 = ((REG4 << 3) | REG4) & static_cast<glm::uint32>(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<glm::uint64>(0x000000FF000000FFull); + REG2 = ((REG2 << 24) | REG2) & static_cast<glm::uint64>(0x000000FF000000FFull); + REG3 = ((REG3 << 24) | REG3) & static_cast<glm::uint64>(0x000000FF000000FFull); + REG4 = ((REG4 << 24) | REG4) & static_cast<glm::uint64>(0x000000FF000000FFull); + + REG1 = ((REG1 << 12) | REG1) & static_cast<glm::uint64>(0x000F000F000F000Full); + REG2 = ((REG2 << 12) | REG2) & static_cast<glm::uint64>(0x000F000F000F000Full); + REG3 = ((REG3 << 12) | REG3) & static_cast<glm::uint64>(0x000F000F000F000Full); + REG4 = ((REG4 << 12) | REG4) & static_cast<glm::uint64>(0x000F000F000F000Full); + + REG1 = ((REG1 << 6) | REG1) & static_cast<glm::uint64>(0x0303030303030303ull); + REG2 = ((REG2 << 6) | REG2) & static_cast<glm::uint64>(0x0303030303030303ull); + REG3 = ((REG3 << 6) | REG3) & static_cast<glm::uint64>(0x0303030303030303ull); + REG4 = ((REG4 << 6) | REG4) & static_cast<glm::uint64>(0x0303030303030303ull); + + REG1 = ((REG1 << 3) | REG1) & static_cast<glm::uint64>(0x1111111111111111ull); + REG2 = ((REG2 << 3) | REG2) & static_cast<glm::uint64>(0x1111111111111111ull); + REG3 = ((REG3 << 3) | REG3) & static_cast<glm::uint64>(0x1111111111111111ull); + REG4 = ((REG4 << 3) | REG4) & static_cast<glm::uint64>(0x1111111111111111ull); + + return REG1 | (REG2 << 1) | (REG3 << 2) | (REG4 << 3); + } +}//namespace detail + + template<typename genIUType> + GLM_FUNC_QUALIFIER genIUType mask(genIUType Bits) + { + GLM_STATIC_ASSERT(std::numeric_limits<genIUType>::is_integer, "'mask' accepts only integer values"); + + return Bits >= sizeof(genIUType) * 8 ? ~static_cast<genIUType>(0) : (static_cast<genIUType>(1) << Bits) - static_cast<genIUType>(1); + } + + template<length_t L, typename T, qualifier Q> + GLM_FUNC_QUALIFIER vec<L, T, Q> mask(vec<L, T, Q> const& v) + { + GLM_STATIC_ASSERT(std::numeric_limits<T>::is_integer, "'mask' accepts only integer values"); + + return detail::functor1<vec, L, T, T, Q>::call(mask, v); + } + + template<typename genIType> + GLM_FUNC_QUALIFIER genIType bitfieldRotateRight(genIType In, int Shift) + { + GLM_STATIC_ASSERT(std::numeric_limits<genIType>::is_integer, "'bitfieldRotateRight' accepts only integer values"); + + int const BitSize = static_cast<genIType>(sizeof(genIType) * 8); + return (In << static_cast<genIType>(Shift)) | (In >> static_cast<genIType>(BitSize - Shift)); + } + + template<length_t L, typename T, qualifier Q> + GLM_FUNC_QUALIFIER vec<L, T, Q> bitfieldRotateRight(vec<L, T, Q> const& In, int Shift) + { + GLM_STATIC_ASSERT(std::numeric_limits<T>::is_integer, "'bitfieldRotateRight' accepts only integer values"); + + int const BitSize = static_cast<int>(sizeof(T) * 8); + return (In << static_cast<T>(Shift)) | (In >> static_cast<T>(BitSize - Shift)); + } + + template<typename genIType> + GLM_FUNC_QUALIFIER genIType bitfieldRotateLeft(genIType In, int Shift) + { + GLM_STATIC_ASSERT(std::numeric_limits<genIType>::is_integer, "'bitfieldRotateLeft' accepts only integer values"); + + int const BitSize = static_cast<genIType>(sizeof(genIType) * 8); + return (In >> static_cast<genIType>(Shift)) | (In << static_cast<genIType>(BitSize - Shift)); + } + + template<length_t L, typename T, qualifier Q> + GLM_FUNC_QUALIFIER vec<L, T, Q> bitfieldRotateLeft(vec<L, T, Q> const& In, int Shift) + { + GLM_STATIC_ASSERT(std::numeric_limits<T>::is_integer, "'bitfieldRotateLeft' accepts only integer values"); + + int const BitSize = static_cast<int>(sizeof(T) * 8); + return (In >> static_cast<T>(Shift)) | (In << static_cast<T>(BitSize - Shift)); + } + + template<typename genIUType> + GLM_FUNC_QUALIFIER genIUType bitfieldFillOne(genIUType Value, int FirstBit, int BitCount) + { + return Value | static_cast<genIUType>(mask(BitCount) << FirstBit); + } + + template<length_t L, typename T, qualifier Q> + GLM_FUNC_QUALIFIER vec<L, T, Q> bitfieldFillOne(vec<L, T, Q> const& Value, int FirstBit, int BitCount) + { + return Value | static_cast<T>(mask(BitCount) << FirstBit); + } + + template<typename genIUType> + GLM_FUNC_QUALIFIER genIUType bitfieldFillZero(genIUType Value, int FirstBit, int BitCount) + { + return Value & static_cast<genIUType>(~(mask(BitCount) << FirstBit)); + } + + template<length_t L, typename T, qualifier Q> + GLM_FUNC_QUALIFIER vec<L, T, Q> bitfieldFillZero(vec<L, T, Q> const& Value, int FirstBit, int BitCount) + { + return Value & static_cast<T>(~(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<uint8, uint16>(x, y); + } + + GLM_FUNC_QUALIFIER uint16 bitfieldInterleave(u8vec2 const& v) + { + return detail::bitfieldInterleave<uint8, uint16>(v.x, v.y); + } + + GLM_FUNC_QUALIFIER u8vec2 bitfieldDeinterleave(glm::uint16 x) + { + uint16 REG1(x); + uint16 REG2(x >>= 1); + + REG1 = REG1 & static_cast<uint16>(0x5555); + REG2 = REG2 & static_cast<uint16>(0x5555); + + REG1 = ((REG1 >> 1) | REG1) & static_cast<uint16>(0x3333); + REG2 = ((REG2 >> 1) | REG2) & static_cast<uint16>(0x3333); + + REG1 = ((REG1 >> 2) | REG1) & static_cast<uint16>(0x0F0F); + REG2 = ((REG2 >> 2) | REG2) & static_cast<uint16>(0x0F0F); + + REG1 = ((REG1 >> 4) | REG1) & static_cast<uint16>(0x00FF); + REG2 = ((REG2 >> 4) | REG2) & static_cast<uint16>(0x00FF); + + REG1 = ((REG1 >> 8) | REG1) & static_cast<uint16>(0xFFFF); + REG2 = ((REG2 >> 8) | REG2) & static_cast<uint16>(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<uint16, uint32>(x, y); + } + + GLM_FUNC_QUALIFIER glm::uint32 bitfieldInterleave(u16vec2 const& v) + { + return detail::bitfieldInterleave<uint16, uint32>(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<glm::uint32>(0x55555555); + REG2 = REG2 & static_cast<glm::uint32>(0x55555555); + + REG1 = ((REG1 >> 1) | REG1) & static_cast<glm::uint32>(0x33333333); + REG2 = ((REG2 >> 1) | REG2) & static_cast<glm::uint32>(0x33333333); + + REG1 = ((REG1 >> 2) | REG1) & static_cast<glm::uint32>(0x0F0F0F0F); + REG2 = ((REG2 >> 2) | REG2) & static_cast<glm::uint32>(0x0F0F0F0F); + + REG1 = ((REG1 >> 4) | REG1) & static_cast<glm::uint32>(0x00FF00FF); + REG2 = ((REG2 >> 4) | REG2) & static_cast<glm::uint32>(0x00FF00FF); + + REG1 = ((REG1 >> 8) | REG1) & static_cast<glm::uint32>(0x0000FFFF); + REG2 = ((REG2 >> 8) | REG2) & static_cast<glm::uint32>(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<uint32, uint64>(x, y); + } + + GLM_FUNC_QUALIFIER glm::uint64 bitfieldInterleave(u32vec2 const& v) + { + return detail::bitfieldInterleave<uint32, uint64>(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<glm::uint64>(0x5555555555555555ull); + REG2 = REG2 & static_cast<glm::uint64>(0x5555555555555555ull); + + REG1 = ((REG1 >> 1) | REG1) & static_cast<glm::uint64>(0x3333333333333333ull); + REG2 = ((REG2 >> 1) | REG2) & static_cast<glm::uint64>(0x3333333333333333ull); + + REG1 = ((REG1 >> 2) | REG1) & static_cast<glm::uint64>(0x0F0F0F0F0F0F0F0Full); + REG2 = ((REG2 >> 2) | REG2) & static_cast<glm::uint64>(0x0F0F0F0F0F0F0F0Full); + + REG1 = ((REG1 >> 4) | REG1) & static_cast<glm::uint64>(0x00FF00FF00FF00FFull); + REG2 = ((REG2 >> 4) | REG2) & static_cast<glm::uint64>(0x00FF00FF00FF00FFull); + + REG1 = ((REG1 >> 8) | REG1) & static_cast<glm::uint64>(0x0000FFFF0000FFFFull); + REG2 = ((REG2 >> 8) | REG2) & static_cast<glm::uint64>(0x0000FFFF0000FFFFull); + + REG1 = ((REG1 >> 16) | REG1) & static_cast<glm::uint64>(0x00000000FFFFFFFFull); + REG2 = ((REG2 >> 16) | REG2) & static_cast<glm::uint64>(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<uint8, uint32>(x, y, z); + } + + GLM_FUNC_QUALIFIER uint32 bitfieldInterleave(u8vec3 const& v) + { + return detail::bitfieldInterleave<uint8, uint32>(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<uint32, uint64>(x, y, z); + } + + GLM_FUNC_QUALIFIER uint64 bitfieldInterleave(u16vec3 const& v) + { + return detail::bitfieldInterleave<uint32, uint64>(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<uint32, uint64>(x, y, z); + } + + GLM_FUNC_QUALIFIER uint64 bitfieldInterleave(u32vec3 const& v) + { + return detail::bitfieldInterleave<uint32, uint64>(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<uint8, uint32>(x, y, z, w); + } + + GLM_FUNC_QUALIFIER uint32 bitfieldInterleave(u8vec4 const& v) + { + return detail::bitfieldInterleave<uint8, uint32>(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<uint16, uint64>(x, y, z, w); + } + + GLM_FUNC_QUALIFIER uint64 bitfieldInterleave(u16vec4 const& v) + { + return detail::bitfieldInterleave<uint16, uint64>(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 0000000000000000000000000000000000000000..cffd9f093fb953ed2f52ef5a427c8b889072d899 --- /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 <glm/gtc/color_space.hpp> 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 <limits> + +#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<length_t L, typename T, qualifier Q> + GLM_FUNC_DECL vec<L, T, Q> convertLinearToSRGB(vec<L, T, Q> 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<length_t L, typename T, qualifier Q> + GLM_FUNC_DECL vec<L, T, Q> convertLinearToSRGB(vec<L, T, Q> 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<length_t L, typename T, qualifier Q> + GLM_FUNC_DECL vec<L, T, Q> convertSRGBToLinear(vec<L, T, Q> 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<length_t L, typename T, qualifier Q> + GLM_FUNC_DECL vec<L, T, Q> convertSRGBToLinear(vec<L, T, Q> 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 0000000000000000000000000000000000000000..2a900044e99b7507e9921782684461acfbd6ab1f --- /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<length_t L, typename T, qualifier Q> + struct compute_rgbToSrgb + { + GLM_FUNC_QUALIFIER static vec<L, T, Q> call(vec<L, T, Q> const& ColorRGB, T GammaCorrection) + { + vec<L, T, Q> const ClampedColor(clamp(ColorRGB, static_cast<T>(0), static_cast<T>(1))); + + return mix( + pow(ClampedColor, vec<L, T, Q>(GammaCorrection)) * static_cast<T>(1.055) - static_cast<T>(0.055), + ClampedColor * static_cast<T>(12.92), + lessThan(ClampedColor, vec<L, T, Q>(static_cast<T>(0.0031308)))); + } + }; + + template<typename T, qualifier Q> + 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<length_t L, typename T, qualifier Q> + struct compute_srgbToRgb + { + GLM_FUNC_QUALIFIER static vec<L, T, Q> call(vec<L, T, Q> const& ColorSRGB, T Gamma) + { + return mix( + pow((ColorSRGB + static_cast<T>(0.055)) * static_cast<T>(0.94786729857819905213270142180095), vec<L, T, Q>(Gamma)), + ColorSRGB * static_cast<T>(0.07739938080495356037151702786378), + lessThanEqual(ColorSRGB, vec<L, T, Q>(static_cast<T>(0.04045)))); + } + }; + + template<typename T, qualifier Q> + 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<length_t L, typename T, qualifier Q> + GLM_FUNC_QUALIFIER vec<L, T, Q> convertLinearToSRGB(vec<L, T, Q> const& ColorLinear) + { + return detail::compute_rgbToSrgb<L, T, Q>::call(ColorLinear, static_cast<T>(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<length_t L, typename T, qualifier Q> + GLM_FUNC_QUALIFIER vec<L, T, Q> convertLinearToSRGB(vec<L, T, Q> const& ColorLinear, T Gamma) + { + return detail::compute_rgbToSrgb<L, T, Q>::call(ColorLinear, static_cast<T>(1) / Gamma); + } + + template<length_t L, typename T, qualifier Q> + GLM_FUNC_QUALIFIER vec<L, T, Q> convertSRGBToLinear(vec<L, T, Q> const& ColorSRGB) + { + return detail::compute_srgbToRgb<L, T, Q>::call(ColorSRGB, static_cast<T>(2.4)); + } + + template<length_t L, typename T, qualifier Q> + GLM_FUNC_QUALIFIER vec<L, T, Q> convertSRGBToLinear(vec<L, T, Q> const& ColorSRGB, T Gamma) + { + return detail::compute_srgbToRgb<L, T, Q>::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 0000000000000000000000000000000000000000..99f212869e0d753d10e0ccaebd51f681de1cce05 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/gtc/constants.hpp @@ -0,0 +1,165 @@ +/// @ref gtc_constants +/// @file glm/gtc/constants.hpp +/// +/// @see core (dependence) +/// +/// @defgroup gtc_constants GLM_GTC_constants +/// @ingroup gtc +/// +/// Include <glm/gtc/constants.hpp> 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<typename genType> + GLM_FUNC_DECL GLM_CONSTEXPR genType zero(); + + /// Return 1. + /// @see gtc_constants + template<typename genType> + GLM_FUNC_DECL GLM_CONSTEXPR genType one(); + + /// Return pi * 2. + /// @see gtc_constants + template<typename genType> + GLM_FUNC_DECL GLM_CONSTEXPR genType two_pi(); + + /// Return square root of pi. + /// @see gtc_constants + template<typename genType> + GLM_FUNC_DECL GLM_CONSTEXPR genType root_pi(); + + /// Return pi / 2. + /// @see gtc_constants + template<typename genType> + GLM_FUNC_DECL GLM_CONSTEXPR genType half_pi(); + + /// Return pi / 2 * 3. + /// @see gtc_constants + template<typename genType> + GLM_FUNC_DECL GLM_CONSTEXPR genType three_over_two_pi(); + + /// Return pi / 4. + /// @see gtc_constants + template<typename genType> + GLM_FUNC_DECL GLM_CONSTEXPR genType quarter_pi(); + + /// Return 1 / pi. + /// @see gtc_constants + template<typename genType> + GLM_FUNC_DECL GLM_CONSTEXPR genType one_over_pi(); + + /// Return 1 / (pi * 2). + /// @see gtc_constants + template<typename genType> + GLM_FUNC_DECL GLM_CONSTEXPR genType one_over_two_pi(); + + /// Return 2 / pi. + /// @see gtc_constants + template<typename genType> + GLM_FUNC_DECL GLM_CONSTEXPR genType two_over_pi(); + + /// Return 4 / pi. + /// @see gtc_constants + template<typename genType> + GLM_FUNC_DECL GLM_CONSTEXPR genType four_over_pi(); + + /// Return 2 / sqrt(pi). + /// @see gtc_constants + template<typename genType> + GLM_FUNC_DECL GLM_CONSTEXPR genType two_over_root_pi(); + + /// Return 1 / sqrt(2). + /// @see gtc_constants + template<typename genType> + GLM_FUNC_DECL GLM_CONSTEXPR genType one_over_root_two(); + + /// Return sqrt(pi / 2). + /// @see gtc_constants + template<typename genType> + GLM_FUNC_DECL GLM_CONSTEXPR genType root_half_pi(); + + /// Return sqrt(2 * pi). + /// @see gtc_constants + template<typename genType> + GLM_FUNC_DECL GLM_CONSTEXPR genType root_two_pi(); + + /// Return sqrt(ln(4)). + /// @see gtc_constants + template<typename genType> + GLM_FUNC_DECL GLM_CONSTEXPR genType root_ln_four(); + + /// Return e constant. + /// @see gtc_constants + template<typename genType> + GLM_FUNC_DECL GLM_CONSTEXPR genType e(); + + /// Return Euler's constant. + /// @see gtc_constants + template<typename genType> + GLM_FUNC_DECL GLM_CONSTEXPR genType euler(); + + /// Return sqrt(2). + /// @see gtc_constants + template<typename genType> + GLM_FUNC_DECL GLM_CONSTEXPR genType root_two(); + + /// Return sqrt(3). + /// @see gtc_constants + template<typename genType> + GLM_FUNC_DECL GLM_CONSTEXPR genType root_three(); + + /// Return sqrt(5). + /// @see gtc_constants + template<typename genType> + GLM_FUNC_DECL GLM_CONSTEXPR genType root_five(); + + /// Return ln(2). + /// @see gtc_constants + template<typename genType> + GLM_FUNC_DECL GLM_CONSTEXPR genType ln_two(); + + /// Return ln(10). + /// @see gtc_constants + template<typename genType> + GLM_FUNC_DECL GLM_CONSTEXPR genType ln_ten(); + + /// Return ln(ln(2)). + /// @see gtc_constants + template<typename genType> + GLM_FUNC_DECL GLM_CONSTEXPR genType ln_ln_two(); + + /// Return 1 / 3. + /// @see gtc_constants + template<typename genType> + GLM_FUNC_DECL GLM_CONSTEXPR genType third(); + + /// Return 2 / 3. + /// @see gtc_constants + template<typename genType> + GLM_FUNC_DECL GLM_CONSTEXPR genType two_thirds(); + + /// Return the golden ratio constant. + /// @see gtc_constants + template<typename genType> + 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 0000000000000000000000000000000000000000..bb98c6bff9d11281f151dfbe7513c8c7f3f26be4 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/gtc/constants.inl @@ -0,0 +1,167 @@ +/// @ref gtc_constants + +namespace glm +{ + template<typename genType> + GLM_FUNC_QUALIFIER GLM_CONSTEXPR genType zero() + { + return genType(0); + } + + template<typename genType> + GLM_FUNC_QUALIFIER GLM_CONSTEXPR genType one() + { + return genType(1); + } + + template<typename genType> + GLM_FUNC_QUALIFIER GLM_CONSTEXPR genType two_pi() + { + return genType(6.28318530717958647692528676655900576); + } + + template<typename genType> + GLM_FUNC_QUALIFIER GLM_CONSTEXPR genType root_pi() + { + return genType(1.772453850905516027); + } + + template<typename genType> + GLM_FUNC_QUALIFIER GLM_CONSTEXPR genType half_pi() + { + return genType(1.57079632679489661923132169163975144); + } + + template<typename genType> + GLM_FUNC_QUALIFIER GLM_CONSTEXPR genType three_over_two_pi() + { + return genType(4.71238898038468985769396507491925432); + } + + template<typename genType> + GLM_FUNC_QUALIFIER GLM_CONSTEXPR genType quarter_pi() + { + return genType(0.785398163397448309615660845819875721); + } + + template<typename genType> + GLM_FUNC_QUALIFIER GLM_CONSTEXPR genType one_over_pi() + { + return genType(0.318309886183790671537767526745028724); + } + + template<typename genType> + GLM_FUNC_QUALIFIER GLM_CONSTEXPR genType one_over_two_pi() + { + return genType(0.159154943091895335768883763372514362); + } + + template<typename genType> + GLM_FUNC_QUALIFIER GLM_CONSTEXPR genType two_over_pi() + { + return genType(0.636619772367581343075535053490057448); + } + + template<typename genType> + GLM_FUNC_QUALIFIER GLM_CONSTEXPR genType four_over_pi() + { + return genType(1.273239544735162686151070106980114898); + } + + template<typename genType> + GLM_FUNC_QUALIFIER GLM_CONSTEXPR genType two_over_root_pi() + { + return genType(1.12837916709551257389615890312154517); + } + + template<typename genType> + GLM_FUNC_QUALIFIER GLM_CONSTEXPR genType one_over_root_two() + { + return genType(0.707106781186547524400844362104849039); + } + + template<typename genType> + GLM_FUNC_QUALIFIER GLM_CONSTEXPR genType root_half_pi() + { + return genType(1.253314137315500251); + } + + template<typename genType> + GLM_FUNC_QUALIFIER GLM_CONSTEXPR genType root_two_pi() + { + return genType(2.506628274631000502); + } + + template<typename genType> + GLM_FUNC_QUALIFIER GLM_CONSTEXPR genType root_ln_four() + { + return genType(1.17741002251547469); + } + + template<typename genType> + GLM_FUNC_QUALIFIER GLM_CONSTEXPR genType e() + { + return genType(2.71828182845904523536); + } + + template<typename genType> + GLM_FUNC_QUALIFIER GLM_CONSTEXPR genType euler() + { + return genType(0.577215664901532860606); + } + + template<typename genType> + GLM_FUNC_QUALIFIER GLM_CONSTEXPR genType root_two() + { + return genType(1.41421356237309504880168872420969808); + } + + template<typename genType> + GLM_FUNC_QUALIFIER GLM_CONSTEXPR genType root_three() + { + return genType(1.73205080756887729352744634150587236); + } + + template<typename genType> + GLM_FUNC_QUALIFIER GLM_CONSTEXPR genType root_five() + { + return genType(2.23606797749978969640917366873127623); + } + + template<typename genType> + GLM_FUNC_QUALIFIER GLM_CONSTEXPR genType ln_two() + { + return genType(0.693147180559945309417232121458176568); + } + + template<typename genType> + GLM_FUNC_QUALIFIER GLM_CONSTEXPR genType ln_ten() + { + return genType(2.30258509299404568401799145468436421); + } + + template<typename genType> + GLM_FUNC_QUALIFIER GLM_CONSTEXPR genType ln_ln_two() + { + return genType(-0.3665129205816643); + } + + template<typename genType> + GLM_FUNC_QUALIFIER GLM_CONSTEXPR genType third() + { + return genType(0.3333333333333333333333333333333333333333); + } + + template<typename genType> + GLM_FUNC_QUALIFIER GLM_CONSTEXPR genType two_thirds() + { + return genType(0.666666666666666666666666666666666666667); + } + + template<typename genType> + 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 0000000000000000000000000000000000000000..640439b11c36cd5df5261bc0e7a62c280700a252 --- /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 <glm/gtc/epsilon.hpp> 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<length_t L, typename T, qualifier Q> + GLM_FUNC_DECL vec<L, bool, Q> epsilonEqual(vec<L, T, Q> const& x, vec<L, T, Q> const& y, T const& epsilon); + + /// Returns the component-wise comparison of |x - y| < epsilon. + /// True if this expression is satisfied. + /// + /// @see gtc_epsilon + template<typename genType> + 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<length_t L, typename T, qualifier Q> + GLM_FUNC_DECL vec<L, bool, Q> epsilonNotEqual(vec<L, T, Q> const& x, vec<L, T, Q> 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<typename genType> + 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 0000000000000000000000000000000000000000..508b9f8966feff92b269182a24e03b67358a4a91 --- /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<length_t L, typename T, qualifier Q> + GLM_FUNC_QUALIFIER vec<L, bool, Q> epsilonEqual(vec<L, T, Q> const& x, vec<L, T, Q> const& y, T const& epsilon) + { + return lessThan(abs(x - y), vec<L, T, Q>(epsilon)); + } + + template<length_t L, typename T, qualifier Q> + GLM_FUNC_QUALIFIER vec<L, bool, Q> epsilonEqual(vec<L, T, Q> const& x, vec<L, T, Q> const& y, vec<L, T, Q> const& epsilon) + { + return lessThan(abs(x - y), vec<L, T, Q>(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<length_t L, typename T, qualifier Q> + GLM_FUNC_QUALIFIER vec<L, bool, Q> epsilonNotEqual(vec<L, T, Q> const& x, vec<L, T, Q> const& y, T const& epsilon) + { + return greaterThanEqual(abs(x - y), vec<L, T, Q>(epsilon)); + } + + template<length_t L, typename T, qualifier Q> + GLM_FUNC_QUALIFIER vec<L, bool, Q> epsilonNotEqual(vec<L, T, Q> const& x, vec<L, T, Q> const& y, vec<L, T, Q> const& epsilon) + { + return greaterThanEqual(abs(x - y), vec<L, T, Q>(epsilon)); + } + + template<typename T, qualifier Q> + GLM_FUNC_QUALIFIER vec<4, bool, Q> epsilonEqual(qua<T, Q> const& x, qua<T, Q> 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<typename T, qualifier Q> + GLM_FUNC_QUALIFIER vec<4, bool, Q> epsilonNotEqual(qua<T, Q> const& x, qua<T, Q> 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 0000000000000000000000000000000000000000..64ce10bb1bd2e4d3c84dfe67e6977f92dd6f2ab6 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/gtc/integer.hpp @@ -0,0 +1,65 @@ +/// @ref gtc_integer +/// @file glm/gtc/integer.hpp +/// +/// @see core (dependence) +/// @see gtc_integer (dependence) +/// +/// @defgroup gtc_integer GLM_GTC_integer +/// @ingroup gtc +/// +/// Include <glm/gtc/integer.hpp> 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 <limits> + +#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. Usefull to compute mipmap count from the texture size. + /// @see gtc_integer + template<typename genIUType> + GLM_FUNC_DECL genIUType log2(genIUType 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 <a href="http://www.opengl.org/sdk/docs/manglsl/xhtml/round.xml">GLSL round man page</a> + /// @see gtc_integer + template<length_t L, typename T, qualifier Q> + GLM_FUNC_DECL vec<L, int, Q> iround(vec<L, T, Q> 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 <a href="http://www.opengl.org/sdk/docs/manglsl/xhtml/round.xml">GLSL round man page</a> + /// @see gtc_integer + template<length_t L, typename T, qualifier Q> + GLM_FUNC_DECL vec<L, uint, Q> uround(vec<L, T, Q> const& x); + + /// @} +} //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 0000000000000000000000000000000000000000..f0a8b4f2578e2935008defa43f6864c8d9dfb72d --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/gtc/integer.inl @@ -0,0 +1,68 @@ +/// @ref gtc_integer + +namespace glm{ +namespace detail +{ + template<length_t L, typename T, qualifier Q, bool Aligned> + struct compute_log2<L, T, Q, false, Aligned> + { + GLM_FUNC_QUALIFIER static vec<L, T, Q> call(vec<L, T, Q> const& v) + { + //Equivalent to return findMSB(vec); but save one function call in ASM with VC + //return findMSB(vec); + return vec<L, T, Q>(detail::compute_findMSB_vec<L, T, Q, sizeof(T) * 8>::call(v)); + } + }; + +# if GLM_HAS_BITSCAN_WINDOWS + template<qualifier Q, bool Aligned> + 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<unsigned long*>(&Result.x), v.x); + _BitScanReverse(reinterpret_cast<unsigned long*>(&Result.y), v.y); + _BitScanReverse(reinterpret_cast<unsigned long*>(&Result.z), v.z); + _BitScanReverse(reinterpret_cast<unsigned long*>(&Result.w), v.w); + return Result; + } + }; +# endif//GLM_HAS_BITSCAN_WINDOWS +}//namespace detail + template<typename genType> + GLM_FUNC_QUALIFIER int iround(genType x) + { + GLM_STATIC_ASSERT(std::numeric_limits<genType>::is_iec559, "'iround' only accept floating-point inputs"); + assert(static_cast<genType>(0.0) <= x); + + return static_cast<int>(x + static_cast<genType>(0.5)); + } + + template<length_t L, typename T, qualifier Q> + GLM_FUNC_QUALIFIER vec<L, int, Q> iround(vec<L, T, Q> const& x) + { + GLM_STATIC_ASSERT(std::numeric_limits<T>::is_iec559, "'iround' only accept floating-point inputs"); + assert(all(lessThanEqual(vec<L, T, Q>(0), x))); + + return vec<L, int, Q>(x + static_cast<T>(0.5)); + } + + template<typename genType> + GLM_FUNC_QUALIFIER uint uround(genType x) + { + GLM_STATIC_ASSERT(std::numeric_limits<genType>::is_iec559, "'uround' only accept floating-point inputs"); + assert(static_cast<genType>(0.0) <= x); + + return static_cast<uint>(x + static_cast<genType>(0.5)); + } + + template<length_t L, typename T, qualifier Q> + GLM_FUNC_QUALIFIER vec<L, uint, Q> uround(vec<L, T, Q> const& x) + { + GLM_STATIC_ASSERT(std::numeric_limits<T>::is_iec559, "'uround' only accept floating-point inputs"); + assert(all(lessThanEqual(vec<L, T, Q>(0), x))); + + return vec<L, uint, Q>(x + static_cast<T>(0.5)); + } +}//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 0000000000000000000000000000000000000000..4935ba755dd502af46a80bfc30a49b39e188a8bc --- /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 <glm/gtc/matrix_access.hpp> 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<typename genType> + 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<typename genType> + 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<typename genType> + 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<typename genType> + 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 0000000000000000000000000000000000000000..09fcc10d3d7e4c2c1d70de38b4d02628e09477fc --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/gtc/matrix_access.inl @@ -0,0 +1,62 @@ +/// @ref gtc_matrix_access + +namespace glm +{ + template<typename genType> + 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<typename genType> + 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<typename genType> + 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<typename genType> + 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 0000000000000000000000000000000000000000..d7ebdc719221c06f9b2d975ea987da7809533156 --- /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 <glm/gtc/matrix_integer.hpp> 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 0000000000000000000000000000000000000000..a1900adcbb06703235b1528b33cb239bd0a16c29 --- /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 <glm/gtc/matrix_integer.hpp> 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 innacurate. + /// @see gtc_matrix_inverse + template<typename genType> + 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 innacurate. + /// @see gtc_matrix_inverse + template<typename genType> + 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 0000000000000000000000000000000000000000..c004b9e146706b64fb9e73ba95e7bc3401b8c42a --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/gtc/matrix_inverse.inl @@ -0,0 +1,118 @@ +/// @ref gtc_matrix_inverse + +namespace glm +{ + template<typename T, qualifier Q> + 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<T>(0)), + vec<3, T, Q>(Inv[1], static_cast<T>(0)), + vec<3, T, Q>(-Inv * vec<2, T, Q>(m[2]), static_cast<T>(1))); + } + + template<typename T, qualifier Q> + 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<T>(0)), + vec<4, T, Q>(Inv[1], static_cast<T>(0)), + vec<4, T, Q>(Inv[2], static_cast<T>(0)), + vec<4, T, Q>(-Inv * vec<3, T, Q>(m[3]), static_cast<T>(1))); + } + + template<typename T, qualifier Q> + 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<typename T, qualifier Q> + 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<typename T, qualifier Q> + 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 0000000000000000000000000000000000000000..612418fa51c49d91c4e4e4a315083044a3db0b4c --- /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 <glm/gtc/matrix_transform.hpp> 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 0000000000000000000000000000000000000000..15b46bc9db617b238d8a60d382f584372e9d0855 --- /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 0000000000000000000000000000000000000000..ab1772e78125da6c280f4b1a676d7ff2c8fae082 --- /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 <glm/gtc/noise.hpp> 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<length_t L, typename T, qualifier Q> + GLM_FUNC_DECL T perlin( + vec<L, T, Q> const& p); + + /// Periodic perlin noise. + /// @see gtc_noise + template<length_t L, typename T, qualifier Q> + GLM_FUNC_DECL T perlin( + vec<L, T, Q> const& p, + vec<L, T, Q> const& rep); + + /// Simplex noise. + /// @see gtc_noise + template<length_t L, typename T, qualifier Q> + GLM_FUNC_DECL T simplex( + vec<L, T, Q> 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 0000000000000000000000000000000000000000..30d0b274d337a8e990fe0e264130e0e42c0321cb --- /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 gtc +{ + template<typename T, qualifier Q> + 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<T>(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 gtc + + // Classic Perlin noise + template<typename T, qualifier Q> + 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<T>(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<typename T, qualifier Q> + 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<typename T, qualifier Q> + 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<typename T, qualifier Q> + 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<typename T, qualifier Q> + 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<T>(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<typename T, qualifier Q> + 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<typename T, qualifier Q> + 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<typename T, qualifier Q> + 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<T>(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<T>(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<typename T, qualifier Q> + 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<T>(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<typename T, qualifier Q> + 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<T>(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<T>(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<T>(1) - isYZ.x; + i0.w += static_cast<T>(1) - isYZ.y; + i0.z += isYZ.z; + i0.w += static_cast<T>(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 = gtc::grad4(j0, ip); + vec<4, T, Q> p1 = gtc::grad4(j1.x, ip); + vec<4, T, Q> p2 = gtc::grad4(j1.y, ip); + vec<4, T, Q> p3 = gtc::grad4(j1.z, ip); + vec<4, T, Q> p4 = gtc::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 0000000000000000000000000000000000000000..8e416b3fe1b582eb540bd7d425220cd289756921 --- /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 <glm/gtc/packing.hpp> 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 <a href="http://www.opengl.org/sdk/docs/manglsl/xhtml/packUnorm4x8.xml">GLSL packUnorm4x8 man page</a> + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 8.4 Floating-Point Pack and Unpack Functions</a> + 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 <a href="http://www.opengl.org/sdk/docs/manglsl/xhtml/unpackUnorm4x8.xml">GLSL unpackUnorm4x8 man page</a> + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 8.4 Floating-Point Pack and Unpack Functions</a> + 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 <a href="http://www.opengl.org/sdk/docs/manglsl/xhtml/packUnorm4x8.xml">GLSL packUnorm4x8 man page</a> + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 8.4 Floating-Point Pack and Unpack Functions</a> + 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 <a href="http://www.opengl.org/sdk/docs/manglsl/xhtml/unpackUnorm4x8.xml">GLSL unpackUnorm4x8 man page</a> + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 8.4 Floating-Point Pack and Unpack Functions</a> + 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 <a href="http://www.opengl.org/sdk/docs/manglsl/xhtml/packSnorm4x8.xml">GLSL packSnorm4x8 man page</a> + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 8.4 Floating-Point Pack and Unpack Functions</a> + 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 <a href="http://www.opengl.org/sdk/docs/manglsl/xhtml/unpackSnorm4x8.xml">GLSL unpackSnorm4x8 man page</a> + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 8.4 Floating-Point Pack and Unpack Functions</a> + 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 <a href="http://www.opengl.org/sdk/docs/manglsl/xhtml/packSnorm4x8.xml">GLSL packSnorm4x8 man page</a> + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 8.4 Floating-Point Pack and Unpack Functions</a> + 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 <a href="http://www.opengl.org/sdk/docs/manglsl/xhtml/unpackSnorm4x8.xml">GLSL unpackSnorm4x8 man page</a> + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 8.4 Floating-Point Pack and Unpack Functions</a> + 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 <a href="http://www.opengl.org/sdk/docs/manglsl/xhtml/packUnorm4x8.xml">GLSL packUnorm4x8 man page</a> + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 8.4 Floating-Point Pack and Unpack Functions</a> + 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 <a href="http://www.opengl.org/sdk/docs/manglsl/xhtml/unpackUnorm2x16.xml">GLSL unpackUnorm2x16 man page</a> + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 8.4 Floating-Point Pack and Unpack Functions</a> + 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 <a href="http://www.opengl.org/sdk/docs/manglsl/xhtml/packUnorm4x8.xml">GLSL packUnorm4x8 man page</a> + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 8.4 Floating-Point Pack and Unpack Functions</a> + 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 <a href="http://www.opengl.org/sdk/docs/manglsl/xhtml/unpackUnorm2x16.xml">GLSL unpackUnorm2x16 man page</a> + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 8.4 Floating-Point Pack and Unpack Functions</a> + 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 <a href="http://www.opengl.org/sdk/docs/manglsl/xhtml/packSnorm4x8.xml">GLSL packSnorm4x8 man page</a> + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 8.4 Floating-Point Pack and Unpack Functions</a> + 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 <a href="http://www.opengl.org/sdk/docs/manglsl/xhtml/unpackSnorm1x16.xml">GLSL unpackSnorm4x8 man page</a> + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 8.4 Floating-Point Pack and Unpack Functions</a> + 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 <a href="http://www.opengl.org/sdk/docs/manglsl/xhtml/packSnorm4x8.xml">GLSL packSnorm4x8 man page</a> + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 8.4 Floating-Point Pack and Unpack Functions</a> + 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 <a href="http://www.opengl.org/sdk/docs/manglsl/xhtml/unpackSnorm2x16.xml">GLSL unpackSnorm4x8 man page</a> + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 8.4 Floating-Point Pack and Unpack Functions</a> + 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 <a href="http://www.opengl.org/sdk/docs/manglsl/xhtml/packHalf2x16.xml">GLSL packHalf2x16 man page</a> + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 8.4 Floating-Point Pack and Unpack Functions</a> + 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 <a href="http://www.opengl.org/sdk/docs/manglsl/xhtml/unpackHalf2x16.xml">GLSL unpackHalf2x16 man page</a> + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 8.4 Floating-Point Pack and Unpack Functions</a> + 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 <a href="http://www.opengl.org/sdk/docs/manglsl/xhtml/packHalf2x16.xml">GLSL packHalf2x16 man page</a> + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 8.4 Floating-Point Pack and Unpack Functions</a> + 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 <a href="http://www.opengl.org/sdk/docs/manglsl/xhtml/unpackHalf2x16.xml">GLSL unpackHalf2x16 man page</a> + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 8.4 Floating-Point Pack and Unpack Functions</a> + 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 <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 8.4 Floating-Point Pack and Unpack Functions</a> + template<length_t L, typename T, qualifier Q> + 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 <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 8.4 Floating-Point Pack and Unpack Functions</a> + template<length_t L, typename T, qualifier Q> + 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<L, float, Q> unpackHalf(vec<L, uint16, Q> const& p) + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 8.4 Floating-Point Pack and Unpack Functions</a> + template<length_t L, qualifier Q> + GLM_FUNC_DECL vec<L, uint16, Q> packHalf(vec<L, float, Q> 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<L, uint16, Q> packHalf(vec<L, float, Q> const& v) + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 8.4 Floating-Point Pack and Unpack Functions</a> + template<length_t L, qualifier Q> + GLM_FUNC_DECL vec<L, float, Q> unpackHalf(vec<L, uint16, Q> const& p); + + /// Convert each component of the normalized floating-point vector into unsigned integer values. + /// + /// @see gtc_packing + /// @see vec<L, floatType, Q> unpackUnorm(vec<L, intType, Q> const& p); + template<typename uintType, length_t L, typename floatType, qualifier Q> + GLM_FUNC_DECL vec<L, uintType, Q> packUnorm(vec<L, floatType, Q> const& v); + + /// Convert a packed integer to a normalized floating-point vector. + /// + /// @see gtc_packing + /// @see vec<L, intType, Q> packUnorm(vec<L, floatType, Q> const& v) + template<typename floatType, length_t L, typename uintType, qualifier Q> + GLM_FUNC_DECL vec<L, floatType, Q> unpackUnorm(vec<L, uintType, Q> const& v); + + /// Convert each component of the normalized floating-point vector into signed integer values. + /// + /// @see gtc_packing + /// @see vec<L, floatType, Q> unpackSnorm(vec<L, intType, Q> const& p); + template<typename intType, length_t L, typename floatType, qualifier Q> + GLM_FUNC_DECL vec<L, intType, Q> packSnorm(vec<L, floatType, Q> const& v); + + /// Convert a packed integer to a normalized floating-point vector. + /// + /// @see gtc_packing + /// @see vec<L, intType, Q> packSnorm(vec<L, floatType, Q> const& v) + template<typename floatType, length_t L, typename intType, qualifier Q> + GLM_FUNC_DECL vec<L, floatType, Q> unpackSnorm(vec<L, intType, Q> 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 0000000000000000000000000000000000000000..8c906e16c11aac784720d8a5ec29b49729e840eb --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/gtc/packing.inl @@ -0,0 +1,938 @@ +/// @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 <cstring> +#include <limits> + +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); +// } + + union u3u3u2 + { + struct + { + uint x : 3; + uint y : 3; + uint z : 2; + } data; + uint8 pack; + }; + + union u4u4 + { + struct + { + uint x : 4; + uint y : 4; + } data; + uint8 pack; + }; + + union u4u4u4u4 + { + struct + { + uint x : 4; + uint y : 4; + uint z : 4; + uint w : 4; + } data; + uint16 pack; + }; + + union u5u6u5 + { + struct + { + uint x : 5; + uint y : 6; + uint z : 5; + } data; + uint16 pack; + }; + + union u5u5u5u1 + { + struct + { + uint x : 5; + uint y : 5; + uint z : 5; + uint w : 1; + } data; + uint16 pack; + }; + + union u10u10u10u2 + { + struct + { + uint x : 10; + uint y : 10; + uint z : 10; + uint w : 2; + } data; + uint32 pack; + }; + + union i10i10i10i2 + { + struct + { + int x : 10; + int y : 10; + int z : 10; + int w : 2; + } data; + uint32 pack; + }; + + union u9u9u9e5 + { + struct + { + uint x : 9; + uint y : 9; + uint z : 9; + uint w : 5; + } data; + uint32 pack; + }; + + template<length_t L, qualifier Q> + struct compute_half + {}; + + template<qualifier Q> + 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<qualifier Q> + 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<qualifier Q> + 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<qualifier Q> + 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(v.x), detail::toFloat32(v.y), detail::toFloat32(v.z), detail::toFloat32(v.w)); + } + }; +}//namespace detail + + GLM_FUNC_QUALIFIER uint8 packUnorm1x8(float v) + { + return static_cast<uint8>(round(clamp(v, 0.0f, 1.0f) * 255.0f)); + } + + GLM_FUNC_QUALIFIER float unpackUnorm1x8(uint8 p) + { + float const Unpack(p); + return Unpack * static_cast<float>(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<int8>(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<float>(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<uint16>(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<int16>(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<float>(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<float>()) ? 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, Unpack.data.w - 15.f - 9.f); + } + + // Based on Brian Karis http://graphicrants.blogspot.fr/2009/04/rgbm-color-encoding.html + template<typename T, qualifier Q> + GLM_FUNC_QUALIFIER vec<4, T, Q> packRGBM(vec<3, T, Q> const& rgb) + { + vec<3, T, Q> const Color(rgb * static_cast<T>(1.0 / 6.0)); + T Alpha = clamp(max(max(Color.x, Color.y), max(Color.z, static_cast<T>(1e-6))), static_cast<T>(0), static_cast<T>(1)); + Alpha = ceil(Alpha * static_cast<T>(255.0)) / static_cast<T>(255.0); + return vec<4, T, Q>(Color / Alpha, Alpha); + } + + template<typename T, qualifier Q> + 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<T>(6); + } + + template<length_t L, qualifier Q> + GLM_FUNC_QUALIFIER vec<L, uint16, Q> packHalf(vec<L, float, Q> const& v) + { + return detail::compute_half<L, Q>::pack(v); + } + + template<length_t L, qualifier Q> + GLM_FUNC_QUALIFIER vec<L, float, Q> unpackHalf(vec<L, uint16, Q> const& v) + { + return detail::compute_half<L, Q>::unpack(v); + } + + template<typename uintType, length_t L, typename floatType, qualifier Q> + GLM_FUNC_QUALIFIER vec<L, uintType, Q> packUnorm(vec<L, floatType, Q> const& v) + { + GLM_STATIC_ASSERT(std::numeric_limits<uintType>::is_integer, "uintType must be an integer type"); + GLM_STATIC_ASSERT(std::numeric_limits<floatType>::is_iec559, "floatType must be a floating point type"); + + return vec<L, uintType, Q>(round(clamp(v, static_cast<floatType>(0), static_cast<floatType>(1)) * static_cast<floatType>(std::numeric_limits<uintType>::max()))); + } + + template<typename floatType, length_t L, typename uintType, qualifier Q> + GLM_FUNC_QUALIFIER vec<L, floatType, Q> unpackUnorm(vec<L, uintType, Q> const& v) + { + GLM_STATIC_ASSERT(std::numeric_limits<uintType>::is_integer, "uintType must be an integer type"); + GLM_STATIC_ASSERT(std::numeric_limits<floatType>::is_iec559, "floatType must be a floating point type"); + + return vec<L, float, Q>(v) * (static_cast<floatType>(1) / static_cast<floatType>(std::numeric_limits<uintType>::max())); + } + + template<typename intType, length_t L, typename floatType, qualifier Q> + GLM_FUNC_QUALIFIER vec<L, intType, Q> packSnorm(vec<L, floatType, Q> const& v) + { + GLM_STATIC_ASSERT(std::numeric_limits<intType>::is_integer, "uintType must be an integer type"); + GLM_STATIC_ASSERT(std::numeric_limits<floatType>::is_iec559, "floatType must be a floating point type"); + + return vec<L, intType, Q>(round(clamp(v , static_cast<floatType>(-1), static_cast<floatType>(1)) * static_cast<floatType>(std::numeric_limits<intType>::max()))); + } + + template<typename floatType, length_t L, typename intType, qualifier Q> + GLM_FUNC_QUALIFIER vec<L, floatType, Q> unpackSnorm(vec<L, intType, Q> const& v) + { + GLM_STATIC_ASSERT(std::numeric_limits<intType>::is_integer, "uintType must be an integer type"); + GLM_STATIC_ASSERT(std::numeric_limits<floatType>::is_iec559, "floatType must be a floating point type"); + + return clamp(vec<L, floatType, Q>(v) * (static_cast<floatType>(1) / static_cast<floatType>(std::numeric_limits<intType>::max())), static_cast<floatType>(-1), static_cast<floatType>(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 0000000000000000000000000000000000000000..359e072b9fa8d7667d54f3afc8ba63ec23563ddf --- /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 <glm/gtc/quaternion.hpp> 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<typename T, qualifier Q> + GLM_FUNC_DECL vec<3, T, Q> eulerAngles(qua<T, Q> const& x); + + /// Returns roll value of euler angles expressed in radians. + /// + /// @tparam T Floating-point scalar types. + /// + /// @see gtc_quaternion + template<typename T, qualifier Q> + GLM_FUNC_DECL T roll(qua<T, Q> const& x); + + /// Returns pitch value of euler angles expressed in radians. + /// + /// @tparam T Floating-point scalar types. + /// + /// @see gtc_quaternion + template<typename T, qualifier Q> + GLM_FUNC_DECL T pitch(qua<T, Q> const& x); + + /// Returns yaw value of euler angles expressed in radians. + /// + /// @tparam T Floating-point scalar types. + /// + /// @see gtc_quaternion + template<typename T, qualifier Q> + GLM_FUNC_DECL T yaw(qua<T, Q> const& x); + + /// Converts a quaternion to a 3 * 3 matrix. + /// + /// @tparam T Floating-point scalar types. + /// + /// @see gtc_quaternion + template<typename T, qualifier Q> + GLM_FUNC_DECL mat<3, 3, T, Q> mat3_cast(qua<T, Q> const& x); + + /// Converts a quaternion to a 4 * 4 matrix. + /// + /// @tparam T Floating-point scalar types. + /// + /// @see gtc_quaternion + template<typename T, qualifier Q> + GLM_FUNC_DECL mat<4, 4, T, Q> mat4_cast(qua<T, Q> const& x); + + /// Converts a pure rotation 3 * 3 matrix to a quaternion. + /// + /// @tparam T Floating-point scalar types. + /// + /// @see gtc_quaternion + template<typename T, qualifier Q> + GLM_FUNC_DECL qua<T, Q> 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<typename T, qualifier Q> + GLM_FUNC_DECL qua<T, Q> 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<typename T, qualifier Q> + GLM_FUNC_DECL vec<4, bool, Q> lessThan(qua<T, Q> const& x, qua<T, Q> 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<typename T, qualifier Q> + GLM_FUNC_DECL vec<4, bool, Q> lessThanEqual(qua<T, Q> const& x, qua<T, Q> 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<typename T, qualifier Q> + GLM_FUNC_DECL vec<4, bool, Q> greaterThan(qua<T, Q> const& x, qua<T, Q> 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<typename T, qualifier Q> + GLM_FUNC_DECL vec<4, bool, Q> greaterThanEqual(qua<T, Q> const& x, qua<T, Q> 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<typename T, qualifier Q> + GLM_FUNC_DECL qua<T, Q> 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<typename T, qualifier Q> + GLM_FUNC_DECL qua<T, Q> 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<typename T, qualifier Q> + GLM_FUNC_DECL qua<T, Q> 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 0000000000000000000000000000000000000000..06f9f020b86d5a319265226f9450ab8e5ee98f15 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/gtc/quaternion.inl @@ -0,0 +1,202 @@ +#include "../trigonometric.hpp" +#include "../geometric.hpp" +#include "../exponential.hpp" +#include "epsilon.hpp" +#include <limits> + +namespace glm +{ + template<typename T, qualifier Q> + GLM_FUNC_QUALIFIER vec<3, T, Q> eulerAngles(qua<T, Q> const& x) + { + return vec<3, T, Q>(pitch(x), yaw(x), roll(x)); + } + + template<typename T, qualifier Q> + GLM_FUNC_QUALIFIER T roll(qua<T, Q> const& q) + { + return static_cast<T>(atan(static_cast<T>(2) * (q.x * q.y + q.w * q.z), q.w * q.w + q.x * q.x - q.y * q.y - q.z * q.z)); + } + + template<typename T, qualifier Q> + GLM_FUNC_QUALIFIER T pitch(qua<T, Q> 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<T>(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<T>()))) //avoid atan2(0,0) - handle singularity - Matiis + return static_cast<T>(static_cast<T>(2) * atan(q.x, q.w)); + + return static_cast<T>(atan(y, x)); + } + + template<typename T, qualifier Q> + GLM_FUNC_QUALIFIER T yaw(qua<T, Q> const& q) + { + return asin(clamp(static_cast<T>(-2) * (q.x * q.z - q.w * q.y), static_cast<T>(-1), static_cast<T>(1))); + } + + template<typename T, qualifier Q> + GLM_FUNC_QUALIFIER mat<3, 3, T, Q> mat3_cast(qua<T, Q> 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<typename T, qualifier Q> + GLM_FUNC_QUALIFIER mat<4, 4, T, Q> mat4_cast(qua<T, Q> const& q) + { + return mat<4, 4, T, Q>(mat3_cast(q)); + } + + template<typename T, qualifier Q> + GLM_FUNC_QUALIFIER qua<T, Q> 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<T>(1)) * static_cast<T>(0.5); + T mult = static_cast<T>(0.25) / biggestVal; + + switch(biggestIndex) + { + case 0: + return qua<T, Q>(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<T, Q>((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<T, Q>((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<T, Q>((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<T, Q>(1, 0, 0, 0); + } + } + + template<typename T, qualifier Q> + GLM_FUNC_QUALIFIER qua<T, Q> quat_cast(mat<4, 4, T, Q> const& m4) + { + return quat_cast(mat<3, 3, T, Q>(m4)); + } + + template<typename T, qualifier Q> + GLM_FUNC_QUALIFIER vec<4, bool, Q> lessThan(qua<T, Q> const& x, qua<T, Q> 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<typename T, qualifier Q> + GLM_FUNC_QUALIFIER vec<4, bool, Q> lessThanEqual(qua<T, Q> const& x, qua<T, Q> 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<typename T, qualifier Q> + GLM_FUNC_QUALIFIER vec<4, bool, Q> greaterThan(qua<T, Q> const& x, qua<T, Q> 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<typename T, qualifier Q> + GLM_FUNC_QUALIFIER vec<4, bool, Q> greaterThanEqual(qua<T, Q> const& x, qua<T, Q> 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<typename T, qualifier Q> + GLM_FUNC_QUALIFIER qua<T, Q> 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<typename T, qualifier Q> + GLM_FUNC_QUALIFIER qua<T, Q> 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<T>(0.00001), dot(Right, Right))); + Result[1] = cross(Result[2], Result[0]); + + return quat_cast(Result); + } + + template<typename T, qualifier Q> + GLM_FUNC_QUALIFIER qua<T, Q> 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<T>(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 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 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 0000000000000000000000000000000000000000..9a859580e409c1d3ef1d11f89c91f1b8aa7b56d1 --- /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 <glm/gtc/random.hpp> 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<typename genType> + 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<length_t L, typename T, qualifier Q> + GLM_FUNC_DECL vec<L, T, Q> linearRand(vec<L, T, Q> const& Min, vec<L, T, Q> const& Max); + + /// Generate random numbers in the interval [Min, Max], according a gaussian distribution + /// + /// @see gtc_random + template<typename genType> + GLM_FUNC_DECL genType gaussRand(genType Mean, genType Deviation); + + /// Generate a random 2D vector which coordinates are regulary distributed on a circle of a given radius + /// + /// @see gtc_random + template<typename T> + GLM_FUNC_DECL vec<2, T, defaultp> circularRand(T Radius); + + /// Generate a random 3D vector which coordinates are regulary distributed on a sphere of a given radius + /// + /// @see gtc_random + template<typename T> + GLM_FUNC_DECL vec<3, T, defaultp> sphericalRand(T Radius); + + /// Generate a random 2D vector which coordinates are regulary distributed within the area of a disk of a given radius + /// + /// @see gtc_random + template<typename T> + GLM_FUNC_DECL vec<2, T, defaultp> diskRand(T Radius); + + /// Generate a random 3D vector which coordinates are regulary distributed within the volume of a ball of a given radius + /// + /// @see gtc_random + template<typename T> + 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 0000000000000000000000000000000000000000..704850987c6597beb6f64cdac2fd5b98e7115a84 --- /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 <cstdlib> +#include <ctime> +#include <cassert> +#include <cmath> + +namespace glm{ +namespace detail +{ + template <length_t L, typename T, qualifier Q> + struct compute_rand + { + GLM_FUNC_QUALIFIER static vec<L, T, Q> call(); + }; + + template <qualifier P> + struct compute_rand<1, uint8, P> + { + GLM_FUNC_QUALIFIER static vec<1, uint8, P> call() + { + return vec<1, uint8, P>( + std::rand() % std::numeric_limits<uint8>::max()); + } + }; + + template <qualifier P> + 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<uint8>::max(), + std::rand() % std::numeric_limits<uint8>::max()); + } + }; + + template <qualifier P> + 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<uint8>::max(), + std::rand() % std::numeric_limits<uint8>::max(), + std::rand() % std::numeric_limits<uint8>::max()); + } + }; + + template <qualifier P> + 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<uint8>::max(), + std::rand() % std::numeric_limits<uint8>::max(), + std::rand() % std::numeric_limits<uint8>::max(), + std::rand() % std::numeric_limits<uint8>::max()); + } + }; + + template <length_t L, qualifier Q> + struct compute_rand<L, uint16, Q> + { + GLM_FUNC_QUALIFIER static vec<L, uint16, Q> call() + { + return + (vec<L, uint16, Q>(compute_rand<L, uint8, Q>::call()) << static_cast<uint16>(8)) | + (vec<L, uint16, Q>(compute_rand<L, uint8, Q>::call()) << static_cast<uint16>(0)); + } + }; + + template <length_t L, qualifier Q> + struct compute_rand<L, uint32, Q> + { + GLM_FUNC_QUALIFIER static vec<L, uint32, Q> call() + { + return + (vec<L, uint32, Q>(compute_rand<L, uint16, Q>::call()) << static_cast<uint32>(16)) | + (vec<L, uint32, Q>(compute_rand<L, uint16, Q>::call()) << static_cast<uint32>(0)); + } + }; + + template <length_t L, qualifier Q> + struct compute_rand<L, uint64, Q> + { + GLM_FUNC_QUALIFIER static vec<L, uint64, Q> call() + { + return + (vec<L, uint64, Q>(compute_rand<L, uint32, Q>::call()) << static_cast<uint64>(32)) | + (vec<L, uint64, Q>(compute_rand<L, uint32, Q>::call()) << static_cast<uint64>(0)); + } + }; + + template <length_t L, typename T, qualifier Q> + struct compute_linearRand + { + GLM_FUNC_QUALIFIER static vec<L, T, Q> call(vec<L, T, Q> const& Min, vec<L, T, Q> const& Max); + }; + + template<length_t L, qualifier Q> + struct compute_linearRand<L, int8, Q> + { + GLM_FUNC_QUALIFIER static vec<L, int8, Q> call(vec<L, int8, Q> const& Min, vec<L, int8, Q> const& Max) + { + return (vec<L, int8, Q>(compute_rand<L, uint8, Q>::call() % vec<L, uint8, Q>(Max + static_cast<int8>(1) - Min))) + Min; + } + }; + + template<length_t L, qualifier Q> + struct compute_linearRand<L, uint8, Q> + { + GLM_FUNC_QUALIFIER static vec<L, uint8, Q> call(vec<L, uint8, Q> const& Min, vec<L, uint8, Q> const& Max) + { + return (compute_rand<L, uint8, Q>::call() % (Max + static_cast<uint8>(1) - Min)) + Min; + } + }; + + template<length_t L, qualifier Q> + struct compute_linearRand<L, int16, Q> + { + GLM_FUNC_QUALIFIER static vec<L, int16, Q> call(vec<L, int16, Q> const& Min, vec<L, int16, Q> const& Max) + { + return (vec<L, int16, Q>(compute_rand<L, uint16, Q>::call() % vec<L, uint16, Q>(Max + static_cast<int16>(1) - Min))) + Min; + } + }; + + template<length_t L, qualifier Q> + struct compute_linearRand<L, uint16, Q> + { + GLM_FUNC_QUALIFIER static vec<L, uint16, Q> call(vec<L, uint16, Q> const& Min, vec<L, uint16, Q> const& Max) + { + return (compute_rand<L, uint16, Q>::call() % (Max + static_cast<uint16>(1) - Min)) + Min; + } + }; + + template<length_t L, qualifier Q> + struct compute_linearRand<L, int32, Q> + { + GLM_FUNC_QUALIFIER static vec<L, int32, Q> call(vec<L, int32, Q> const& Min, vec<L, int32, Q> const& Max) + { + return (vec<L, int32, Q>(compute_rand<L, uint32, Q>::call() % vec<L, uint32, Q>(Max + static_cast<int32>(1) - Min))) + Min; + } + }; + + template<length_t L, qualifier Q> + struct compute_linearRand<L, uint32, Q> + { + GLM_FUNC_QUALIFIER static vec<L, uint32, Q> call(vec<L, uint32, Q> const& Min, vec<L, uint32, Q> const& Max) + { + return (compute_rand<L, uint32, Q>::call() % (Max + static_cast<uint32>(1) - Min)) + Min; + } + }; + + template<length_t L, qualifier Q> + struct compute_linearRand<L, int64, Q> + { + GLM_FUNC_QUALIFIER static vec<L, int64, Q> call(vec<L, int64, Q> const& Min, vec<L, int64, Q> const& Max) + { + return (vec<L, int64, Q>(compute_rand<L, uint64, Q>::call() % vec<L, uint64, Q>(Max + static_cast<int64>(1) - Min))) + Min; + } + }; + + template<length_t L, qualifier Q> + struct compute_linearRand<L, uint64, Q> + { + GLM_FUNC_QUALIFIER static vec<L, uint64, Q> call(vec<L, uint64, Q> const& Min, vec<L, uint64, Q> const& Max) + { + return (compute_rand<L, uint64, Q>::call() % (Max + static_cast<uint64>(1) - Min)) + Min; + } + }; + + template<length_t L, qualifier Q> + struct compute_linearRand<L, float, Q> + { + GLM_FUNC_QUALIFIER static vec<L, float, Q> call(vec<L, float, Q> const& Min, vec<L, float, Q> const& Max) + { + return vec<L, float, Q>(compute_rand<L, uint32, Q>::call()) / static_cast<float>(std::numeric_limits<uint32>::max()) * (Max - Min) + Min; + } + }; + + template<length_t L, qualifier Q> + struct compute_linearRand<L, double, Q> + { + GLM_FUNC_QUALIFIER static vec<L, double, Q> call(vec<L, double, Q> const& Min, vec<L, double, Q> const& Max) + { + return vec<L, double, Q>(compute_rand<L, uint64, Q>::call()) / static_cast<double>(std::numeric_limits<uint64>::max()) * (Max - Min) + Min; + } + }; + + template<length_t L, qualifier Q> + struct compute_linearRand<L, long double, Q> + { + GLM_FUNC_QUALIFIER static vec<L, long double, Q> call(vec<L, long double, Q> const& Min, vec<L, long double, Q> const& Max) + { + return vec<L, long double, Q>(compute_rand<L, uint64, Q>::call()) / static_cast<long double>(std::numeric_limits<uint64>::max()) * (Max - Min) + Min; + } + }; +}//namespace detail + + template<typename genType> + 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<length_t L, typename T, qualifier Q> + GLM_FUNC_QUALIFIER vec<L, T, Q> linearRand(vec<L, T, Q> const& Min, vec<L, T, Q> const& Max) + { + return detail::compute_linearRand<L, T, Q>::call(Min, Max); + } + + template<typename genType> + 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<genType>(x2 * Deviation * Deviation * sqrt((genType(-2) * log(w)) / w) + Mean); + } + + template<length_t L, typename T, qualifier Q> + GLM_FUNC_QUALIFIER vec<L, T, Q> gaussRand(vec<L, T, Q> const& Mean, vec<L, T, Q> const& Deviation) + { + return detail::functor2<vec, L, T, Q>::call(gaussRand, Mean, Deviation); + } + + template<typename T> + GLM_FUNC_QUALIFIER vec<2, T, defaultp> diskRand(T Radius) + { + assert(Radius > static_cast<T>(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<typename T> + GLM_FUNC_QUALIFIER vec<3, T, defaultp> ballRand(T Radius) + { + assert(Radius > static_cast<T>(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<typename T> + GLM_FUNC_QUALIFIER vec<2, T, defaultp> circularRand(T Radius) + { + assert(Radius > static_cast<T>(0)); + + T a = linearRand(T(0), static_cast<T>(6.283185307179586476925286766559)); + return vec<2, T, defaultp>(glm::cos(a), glm::sin(a)) * Radius; + } + + template<typename T> + GLM_FUNC_QUALIFIER vec<3, T, defaultp> sphericalRand(T Radius) + { + assert(Radius > static_cast<T>(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 0000000000000000000000000000000000000000..c7d1330383827ef0e7b6be0441c09fdf7b5d60b6 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/gtc/reciprocal.hpp @@ -0,0 +1,135 @@ +/// @ref gtc_reciprocal +/// @file glm/gtc/reciprocal.hpp +/// +/// @see core (dependence) +/// +/// @defgroup gtc_reciprocal GLM_GTC_reciprocal +/// @ingroup gtc +/// +/// Include <glm/gtc/reciprocal.hpp> 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 + +namespace glm +{ + /// @addtogroup gtc_reciprocal + /// @{ + + /// Secant function. + /// hypotenuse / adjacent or 1 / cos(x) + /// + /// @tparam genType Floating-point scalar or vector types. + /// + /// @see gtc_reciprocal + template<typename genType> + GLM_FUNC_DECL genType sec(genType angle); + + /// Cosecant function. + /// hypotenuse / opposite or 1 / sin(x) + /// + /// @tparam genType Floating-point scalar or vector types. + /// + /// @see gtc_reciprocal + template<typename genType> + GLM_FUNC_DECL genType csc(genType angle); + + /// Cotangent function. + /// adjacent / opposite or 1 / tan(x) + /// + /// @tparam genType Floating-point scalar or vector types. + /// + /// @see gtc_reciprocal + template<typename genType> + 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 gtc_reciprocal + template<typename genType> + 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 gtc_reciprocal + template<typename genType> + 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 gtc_reciprocal + template<typename genType> + GLM_FUNC_DECL genType acot(genType x); + + /// Secant hyperbolic function. + /// + /// @tparam genType Floating-point scalar or vector types. + /// + /// @see gtc_reciprocal + template<typename genType> + GLM_FUNC_DECL genType sech(genType angle); + + /// Cosecant hyperbolic function. + /// + /// @tparam genType Floating-point scalar or vector types. + /// + /// @see gtc_reciprocal + template<typename genType> + GLM_FUNC_DECL genType csch(genType angle); + + /// Cotangent hyperbolic function. + /// + /// @tparam genType Floating-point scalar or vector types. + /// + /// @see gtc_reciprocal + template<typename genType> + 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 gtc_reciprocal + template<typename genType> + 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 gtc_reciprocal + template<typename genType> + 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 gtc_reciprocal + template<typename genType> + GLM_FUNC_DECL genType acoth(genType x); + + /// @} +}//namespace glm + +#include "reciprocal.inl" diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/gtc/reciprocal.inl b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/gtc/reciprocal.inl new file mode 100644 index 0000000000000000000000000000000000000000..d88729e88f4098ca26ce757f54b88318d29bc45d --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/gtc/reciprocal.inl @@ -0,0 +1,191 @@ +/// @ref gtc_reciprocal + +#include "../trigonometric.hpp" +#include <limits> + +namespace glm +{ + // sec + template<typename genType> + GLM_FUNC_QUALIFIER genType sec(genType angle) + { + GLM_STATIC_ASSERT(std::numeric_limits<genType>::is_iec559, "'sec' only accept floating-point values"); + return genType(1) / glm::cos(angle); + } + + template<length_t L, typename T, qualifier Q> + GLM_FUNC_QUALIFIER vec<L, T, Q> sec(vec<L, T, Q> const& x) + { + GLM_STATIC_ASSERT(std::numeric_limits<T>::is_iec559, "'sec' only accept floating-point inputs"); + return detail::functor1<vec, L, T, T, Q>::call(sec, x); + } + + // csc + template<typename genType> + GLM_FUNC_QUALIFIER genType csc(genType angle) + { + GLM_STATIC_ASSERT(std::numeric_limits<genType>::is_iec559, "'csc' only accept floating-point values"); + return genType(1) / glm::sin(angle); + } + + template<length_t L, typename T, qualifier Q> + GLM_FUNC_QUALIFIER vec<L, T, Q> csc(vec<L, T, Q> const& x) + { + GLM_STATIC_ASSERT(std::numeric_limits<T>::is_iec559, "'csc' only accept floating-point inputs"); + return detail::functor1<vec, L, T, T, Q>::call(csc, x); + } + + // cot + template<typename genType> + GLM_FUNC_QUALIFIER genType cot(genType angle) + { + GLM_STATIC_ASSERT(std::numeric_limits<genType>::is_iec559, "'cot' only accept floating-point values"); + + genType const pi_over_2 = genType(3.1415926535897932384626433832795 / 2.0); + return glm::tan(pi_over_2 - angle); + } + + template<length_t L, typename T, qualifier Q> + GLM_FUNC_QUALIFIER vec<L, T, Q> cot(vec<L, T, Q> const& x) + { + GLM_STATIC_ASSERT(std::numeric_limits<T>::is_iec559, "'cot' only accept floating-point inputs"); + return detail::functor1<vec, L, T, T, Q>::call(cot, x); + } + + // asec + template<typename genType> + GLM_FUNC_QUALIFIER genType asec(genType x) + { + GLM_STATIC_ASSERT(std::numeric_limits<genType>::is_iec559, "'asec' only accept floating-point values"); + return acos(genType(1) / x); + } + + template<length_t L, typename T, qualifier Q> + GLM_FUNC_QUALIFIER vec<L, T, Q> asec(vec<L, T, Q> const& x) + { + GLM_STATIC_ASSERT(std::numeric_limits<T>::is_iec559, "'asec' only accept floating-point inputs"); + return detail::functor1<vec, L, T, T, Q>::call(asec, x); + } + + // acsc + template<typename genType> + GLM_FUNC_QUALIFIER genType acsc(genType x) + { + GLM_STATIC_ASSERT(std::numeric_limits<genType>::is_iec559, "'acsc' only accept floating-point values"); + return asin(genType(1) / x); + } + + template<length_t L, typename T, qualifier Q> + GLM_FUNC_QUALIFIER vec<L, T, Q> acsc(vec<L, T, Q> const& x) + { + GLM_STATIC_ASSERT(std::numeric_limits<T>::is_iec559, "'acsc' only accept floating-point inputs"); + return detail::functor1<vec, L, T, T, Q>::call(acsc, x); + } + + // acot + template<typename genType> + GLM_FUNC_QUALIFIER genType acot(genType x) + { + GLM_STATIC_ASSERT(std::numeric_limits<genType>::is_iec559, "'acot' only accept floating-point values"); + + genType const pi_over_2 = genType(3.1415926535897932384626433832795 / 2.0); + return pi_over_2 - atan(x); + } + + template<length_t L, typename T, qualifier Q> + GLM_FUNC_QUALIFIER vec<L, T, Q> acot(vec<L, T, Q> const& x) + { + GLM_STATIC_ASSERT(std::numeric_limits<T>::is_iec559, "'acot' only accept floating-point inputs"); + return detail::functor1<vec, L, T, T, Q>::call(acot, x); + } + + // sech + template<typename genType> + GLM_FUNC_QUALIFIER genType sech(genType angle) + { + GLM_STATIC_ASSERT(std::numeric_limits<genType>::is_iec559, "'sech' only accept floating-point values"); + return genType(1) / glm::cosh(angle); + } + + template<length_t L, typename T, qualifier Q> + GLM_FUNC_QUALIFIER vec<L, T, Q> sech(vec<L, T, Q> const& x) + { + GLM_STATIC_ASSERT(std::numeric_limits<T>::is_iec559, "'sech' only accept floating-point inputs"); + return detail::functor1<vec, L, T, T, Q>::call(sech, x); + } + + // csch + template<typename genType> + GLM_FUNC_QUALIFIER genType csch(genType angle) + { + GLM_STATIC_ASSERT(std::numeric_limits<genType>::is_iec559, "'csch' only accept floating-point values"); + return genType(1) / glm::sinh(angle); + } + + template<length_t L, typename T, qualifier Q> + GLM_FUNC_QUALIFIER vec<L, T, Q> csch(vec<L, T, Q> const& x) + { + GLM_STATIC_ASSERT(std::numeric_limits<T>::is_iec559, "'csch' only accept floating-point inputs"); + return detail::functor1<vec, L, T, T, Q>::call(csch, x); + } + + // coth + template<typename genType> + GLM_FUNC_QUALIFIER genType coth(genType angle) + { + GLM_STATIC_ASSERT(std::numeric_limits<genType>::is_iec559, "'coth' only accept floating-point values"); + return glm::cosh(angle) / glm::sinh(angle); + } + + template<length_t L, typename T, qualifier Q> + GLM_FUNC_QUALIFIER vec<L, T, Q> coth(vec<L, T, Q> const& x) + { + GLM_STATIC_ASSERT(std::numeric_limits<T>::is_iec559, "'coth' only accept floating-point inputs"); + return detail::functor1<vec, L, T, T, Q>::call(coth, x); + } + + // asech + template<typename genType> + GLM_FUNC_QUALIFIER genType asech(genType x) + { + GLM_STATIC_ASSERT(std::numeric_limits<genType>::is_iec559, "'asech' only accept floating-point values"); + return acosh(genType(1) / x); + } + + template<length_t L, typename T, qualifier Q> + GLM_FUNC_QUALIFIER vec<L, T, Q> asech(vec<L, T, Q> const& x) + { + GLM_STATIC_ASSERT(std::numeric_limits<T>::is_iec559, "'asech' only accept floating-point inputs"); + return detail::functor1<vec, L, T, T, Q>::call(asech, x); + } + + // acsch + template<typename genType> + GLM_FUNC_QUALIFIER genType acsch(genType x) + { + GLM_STATIC_ASSERT(std::numeric_limits<genType>::is_iec559, "'acsch' only accept floating-point values"); + return asinh(genType(1) / x); + } + + template<length_t L, typename T, qualifier Q> + GLM_FUNC_QUALIFIER vec<L, T, Q> acsch(vec<L, T, Q> const& x) + { + GLM_STATIC_ASSERT(std::numeric_limits<T>::is_iec559, "'acsch' only accept floating-point inputs"); + return detail::functor1<vec, L, T, T, Q>::call(acsch, x); + } + + // acoth + template<typename genType> + GLM_FUNC_QUALIFIER genType acoth(genType x) + { + GLM_STATIC_ASSERT(std::numeric_limits<genType>::is_iec559, "'acoth' only accept floating-point values"); + return atanh(genType(1) / x); + } + + template<length_t L, typename T, qualifier Q> + GLM_FUNC_QUALIFIER vec<L, T, Q> acoth(vec<L, T, Q> const& x) + { + GLM_STATIC_ASSERT(std::numeric_limits<T>::is_iec559, "'acoth' only accept floating-point inputs"); + return detail::functor1<vec, L, T, T, Q>::call(acoth, x); + } +}//namespace glm 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 0000000000000000000000000000000000000000..56edbbca30b502abad5b82a70822453a475e4be2 --- /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 <glm/gtc/round.hpp> 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 <limits> + +#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<typename genIUType> + 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<length_t L, typename T, qualifier Q> + GLM_FUNC_DECL vec<L, T, Q> ceilPowerOfTwo(vec<L, T, Q> 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<typename genIUType> + 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<length_t L, typename T, qualifier Q> + GLM_FUNC_DECL vec<L, T, Q> floorPowerOfTwo(vec<L, T, Q> const& v); + + /// Return the power of two number which value is the closet to the input value. + /// + /// @see gtc_round + template<typename genIUType> + 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<length_t L, typename T, qualifier Q> + GLM_FUNC_DECL vec<L, T, Q> roundPowerOfTwo(vec<L, T, Q> 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<typename genType> + 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<length_t L, typename T, qualifier Q> + GLM_FUNC_DECL vec<L, T, Q> ceilMultiple(vec<L, T, Q> const& v, vec<L, T, Q> 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<typename genType> + 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<length_t L, typename T, qualifier Q> + GLM_FUNC_DECL vec<L, T, Q> floorMultiple(vec<L, T, Q> const& v, vec<L, T, Q> 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<typename genType> + 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<length_t L, typename T, qualifier Q> + GLM_FUNC_DECL vec<L, T, Q> roundMultiple(vec<L, T, Q> const& v, vec<L, T, Q> 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 0000000000000000000000000000000000000000..48411e41dc3442ec38a0dc88d9aa97d7dad20986 --- /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<bool is_float, bool is_signed> + struct compute_roundMultiple {}; + + template<> + struct compute_roundMultiple<true, true> + { + template<typename genType> + 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<false, false> + { + template<typename genType> + 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<false, true> + { + template<typename genType> + 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<typename genType> + GLM_FUNC_QUALIFIER genType ceilPowerOfTwo(genType value) + { + return detail::compute_ceilPowerOfTwo<1, genType, defaultp, std::numeric_limits<genType>::is_signed>::call(vec<1, genType, defaultp>(value)).x; + } + + template<length_t L, typename T, qualifier Q> + GLM_FUNC_QUALIFIER vec<L, T, Q> ceilPowerOfTwo(vec<L, T, Q> const& v) + { + return detail::compute_ceilPowerOfTwo<L, T, Q, std::numeric_limits<T>::is_signed>::call(v); + } + + /////////////////// + // floorPowerOfTwo + + template<typename genType> + GLM_FUNC_QUALIFIER genType floorPowerOfTwo(genType value) + { + return isPowerOfTwo(value) ? value : static_cast<genType>(1) << findMSB(value); + } + + template<length_t L, typename T, qualifier Q> + GLM_FUNC_QUALIFIER vec<L, T, Q> floorPowerOfTwo(vec<L, T, Q> const& v) + { + return detail::functor1<vec, L, T, T, Q>::call(floorPowerOfTwo, v); + } + + /////////////////// + // roundPowerOfTwo + + template<typename genIUType> + GLM_FUNC_QUALIFIER genIUType roundPowerOfTwo(genIUType value) + { + if(isPowerOfTwo(value)) + return value; + + genIUType const prev = static_cast<genIUType>(1) << findMSB(value); + genIUType const next = prev << static_cast<genIUType>(1); + return (next - value) < (value - prev) ? next : prev; + } + + template<length_t L, typename T, qualifier Q> + GLM_FUNC_QUALIFIER vec<L, T, Q> roundPowerOfTwo(vec<L, T, Q> const& v) + { + return detail::functor1<vec, L, T, T, Q>::call(roundPowerOfTwo, v); + } + + ////////////////////// + // ceilMultiple + + template<typename genType> + GLM_FUNC_QUALIFIER genType ceilMultiple(genType Source, genType Multiple) + { + return detail::compute_ceilMultiple<std::numeric_limits<genType>::is_iec559, std::numeric_limits<genType>::is_signed>::call(Source, Multiple); + } + + template<length_t L, typename T, qualifier Q> + GLM_FUNC_QUALIFIER vec<L, T, Q> ceilMultiple(vec<L, T, Q> const& Source, vec<L, T, Q> const& Multiple) + { + return detail::functor2<vec, L, T, Q>::call(ceilMultiple, Source, Multiple); + } + + ////////////////////// + // floorMultiple + + template<typename genType> + GLM_FUNC_QUALIFIER genType floorMultiple(genType Source, genType Multiple) + { + return detail::compute_floorMultiple<std::numeric_limits<genType>::is_iec559, std::numeric_limits<genType>::is_signed>::call(Source, Multiple); + } + + template<length_t L, typename T, qualifier Q> + GLM_FUNC_QUALIFIER vec<L, T, Q> floorMultiple(vec<L, T, Q> const& Source, vec<L, T, Q> const& Multiple) + { + return detail::functor2<vec, L, T, Q>::call(floorMultiple, Source, Multiple); + } + + ////////////////////// + // roundMultiple + + template<typename genType> + GLM_FUNC_QUALIFIER genType roundMultiple(genType Source, genType Multiple) + { + return detail::compute_roundMultiple<std::numeric_limits<genType>::is_iec559, std::numeric_limits<genType>::is_signed>::call(Source, Multiple); + } + + template<length_t L, typename T, qualifier Q> + GLM_FUNC_QUALIFIER vec<L, T, Q> roundMultiple(vec<L, T, Q> const& Source, vec<L, T, Q> const& Multiple) + { + return detail::functor2<vec, L, T, Q>::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 0000000000000000000000000000000000000000..5403abf675256b1dcb53bcd7eb553336daed29f6 --- /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 <glm/gtc/type_aligned.hpp> 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 0000000000000000000000000000000000000000..775e2f484d733b162043d8652ab990e70c9b68eb --- /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 <glm/gtc/type_precision.hpp> 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<f32, lowp> 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<f32, mediump> 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<f32, highp> 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<f32> 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<f32, defaultp> 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<f64, defaultp> 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<f32, defaultp> f32quat; + + /// Low single-qualifier floating-point quaternion. + /// @see gtc_type_precision + typedef qua<f32, lowp> lowp_f32quat; + + /// Low double-qualifier floating-point quaternion. + /// @see gtc_type_precision + typedef qua<f64, lowp> lowp_f64quat; + + /// Medium single-qualifier floating-point quaternion. + /// @see gtc_type_precision + typedef qua<f32, mediump> mediump_f32quat; + +# ifndef GLM_FORCE_SINGLE_ONLY + + /// Medium double-qualifier floating-point quaternion. + /// @see gtc_type_precision + typedef qua<f64, mediump> mediump_f64quat; + + /// High single-qualifier floating-point quaternion. + /// @see gtc_type_precision + typedef qua<f32, highp> highp_f32quat; + + /// High double-qualifier floating-point quaternion. + /// @see gtc_type_precision + typedef qua<f64, highp> highp_f64quat; + + /// Double-qualifier floating-point quaternion. + /// @see gtc_type_precision + typedef qua<f64, defaultp> 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 0000000000000000000000000000000000000000..ae8091206bd402a59d13d86edc1998b78eadb372 --- /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 0000000000000000000000000000000000000000..d7e625aa591719bb0c7e42db2509c48a2fc89b8e --- /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 <glm/gtc/type_ptr.hpp> 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 <glm/glm.hpp> +/// #include <glm/gtc/type_ptr.hpp> +/// +/// 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 +/// +/// <glm/gtc/type_ptr.hpp> 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 <cstring> + +#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<typename genType> + GLM_FUNC_DECL typename genType::value_type const * value_ptr(genType const& v); + + /// Build a vector from a pointer. + /// @see gtc_type_ptr + template <typename T, qualifier Q> + 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 <typename T, qualifier Q> + 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 <typename T, qualifier Q> + 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 <typename T, qualifier Q> + 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 <typename T, qualifier Q> + 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 <typename T, qualifier Q> + 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 <typename T, qualifier Q> + 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 <typename T, qualifier Q> + 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 <typename T, qualifier Q> + 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 <typename T, qualifier Q> + 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 <typename T, qualifier Q> + 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 <typename T, qualifier Q> + 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 <typename T, qualifier Q> + 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 <typename T, qualifier Q> + 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 <typename T, qualifier Q> + 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 <typename T, qualifier Q> + 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<typename T> + GLM_FUNC_DECL vec<2, T, defaultp> make_vec2(T const * const ptr); + + /// Build a vector from a pointer. + /// @see gtc_type_ptr + template<typename T> + GLM_FUNC_DECL vec<3, T, defaultp> make_vec3(T const * const ptr); + + /// Build a vector from a pointer. + /// @see gtc_type_ptr + template<typename T> + GLM_FUNC_DECL vec<4, T, defaultp> make_vec4(T const * const ptr); + + /// Build a matrix from a pointer. + /// @see gtc_type_ptr + template<typename T> + 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<typename T> + 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<typename T> + 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<typename T> + 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<typename T> + 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<typename T> + 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<typename T> + 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<typename T> + 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<typename T> + 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<typename T> + 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<typename T> + 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<typename T> + 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<typename T> + GLM_FUNC_DECL qua<T, defaultp> 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 0000000000000000000000000000000000000000..71df4d30d00cb844dd0cc5bf72c69aeaabb9e5de --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/gtc/type_ptr.inl @@ -0,0 +1,386 @@ +/// @ref gtc_type_ptr + +#include <cstring> + +namespace glm +{ + /// @addtogroup gtc_type_ptr + /// @{ + + template<typename T, qualifier Q> + GLM_FUNC_QUALIFIER T const* value_ptr(vec<2, T, Q> const& v) + { + return &(v.x); + } + + template<typename T, qualifier Q> + GLM_FUNC_QUALIFIER T* value_ptr(vec<2, T, Q>& v) + { + return &(v.x); + } + + template<typename T, qualifier Q> + GLM_FUNC_QUALIFIER T const * value_ptr(vec<3, T, Q> const& v) + { + return &(v.x); + } + + template<typename T, qualifier Q> + GLM_FUNC_QUALIFIER T* value_ptr(vec<3, T, Q>& v) + { + return &(v.x); + } + + template<typename T, qualifier Q> + GLM_FUNC_QUALIFIER T const* value_ptr(vec<4, T, Q> const& v) + { + return &(v.x); + } + + template<typename T, qualifier Q> + GLM_FUNC_QUALIFIER T* value_ptr(vec<4, T, Q>& v) + { + return &(v.x); + } + + template<typename T, qualifier Q> + GLM_FUNC_QUALIFIER T const* value_ptr(mat<2, 2, T, Q> const& m) + { + return &(m[0].x); + } + + template<typename T, qualifier Q> + GLM_FUNC_QUALIFIER T* value_ptr(mat<2, 2, T, Q>& m) + { + return &(m[0].x); + } + + template<typename T, qualifier Q> + GLM_FUNC_QUALIFIER T const* value_ptr(mat<3, 3, T, Q> const& m) + { + return &(m[0].x); + } + + template<typename T, qualifier Q> + GLM_FUNC_QUALIFIER T* value_ptr(mat<3, 3, T, Q>& m) + { + return &(m[0].x); + } + + template<typename T, qualifier Q> + GLM_FUNC_QUALIFIER T const* value_ptr(mat<4, 4, T, Q> const& m) + { + return &(m[0].x); + } + + template<typename T, qualifier Q> + GLM_FUNC_QUALIFIER T* value_ptr(mat<4, 4, T, Q>& m) + { + return &(m[0].x); + } + + template<typename T, qualifier Q> + GLM_FUNC_QUALIFIER T const* value_ptr(mat<2, 3, T, Q> const& m) + { + return &(m[0].x); + } + + template<typename T, qualifier Q> + GLM_FUNC_QUALIFIER T* value_ptr(mat<2, 3, T, Q>& m) + { + return &(m[0].x); + } + + template<typename T, qualifier Q> + GLM_FUNC_QUALIFIER T const* value_ptr(mat<3, 2, T, Q> const& m) + { + return &(m[0].x); + } + + template<typename T, qualifier Q> + GLM_FUNC_QUALIFIER T* value_ptr(mat<3, 2, T, Q>& m) + { + return &(m[0].x); + } + + template<typename T, qualifier Q> + GLM_FUNC_QUALIFIER T const* value_ptr(mat<2, 4, T, Q> const& m) + { + return &(m[0].x); + } + + template<typename T, qualifier Q> + GLM_FUNC_QUALIFIER T* value_ptr(mat<2, 4, T, Q>& m) + { + return &(m[0].x); + } + + template<typename T, qualifier Q> + GLM_FUNC_QUALIFIER T const* value_ptr(mat<4, 2, T, Q> const& m) + { + return &(m[0].x); + } + + template<typename T, qualifier Q> + GLM_FUNC_QUALIFIER T* value_ptr(mat<4, 2, T, Q>& m) + { + return &(m[0].x); + } + + template<typename T, qualifier Q> + GLM_FUNC_QUALIFIER T const* value_ptr(mat<3, 4, T, Q> const& m) + { + return &(m[0].x); + } + + template<typename T, qualifier Q> + GLM_FUNC_QUALIFIER T* value_ptr(mat<3, 4, T, Q>& m) + { + return &(m[0].x); + } + + template<typename T, qualifier Q> + GLM_FUNC_QUALIFIER T const* value_ptr(mat<4, 3, T, Q> const& m) + { + return &(m[0].x); + } + + template<typename T, qualifier Q> + GLM_FUNC_QUALIFIER T * value_ptr(mat<4, 3, T, Q>& m) + { + return &(m[0].x); + } + + template<typename T, qualifier Q> + GLM_FUNC_QUALIFIER T const * value_ptr(qua<T, Q> const& q) + { + return &(q[0]); + } + + template<typename T, qualifier Q> + GLM_FUNC_QUALIFIER T* value_ptr(qua<T, Q>& q) + { + return &(q[0]); + } + + template <typename T, qualifier Q> + inline vec<1, T, Q> make_vec1(vec<1, T, Q> const& v) + { + return v; + } + + template <typename T, qualifier Q> + inline vec<1, T, Q> make_vec1(vec<2, T, Q> const& v) + { + return vec<1, T, Q>(v); + } + + template <typename T, qualifier Q> + inline vec<1, T, Q> make_vec1(vec<3, T, Q> const& v) + { + return vec<1, T, Q>(v); + } + + template <typename T, qualifier Q> + inline vec<1, T, Q> make_vec1(vec<4, T, Q> const& v) + { + return vec<1, T, Q>(v); + } + + template <typename T, qualifier Q> + inline vec<2, T, Q> make_vec2(vec<1, T, Q> const& v) + { + return vec<2, T, Q>(v.x, static_cast<T>(0)); + } + + template <typename T, qualifier Q> + inline vec<2, T, Q> make_vec2(vec<2, T, Q> const& v) + { + return v; + } + + template <typename T, qualifier Q> + inline vec<2, T, Q> make_vec2(vec<3, T, Q> const& v) + { + return vec<2, T, Q>(v); + } + + template <typename T, qualifier Q> + inline vec<2, T, Q> make_vec2(vec<4, T, Q> const& v) + { + return vec<2, T, Q>(v); + } + + template <typename T, qualifier Q> + inline vec<3, T, Q> make_vec3(vec<1, T, Q> const& v) + { + return vec<3, T, Q>(v.x, static_cast<T>(0), static_cast<T>(0)); + } + + template <typename T, qualifier Q> + inline vec<3, T, Q> make_vec3(vec<2, T, Q> const& v) + { + return vec<3, T, Q>(v.x, v.y, static_cast<T>(0)); + } + + template <typename T, qualifier Q> + inline vec<3, T, Q> make_vec3(vec<3, T, Q> const& v) + { + return v; + } + + template <typename T, qualifier Q> + inline vec<3, T, Q> make_vec3(vec<4, T, Q> const& v) + { + return vec<3, T, Q>(v); + } + + template <typename T, qualifier Q> + inline vec<4, T, Q> make_vec4(vec<1, T, Q> const& v) + { + return vec<4, T, Q>(v.x, static_cast<T>(0), static_cast<T>(0), static_cast<T>(1)); + } + + template <typename T, qualifier Q> + inline vec<4, T, Q> make_vec4(vec<2, T, Q> const& v) + { + return vec<4, T, Q>(v.x, v.y, static_cast<T>(0), static_cast<T>(1)); + } + + template <typename T, qualifier Q> + inline 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<T>(1)); + } + + template <typename T, qualifier Q> + inline vec<4, T, Q> make_vec4(vec<4, T, Q> const& v) + { + return v; + } + + template<typename T> + 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<typename T> + 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<typename T> + 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<typename T> + 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<typename T> + 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<typename T> + 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<typename T> + 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<typename T> + 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<typename T> + 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<typename T> + 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<typename T> + 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<typename T> + 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<typename T> + GLM_FUNC_QUALIFIER mat<2, 2, T, defaultp> make_mat2(T const *const ptr) + { + return make_mat2x2(ptr); + } + + template<typename T> + GLM_FUNC_QUALIFIER mat<3, 3, T, defaultp> make_mat3(T const *const ptr) + { + return make_mat3x3(ptr); + } + + template<typename T> + GLM_FUNC_QUALIFIER mat<4, 4, T, defaultp> make_mat4(T const *const ptr) + { + return make_mat4x4(ptr); + } + + template<typename T> + GLM_FUNC_QUALIFIER qua<T, defaultp> make_quat(T const *const ptr) + { + qua<T, defaultp> Result; + memcpy(value_ptr(Result), ptr, sizeof(qua<T, defaultp>)); + 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 0000000000000000000000000000000000000000..0d80a75852a277b4a28a1a17d82f59850eabfe2e --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/gtc/ulp.hpp @@ -0,0 +1,152 @@ +/// @ref gtc_ulp +/// @file glm/gtc/ulp.hpp +/// +/// @see core (dependence) +/// +/// @defgroup gtc_ulp GLM_GTC_ulp +/// @ingroup gtc +/// +/// Include <glm/gtc/ulp.hpp> 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 +{ + /// Return the next ULP value(s) after the input value(s). + /// + /// @tparam genType A floating-point scalar type. + /// + /// @see gtc_ulp + template<typename genType> + 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<typename genType> + 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<typename genType> + 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<typename genType> + 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<length_t L, typename T, qualifier Q> + GLM_FUNC_DECL vec<L, T, Q> next_float(vec<L, T, Q> 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<length_t L, typename T, qualifier Q> + GLM_FUNC_DECL vec<L, T, Q> next_float(vec<L, T, Q> 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<length_t L, typename T, qualifier Q> + GLM_FUNC_DECL vec<L, T, Q> next_float(vec<L, T, Q> const& x, vec<L, int, Q> 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<length_t L, typename T, qualifier Q> + GLM_FUNC_DECL vec<L, T, Q> prev_float(vec<L, T, Q> 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<length_t L, typename T, qualifier Q> + GLM_FUNC_DECL vec<L, T, Q> prev_float(vec<L, T, Q> 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<length_t L, typename T, qualifier Q> + GLM_FUNC_DECL vec<L, T, Q> prev_float(vec<L, T, Q> const& x, vec<L, int, Q> 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<length_t L, typename T, qualifier Q> + GLM_FUNC_DECL vec<L, int, Q> float_distance(vec<L, float, Q> const& x, vec<L, float, Q> 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<length_t L, typename T, qualifier Q> + GLM_FUNC_DECL vec<L, int64, Q> float_distance(vec<L, double, Q> const& x, vec<L, double, Q> 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 0000000000000000000000000000000000000000..4ecbd3f437a4e4539dc039626380b759d361e978 --- /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<float>::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<double>::max()); +# elif((GLM_COMPILER & GLM_COMPILER_VC) || ((GLM_COMPILER & GLM_COMPILER_INTEL) && (GLM_PLATFORM & GLM_PLATFORM_WINDOWS))) + return detail::nextafter(x, std::numeric_limits<double>::max()); +# elif(GLM_PLATFORM & GLM_PLATFORM_ANDROID) + return __builtin_nextafter(x, DBL_MAX); +# else + return nextafter(x, DBL_MAX); +# endif + } + + template<typename T> + GLM_FUNC_QUALIFIER T next_float(T x, int ULPs) + { + GLM_STATIC_ASSERT(std::numeric_limits<T>::is_iec559, "'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<float>::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<double>::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<typename T> + GLM_FUNC_QUALIFIER T prev_float(T x, int ULPs) + { + GLM_STATIC_ASSERT(std::numeric_limits<T>::is_iec559, "'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<float> const a(x); + detail::float_t<float> const b(y); + + return abs(a.i - b.i); + } + + GLM_FUNC_QUALIFIER int64 float_distance(double x, double y) + { + detail::float_t<double> const a(x); + detail::float_t<double> const b(y); + + return abs(a.i - b.i); + } + + template<length_t L, typename T, qualifier Q> + GLM_FUNC_QUALIFIER vec<L, T, Q> next_float(vec<L, T, Q> const& x) + { + vec<L, T, Q> Result; + for (length_t i = 0, n = Result.length(); i < n; ++i) + Result[i] = next_float(x[i]); + return Result; + } + + template<length_t L, typename T, qualifier Q> + GLM_FUNC_QUALIFIER vec<L, T, Q> next_float(vec<L, T, Q> const& x, int ULPs) + { + vec<L, T, Q> Result; + for (length_t i = 0, n = Result.length(); i < n; ++i) + Result[i] = next_float(x[i], ULPs); + return Result; + } + + template<length_t L, typename T, qualifier Q> + GLM_FUNC_QUALIFIER vec<L, T, Q> next_float(vec<L, T, Q> const& x, vec<L, int, Q> const& ULPs) + { + vec<L, T, Q> Result; + for (length_t i = 0, n = Result.length(); i < n; ++i) + Result[i] = next_float(x[i], ULPs[i]); + return Result; + } + + template<length_t L, typename T, qualifier Q> + GLM_FUNC_QUALIFIER vec<L, T, Q> prev_float(vec<L, T, Q> const& x) + { + vec<L, T, Q> Result; + for (length_t i = 0, n = Result.length(); i < n; ++i) + Result[i] = prev_float(x[i]); + return Result; + } + + template<length_t L, typename T, qualifier Q> + GLM_FUNC_QUALIFIER vec<L, T, Q> prev_float(vec<L, T, Q> const& x, int ULPs) + { + vec<L, T, Q> Result; + for (length_t i = 0, n = Result.length(); i < n; ++i) + Result[i] = prev_float(x[i], ULPs); + return Result; + } + + template<length_t L, typename T, qualifier Q> + GLM_FUNC_QUALIFIER vec<L, T, Q> prev_float(vec<L, T, Q> const& x, vec<L, int, Q> const& ULPs) + { + vec<L, T, Q> Result; + for (length_t i = 0, n = Result.length(); i < n; ++i) + Result[i] = prev_float(x[i], ULPs[i]); + return Result; + } + + template<length_t L, qualifier Q> + GLM_FUNC_QUALIFIER vec<L, int, Q> float_distance(vec<L, float, Q> const& x, vec<L, float, Q> const& y) + { + vec<L, int, Q> Result; + for (length_t i = 0, n = Result.length(); i < n; ++i) + Result[i] = float_distance(x[i], y[i]); + return Result; + } + + template<length_t L, qualifier Q> + GLM_FUNC_QUALIFIER vec<L, int64, Q> float_distance(vec<L, double, Q> const& x, vec<L, double, Q> const& y) + { + vec<L, int64, Q> 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 0000000000000000000000000000000000000000..63697a2157508ac9ae597ea885804c7963e919c7 --- /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 <glm/gtc/vec1.hpp> 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 0000000000000000000000000000000000000000..d1a41c06baf8bdbffeec698597a73ec63bc2fe76 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/gtx/associated_min_max.hpp @@ -0,0 +1,207 @@ +/// @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 <glm/gtx/associated_min_max.hpp> to use the features of this extension. +/// +/// @brief Min and max functions that return associated values not the compared onces. + +#pragma once + +// Dependency: +#include "../glm.hpp" + +#if GLM_MESSAGES == GLM_ENABLE && !defined(GLM_EXT_INCLUDED) +# ifndef GLM_ENABLE_EXPERIMENTAL +# pragma message("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.") +# else +# pragma message("GLM: GLM_GTX_associated_min_max extension included") +# endif +#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<typename T, typename U, qualifier Q> + 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<length_t L, typename T, typename U, qualifier Q> + GLM_FUNC_DECL vec<2, U, Q> associatedMin( + vec<L, T, Q> const& x, vec<L, U, Q> const& a, + vec<L, T, Q> const& y, vec<L, U, Q> const& b); + + /// Minimum comparison between 2 variables and returns 2 associated variable values + /// @see gtx_associated_min_max + template<length_t L, typename T, typename U, qualifier Q> + GLM_FUNC_DECL vec<L, U, Q> associatedMin( + T x, const vec<L, U, Q>& a, + T y, const vec<L, U, Q>& b); + + /// Minimum comparison between 2 variables and returns 2 associated variable values + /// @see gtx_associated_min_max + template<length_t L, typename T, typename U, qualifier Q> + GLM_FUNC_DECL vec<L, U, Q> associatedMin( + vec<L, T, Q> const& x, U a, + vec<L, T, Q> const& y, U b); + + /// Minimum comparison between 3 variables and returns 3 associated variable values + /// @see gtx_associated_min_max + template<typename T, typename U> + 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<length_t L, typename T, typename U, qualifier Q> + GLM_FUNC_DECL vec<L, U, Q> associatedMin( + vec<L, T, Q> const& x, vec<L, U, Q> const& a, + vec<L, T, Q> const& y, vec<L, U, Q> const& b, + vec<L, T, Q> const& z, vec<L, U, Q> const& c); + + /// Minimum comparison between 4 variables and returns 4 associated variable values + /// @see gtx_associated_min_max + template<typename T, typename U> + 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<length_t L, typename T, typename U, qualifier Q> + GLM_FUNC_DECL vec<L, U, Q> associatedMin( + vec<L, T, Q> const& x, vec<L, U, Q> const& a, + vec<L, T, Q> const& y, vec<L, U, Q> const& b, + vec<L, T, Q> const& z, vec<L, U, Q> const& c, + vec<L, T, Q> const& w, vec<L, U, Q> const& d); + + /// Minimum comparison between 4 variables and returns 4 associated variable values + /// @see gtx_associated_min_max + template<length_t L, typename T, typename U, qualifier Q> + GLM_FUNC_DECL vec<L, U, Q> associatedMin( + T x, vec<L, U, Q> const& a, + T y, vec<L, U, Q> const& b, + T z, vec<L, U, Q> const& c, + T w, vec<L, U, Q> const& d); + + /// Minimum comparison between 4 variables and returns 4 associated variable values + /// @see gtx_associated_min_max + template<length_t L, typename T, typename U, qualifier Q> + GLM_FUNC_DECL vec<L, U, Q> associatedMin( + vec<L, T, Q> const& x, U a, + vec<L, T, Q> const& y, U b, + vec<L, T, Q> const& z, U c, + vec<L, T, Q> const& w, U d); + + /// Maximum comparison between 2 variables and returns 2 associated variable values + /// @see gtx_associated_min_max + template<typename T, typename U> + 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<length_t L, typename T, typename U, qualifier Q> + GLM_FUNC_DECL vec<2, U, Q> associatedMax( + vec<L, T, Q> const& x, vec<L, U, Q> const& a, + vec<L, T, Q> const& y, vec<L, U, Q> const& b); + + /// Maximum comparison between 2 variables and returns 2 associated variable values + /// @see gtx_associated_min_max + template<length_t L, typename T, typename U, qualifier Q> + GLM_FUNC_DECL vec<L, T, Q> associatedMax( + T x, vec<L, U, Q> const& a, + T y, vec<L, U, Q> const& b); + + /// Maximum comparison between 2 variables and returns 2 associated variable values + /// @see gtx_associated_min_max + template<length_t L, typename T, typename U, qualifier Q> + GLM_FUNC_DECL vec<L, U, Q> associatedMax( + vec<L, T, Q> const& x, U a, + vec<L, T, Q> const& y, U b); + + /// Maximum comparison between 3 variables and returns 3 associated variable values + /// @see gtx_associated_min_max + template<typename T, typename U> + 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<length_t L, typename T, typename U, qualifier Q> + GLM_FUNC_DECL vec<L, U, Q> associatedMax( + vec<L, T, Q> const& x, vec<L, U, Q> const& a, + vec<L, T, Q> const& y, vec<L, U, Q> const& b, + vec<L, T, Q> const& z, vec<L, U, Q> const& c); + + /// Maximum comparison between 3 variables and returns 3 associated variable values + /// @see gtx_associated_min_max + template<length_t L, typename T, typename U, qualifier Q> + GLM_FUNC_DECL vec<L, T, Q> associatedMax( + T x, vec<L, U, Q> const& a, + T y, vec<L, U, Q> const& b, + T z, vec<L, U, Q> const& c); + + /// Maximum comparison between 3 variables and returns 3 associated variable values + /// @see gtx_associated_min_max + template<length_t L, typename T, typename U, qualifier Q> + GLM_FUNC_DECL vec<L, U, Q> associatedMax( + vec<L, T, Q> const& x, U a, + vec<L, T, Q> const& y, U b, + vec<L, T, Q> const& z, U c); + + /// Maximum comparison between 4 variables and returns 4 associated variable values + /// @see gtx_associated_min_max + template<typename T, typename U> + 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<length_t L, typename T, typename U, qualifier Q> + GLM_FUNC_DECL vec<L, U, Q> associatedMax( + vec<L, T, Q> const& x, vec<L, U, Q> const& a, + vec<L, T, Q> const& y, vec<L, U, Q> const& b, + vec<L, T, Q> const& z, vec<L, U, Q> const& c, + vec<L, T, Q> const& w, vec<L, U, Q> const& d); + + /// Maximum comparison between 4 variables and returns 4 associated variable values + /// @see gtx_associated_min_max + template<length_t L, typename T, typename U, qualifier Q> + GLM_FUNC_DECL vec<L, U, Q> associatedMax( + T x, vec<L, U, Q> const& a, + T y, vec<L, U, Q> const& b, + T z, vec<L, U, Q> const& c, + T w, vec<L, U, Q> const& d); + + /// Maximum comparison between 4 variables and returns 4 associated variable values + /// @see gtx_associated_min_max + template<length_t L, typename T, typename U, qualifier Q> + GLM_FUNC_DECL vec<L, U, Q> associatedMax( + vec<L, T, Q> const& x, U a, + vec<L, T, Q> const& y, U b, + vec<L, T, Q> const& z, U c, + vec<L, T, Q> 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 0000000000000000000000000000000000000000..5186c471c28c6da0b7070ea6ca82f1de04c75bc5 --- /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<typename T, typename U, qualifier Q> +GLM_FUNC_QUALIFIER U associatedMin(T x, U a, T y, U b) +{ + return x < y ? a : b; +} + +template<length_t L, typename T, typename U, qualifier Q> +GLM_FUNC_QUALIFIER vec<2, U, Q> associatedMin +( + vec<L, T, Q> const& x, vec<L, U, Q> const& a, + vec<L, T, Q> const& y, vec<L, U, Q> const& b +) +{ + vec<L, U, Q> 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<length_t L, typename T, typename U, qualifier Q> +GLM_FUNC_QUALIFIER vec<L, U, Q> associatedMin +( + T x, const vec<L, U, Q>& a, + T y, const vec<L, U, Q>& b +) +{ + vec<L, U, Q> Result; + for(length_t i = 0, n = Result.length(); i < n; ++i) + Result[i] = x < y ? a[i] : b[i]; + return Result; +} + +template<length_t L, typename T, typename U, qualifier Q> +GLM_FUNC_QUALIFIER vec<L, U, Q> associatedMin +( + vec<L, T, Q> const& x, U a, + vec<L, T, Q> const& y, U b +) +{ + vec<L, U, Q> 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<typename T, typename U> +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<length_t L, typename T, typename U, qualifier Q> +GLM_FUNC_QUALIFIER vec<L, U, Q> associatedMin +( + vec<L, T, Q> const& x, vec<L, U, Q> const& a, + vec<L, T, Q> const& y, vec<L, U, Q> const& b, + vec<L, T, Q> const& z, vec<L, U, Q> const& c +) +{ + vec<L, U, Q> 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<typename T, typename U> +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<length_t L, typename T, typename U, qualifier Q> +GLM_FUNC_QUALIFIER vec<L, U, Q> associatedMin +( + vec<L, T, Q> const& x, vec<L, U, Q> const& a, + vec<L, T, Q> const& y, vec<L, U, Q> const& b, + vec<L, T, Q> const& z, vec<L, U, Q> const& c, + vec<L, T, Q> const& w, vec<L, U, Q> const& d +) +{ + vec<L, U, Q> 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<length_t L, typename T, typename U, qualifier Q> +GLM_FUNC_QUALIFIER vec<L, U, Q> associatedMin +( + T x, vec<L, U, Q> const& a, + T y, vec<L, U, Q> const& b, + T z, vec<L, U, Q> const& c, + T w, vec<L, U, Q> const& d +) +{ + T Test1 = min(x, y); + T Test2 = min(z, w); + + vec<L, U, Q> 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<length_t L, typename T, typename U, qualifier Q> +GLM_FUNC_QUALIFIER vec<L, U, Q> associatedMin +( + vec<L, T, Q> const& x, U a, + vec<L, T, Q> const& y, U b, + vec<L, T, Q> const& z, U c, + vec<L, T, Q> const& w, U d +) +{ + vec<L, U, Q> 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<typename T, typename U> +GLM_FUNC_QUALIFIER U associatedMax(T x, U a, T y, U b) +{ + return x > y ? a : b; +} + +// Max comparison between 2 variables +template<length_t L, typename T, typename U, qualifier Q> +GLM_FUNC_QUALIFIER vec<2, U, Q> associatedMax +( + vec<L, T, Q> const& x, vec<L, U, Q> const& a, + vec<L, T, Q> const& y, vec<L, U, Q> const& b +) +{ + vec<L, U, Q> 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<length_t L, typename T, typename U, qualifier Q> +GLM_FUNC_QUALIFIER vec<L, T, Q> associatedMax +( + T x, vec<L, U, Q> const& a, + T y, vec<L, U, Q> const& b +) +{ + vec<L, U, Q> 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<length_t L, typename T, typename U, qualifier Q> +GLM_FUNC_QUALIFIER vec<L, U, Q> associatedMax +( + vec<L, T, Q> const& x, U a, + vec<L, T, Q> const& y, U b +) +{ + vec<L, T, Q> 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<typename T, typename U> +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<length_t L, typename T, typename U, qualifier Q> +GLM_FUNC_QUALIFIER vec<L, U, Q> associatedMax +( + vec<L, T, Q> const& x, vec<L, U, Q> const& a, + vec<L, T, Q> const& y, vec<L, U, Q> const& b, + vec<L, T, Q> const& z, vec<L, U, Q> const& c +) +{ + vec<L, U, Q> 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<length_t L, typename T, typename U, qualifier Q> +GLM_FUNC_QUALIFIER vec<L, T, Q> associatedMax +( + T x, vec<L, U, Q> const& a, + T y, vec<L, U, Q> const& b, + T z, vec<L, U, Q> const& c +) +{ + vec<L, U, Q> 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<length_t L, typename T, typename U, qualifier Q> +GLM_FUNC_QUALIFIER vec<L, U, Q> associatedMax +( + vec<L, T, Q> const& x, U a, + vec<L, T, Q> const& y, U b, + vec<L, T, Q> const& z, U c +) +{ + vec<L, T, Q> 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<typename T, typename U> +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<length_t L, typename T, typename U, qualifier Q> +GLM_FUNC_QUALIFIER vec<L, U, Q> associatedMax +( + vec<L, T, Q> const& x, vec<L, U, Q> const& a, + vec<L, T, Q> const& y, vec<L, U, Q> const& b, + vec<L, T, Q> const& z, vec<L, U, Q> const& c, + vec<L, T, Q> const& w, vec<L, U, Q> const& d +) +{ + vec<L, U, Q> 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<length_t L, typename T, typename U, qualifier Q> +GLM_FUNC_QUALIFIER vec<L, U, Q> associatedMax +( + T x, vec<L, U, Q> const& a, + T y, vec<L, U, Q> const& b, + T z, vec<L, U, Q> const& c, + T w, vec<L, U, Q> const& d +) +{ + T Test1 = max(x, y); + T Test2 = max(z, w); + + vec<L, U, Q> 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<length_t L, typename T, typename U, qualifier Q> +GLM_FUNC_QUALIFIER vec<L, U, Q> associatedMax +( + vec<L, T, Q> const& x, U a, + vec<L, T, Q> const& y, U b, + vec<L, T, Q> const& z, U c, + vec<L, T, Q> const& w, U d +) +{ + vec<L, U, Q> 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 0000000000000000000000000000000000000000..60a7aef1b463f7c945e8e9e8cabf7f02c49343f1 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/gtx/bit.hpp @@ -0,0 +1,98 @@ +/// @ref gtx_bit +/// @file glm/gtx/bit.hpp +/// +/// @see core (dependence) +/// +/// @defgroup gtx_bit GLM_GTX_bit +/// @ingroup gtx +/// +/// Include <glm/gtx/bit.hpp> to use the features of this extension. +/// +/// Allow to perform bit operations on integer values + +#pragma once + +// Dependencies +#include "../gtc/bitfield.hpp" + +#if GLM_MESSAGES == GLM_ENABLE && !defined(GLM_EXT_INCLUDED) +# ifndef GLM_ENABLE_EXPERIMENTAL +# pragma message("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.") +# else +# pragma message("GLM: GLM_GTX_bit extension included") +# endif +#endif + +namespace glm +{ + /// @addtogroup gtx_bit + /// @{ + + /// @see gtx_bit + template<typename genIUType> + GLM_FUNC_DECL genIUType highestBitValue(genIUType Value); + + /// @see gtx_bit + template<typename genIUType> + 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<length_t L, typename T, qualifier Q> + GLM_FUNC_DECL vec<L, T, Q> highestBitValue(vec<L, T, Q> 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<typename genIUType> + 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<length_t L, typename T, qualifier Q> + GLM_DEPRECATED GLM_FUNC_DECL vec<L, T, Q> powerOfTwoAbove(vec<L, T, Q> 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<typename genIUType> + 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<length_t L, typename T, qualifier Q> + GLM_DEPRECATED GLM_FUNC_DECL vec<L, T, Q> powerOfTwoBelow(vec<L, T, Q> 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<typename genIUType> + 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<length_t L, typename T, qualifier Q> + GLM_DEPRECATED GLM_FUNC_DECL vec<L, T, Q> powerOfTwoNearest(vec<L, T, Q> 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 0000000000000000000000000000000000000000..621b6262406de7bcb462e09085fc82f2d638bdeb --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/gtx/bit.inl @@ -0,0 +1,92 @@ +/// @ref gtx_bit + +namespace glm +{ + /////////////////// + // highestBitValue + + template<typename genIUType> + 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<length_t L, typename T, qualifier Q> + GLM_FUNC_QUALIFIER vec<L, T, Q> highestBitValue(vec<L, T, Q> const& v) + { + return detail::functor1<vec, L, T, T, Q>::call(highestBitValue, v); + } + + /////////////////// + // lowestBitValue + + template<typename genIUType> + GLM_FUNC_QUALIFIER genIUType lowestBitValue(genIUType Value) + { + return (Value & (~Value + 1)); + } + + template<length_t L, typename T, qualifier Q> + GLM_FUNC_QUALIFIER vec<L, T, Q> lowestBitValue(vec<L, T, Q> const& v) + { + return detail::functor1<vec, L, T, T, Q>::call(lowestBitValue, v); + } + + /////////////////// + // powerOfTwoAbove + + template<typename genType> + GLM_FUNC_QUALIFIER genType powerOfTwoAbove(genType value) + { + return isPowerOfTwo(value) ? value : highestBitValue(value) << 1; + } + + template<length_t L, typename T, qualifier Q> + GLM_FUNC_QUALIFIER vec<L, T, Q> powerOfTwoAbove(vec<L, T, Q> const& v) + { + return detail::functor1<vec, L, T, T, Q>::call(powerOfTwoAbove, v); + } + + /////////////////// + // powerOfTwoBelow + + template<typename genType> + GLM_FUNC_QUALIFIER genType powerOfTwoBelow(genType value) + { + return isPowerOfTwo(value) ? value : highestBitValue(value); + } + + template<length_t L, typename T, qualifier Q> + GLM_FUNC_QUALIFIER vec<L, T, Q> powerOfTwoBelow(vec<L, T, Q> const& v) + { + return detail::functor1<vec, L, T, T, Q>::call(powerOfTwoBelow, v); + } + + ///////////////////// + // powerOfTwoNearest + + template<typename genType> + 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<length_t L, typename T, qualifier Q> + GLM_FUNC_QUALIFIER vec<L, T, Q> powerOfTwoNearest(vec<L, T, Q> const& v) + { + return detail::functor1<vec, L, T, T, Q>::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 0000000000000000000000000000000000000000..de6dbbff94470ffba44d9ddfa6badfbaa176f3a6 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/gtx/closest_point.hpp @@ -0,0 +1,49 @@ +/// @ref gtx_closest_point +/// @file glm/gtx/closest_point.hpp +/// +/// @see core (dependence) +/// +/// @defgroup gtx_closest_point GLM_GTX_closest_point +/// @ingroup gtx +/// +/// Include <glm/gtx/closest_point.hpp> 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" + +#if GLM_MESSAGES == GLM_ENABLE && !defined(GLM_EXT_INCLUDED) +# ifndef GLM_ENABLE_EXPERIMENTAL +# pragma message("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.") +# else +# pragma message("GLM: GLM_GTX_closest_point extension included") +# endif +#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<typename T, qualifier Q> + 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<typename T, qualifier Q> + 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 0000000000000000000000000000000000000000..0a39b042b88c9f57052e0580f5fa8bcbba3ccfcc --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/gtx/closest_point.inl @@ -0,0 +1,45 @@ +/// @ref gtx_closest_point + +namespace glm +{ + template<typename T, qualifier Q> + 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<typename T, qualifier Q> + 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 0000000000000000000000000000000000000000..96ded2a2770ffd1e60d147c863bb26c978d93e05 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/gtx/color_encoding.hpp @@ -0,0 +1,54 @@ +/// @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 <glm/gtx/color_encoding.hpp> 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 <limits> + +#if GLM_MESSAGES == GLM_ENABLE && !defined(GLM_EXT_INCLUDED) +# ifndef GLM_ENABLE_EXPERIMENTAL +# pragma message("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.") +# else +# pragma message("GLM: GLM_GTC_color_encoding extension included") +# endif +#endif + +namespace glm +{ + /// @addtogroup gtx_color_encoding + /// @{ + + /// Convert a linear sRGB color to D65 YUV. + template<typename T, qualifier Q> + GLM_FUNC_DECL vec<3, T, Q> convertLinearSRGBToD65XYZ(vec<3, T, Q> const& ColorLinearSRGB); + + /// Convert a linear sRGB color to D50 YUV. + template<typename T, qualifier Q> + GLM_FUNC_DECL vec<3, T, Q> convertLinearSRGBToD50XYZ(vec<3, T, Q> const& ColorLinearSRGB); + + /// Convert a D65 YUV color to linear sRGB. + template<typename T, qualifier Q> + GLM_FUNC_DECL vec<3, T, Q> convertD65XYZToLinearSRGB(vec<3, T, Q> const& ColorD65XYZ); + + /// Convert a D65 YUV color to D50 YUV. + template<typename T, qualifier Q> + 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 0000000000000000000000000000000000000000..e50fa3efa42c9dd0452e11e0158df443d8c7e55b --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/gtx/color_encoding.inl @@ -0,0 +1,45 @@ +/// @ref gtx_color_encoding + +namespace glm +{ + template<typename T, qualifier Q> + 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<T>(5.650675255693055f); + } + + template<typename T, qualifier Q> + 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<typename T, qualifier Q> + 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<typename T, qualifier Q> + 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 0000000000000000000000000000000000000000..a6343921490840150c6930ec9de0518d16103bee --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/gtx/color_space.hpp @@ -0,0 +1,72 @@ +/// @ref gtx_color_space +/// @file glm/gtx/color_space.hpp +/// +/// @see core (dependence) +/// +/// @defgroup gtx_color_space GLM_GTX_color_space +/// @ingroup gtx +/// +/// Include <glm/gtx/color_space.hpp> to use the features of this extension. +/// +/// Related to RGB to HSV conversions and operations. + +#pragma once + +// Dependency: +#include "../glm.hpp" + +#if GLM_MESSAGES == GLM_ENABLE && !defined(GLM_EXT_INCLUDED) +# ifndef GLM_ENABLE_EXPERIMENTAL +# pragma message("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.") +# else +# pragma message("GLM: GLM_GTX_color_space extension included") +# endif +#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<typename T, qualifier Q> + 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<typename T, qualifier Q> + GLM_FUNC_DECL vec<3, T, Q> hsvColor( + vec<3, T, Q> const& rgbValue); + + /// Build a saturation matrix. + /// @see gtx_color_space + template<typename T> + GLM_FUNC_DECL mat<4, 4, T, defaultp> saturation( + T const s); + + /// Modify the saturation of a color. + /// @see gtx_color_space + template<typename T, qualifier Q> + 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<typename T, qualifier Q> + 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<typename T, qualifier Q> + 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 0000000000000000000000000000000000000000..f698afe1e1b043b4f579896de7bb5cd921bc4075 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/gtx/color_space.inl @@ -0,0 +1,141 @@ +/// @ref gtx_color_space + +namespace glm +{ + template<typename T, qualifier Q> + 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(hsv.y == static_cast<T>(0)) + // 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<typename T, qualifier Q> + GLM_FUNC_QUALIFIER vec<3, T, Q> hsvColor(const vec<3, T, Q>& rgbColor) + { + vec<3, T, Q> hsv = rgbColor; + float Min = min(min(rgbColor.r, rgbColor.g), rgbColor.b); + float Max = max(max(rgbColor.r, rgbColor.g), rgbColor.b); + float Delta = Max - Min; + + hsv.z = Max; + + if(Max != static_cast<T>(0)) + { + hsv.y = Delta / hsv.z; + T h = static_cast<T>(0); + + if(rgbColor.r == Max) + // between yellow & magenta + h = static_cast<T>(0) + T(60) * (rgbColor.g - rgbColor.b) / Delta; + else if(rgbColor.g == Max) + // between cyan & yellow + h = static_cast<T>(120) + T(60) * (rgbColor.b - rgbColor.r) / Delta; + else + // between magenta & cyan + h = static_cast<T>(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<T>(0); + hsv.x = static_cast<T>(0); + } + + return hsv; + } + + template<typename T> + 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<typename T, qualifier Q> + 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<typename T, qualifier Q> + GLM_FUNC_QUALIFIER vec<4, T, Q> saturation(const T s, const vec<4, T, Q>& color) + { + return saturation(s) * color; + } + + template<typename T, qualifier Q> + 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 0000000000000000000000000000000000000000..dd2b771693f6fed894e001da530523ed9d32b951 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/gtx/color_space_YCoCg.hpp @@ -0,0 +1,60 @@ +/// @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 <glm/gtx/color_space_YCoCg.hpp> to use the features of this extension. +/// +/// RGB to YCoCg conversions and operations + +#pragma once + +// Dependency: +#include "../glm.hpp" + +#if GLM_MESSAGES == GLM_ENABLE && !defined(GLM_EXT_INCLUDED) +# ifndef GLM_ENABLE_EXPERIMENTAL +# pragma message("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.") +# else +# pragma message("GLM: GLM_GTX_color_space_YCoCg extension included") +# endif +#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<typename T, qualifier Q> + 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<typename T, qualifier Q> + 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<typename T, qualifier Q> + 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<typename T, qualifier Q> + 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 0000000000000000000000000000000000000000..83ba857c08bd248e037e0819c9fcb74558e81a77 --- /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<typename T, qualifier Q> + 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<typename T, qualifier Q> + 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<typename T, qualifier Q, bool isInteger> + 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<T>(0.5) + (rgbColor.r + rgbColor.b) * static_cast<T>(0.25); + result.y/*Co*/ = rgbColor.r - rgbColor.b; + result.z/*Cg*/ = rgbColor.g - (rgbColor.r + rgbColor.b) * static_cast<T>(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<T>(0.5)); + result.g = YCoCgRColor.z + tmp; + result.b = tmp - (YCoCgRColor.y * static_cast<T>(0.5)); + result.r = result.b + YCoCgRColor.y; + return result; + } + }; + + template<typename T, qualifier Q> + class compute_YCoCgR<T, Q, true> { + 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<typename T, qualifier Q> + GLM_FUNC_QUALIFIER vec<3, T, Q> rgb2YCoCgR + ( + vec<3, T, Q> const& rgbColor + ) + { + return compute_YCoCgR<T, Q, std::numeric_limits<T>::is_integer>::rgb2YCoCgR(rgbColor); + } + + template<typename T, qualifier Q> + GLM_FUNC_QUALIFIER vec<3, T, Q> YCoCgR2rgb + ( + vec<3, T, Q> const& YCoCgRColor + ) + { + return compute_YCoCgR<T, Q, std::numeric_limits<T>::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 0000000000000000000000000000000000000000..254ada2d769550538aefe5f91fcb413ede9543a9 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/gtx/common.hpp @@ -0,0 +1,76 @@ +/// @ref gtx_common +/// @file glm/gtx/common.hpp +/// +/// @see core (dependence) +/// +/// @defgroup gtx_common GLM_GTX_common +/// @ingroup gtx +/// +/// Include <glm/gtx/common.hpp> 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" + +#if GLM_MESSAGES == GLM_ENABLE && !defined(GLM_EXT_INCLUDED) +# ifndef GLM_ENABLE_EXPERIMENTAL +# pragma message("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.") +# else +# pragma message("GLM: GLM_GTX_common extension included") +# endif +#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 <a href="http://www.opengl.org/sdk/docs/manglsl/xhtml/isnan.xml">GLSL isnan man page</a> + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 8.3 Common Functions</a> + template<typename genType> + 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 <a href="http://stackoverflow.com/questions/7610631/glsl-mod-vs-hlsl-fmod">GLSL mod vs HLSL fmod</a> + /// @see <a href="http://www.opengl.org/sdk/docs/manglsl/xhtml/mod.xml">GLSL mod man page</a> + template<length_t L, typename T, qualifier Q> + GLM_FUNC_DECL vec<L, T, Q> fmod(vec<L, T, Q> 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 <length_t L, typename T, qualifier Q> + GLM_FUNC_DECL vec<L, bool, Q> openBounded(vec<L, T, Q> const& Value, vec<L, T, Q> const& Min, vec<L, T, Q> 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 <length_t L, typename T, qualifier Q> + GLM_FUNC_DECL vec<L, bool, Q> closeBounded(vec<L, T, Q> const& Value, vec<L, T, Q> const& Min, vec<L, T, Q> 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 0000000000000000000000000000000000000000..4ad2126d965d793dfd999c323039bf05c04da2d3 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/gtx/common.inl @@ -0,0 +1,125 @@ +/// @ref gtx_common + +#include <cmath> +#include "../gtc/epsilon.hpp" +#include "../gtc/constants.hpp" + +namespace glm{ +namespace detail +{ + template<length_t L, typename T, qualifier Q, bool isFloat = true> + struct compute_fmod + { + GLM_FUNC_QUALIFIER static vec<L, T, Q> call(vec<L, T, Q> const& a, vec<L, T, Q> const& b) + { + return detail::functor2<vec, L, T, Q>::call(std::fmod, a, b); + } + }; + + template<length_t L, typename T, qualifier Q> + struct compute_fmod<L, T, Q, false> + { + GLM_FUNC_QUALIFIER static vec<L, T, Q> call(vec<L, T, Q> const& a, vec<L, T, Q> const& b) + { + return a % b; + } + }; +}//namespace detail + + template<typename T> + GLM_FUNC_QUALIFIER bool isdenormal(T const& x) + { + GLM_STATIC_ASSERT(std::numeric_limits<T>::is_iec559, "'isdenormal' only accept floating-point inputs"); + +# if GLM_HAS_CXX11_STL + return std::fpclassify(x) == FP_SUBNORMAL; +# else + return epsilonNotEqual(x, static_cast<T>(0), epsilon<T>()) && std::fabs(x) < std::numeric_limits<T>::min(); +# endif + } + + template<typename T, qualifier Q> + GLM_FUNC_QUALIFIER typename vec<1, T, Q>::bool_type isdenormal + ( + vec<1, T, Q> const& x + ) + { + GLM_STATIC_ASSERT(std::numeric_limits<T>::is_iec559, "'isdenormal' only accept floating-point inputs"); + + return typename vec<1, T, Q>::bool_type( + isdenormal(x.x)); + } + + template<typename T, qualifier Q> + GLM_FUNC_QUALIFIER typename vec<2, T, Q>::bool_type isdenormal + ( + vec<2, T, Q> const& x + ) + { + GLM_STATIC_ASSERT(std::numeric_limits<T>::is_iec559, "'isdenormal' only accept floating-point inputs"); + + return typename vec<2, T, Q>::bool_type( + isdenormal(x.x), + isdenormal(x.y)); + } + + template<typename T, qualifier Q> + GLM_FUNC_QUALIFIER typename vec<3, T, Q>::bool_type isdenormal + ( + vec<3, T, Q> const& x + ) + { + GLM_STATIC_ASSERT(std::numeric_limits<T>::is_iec559, "'isdenormal' only accept floating-point inputs"); + + return typename vec<3, T, Q>::bool_type( + isdenormal(x.x), + isdenormal(x.y), + isdenormal(x.z)); + } + + template<typename T, qualifier Q> + GLM_FUNC_QUALIFIER typename vec<4, T, Q>::bool_type isdenormal + ( + vec<4, T, Q> const& x + ) + { + GLM_STATIC_ASSERT(std::numeric_limits<T>::is_iec559, "'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<typename genType> + GLM_FUNC_QUALIFIER genType fmod(genType x, genType y) + { + return fmod(vec<1, genType>(x), y).x; + } + + template<length_t L, typename T, qualifier Q> + GLM_FUNC_QUALIFIER vec<L, T, Q> fmod(vec<L, T, Q> const& x, T y) + { + return detail::compute_fmod<L, T, Q, std::numeric_limits<T>::is_iec559>::call(x, vec<L, T, Q>(y)); + } + + template<length_t L, typename T, qualifier Q> + GLM_FUNC_QUALIFIER vec<L, T, Q> fmod(vec<L, T, Q> const& x, vec<L, T, Q> const& y) + { + return detail::compute_fmod<L, T, Q, std::numeric_limits<T>::is_iec559>::call(x, y); + } + + template <length_t L, typename T, qualifier Q> + GLM_FUNC_QUALIFIER vec<L, bool, Q> openBounded(vec<L, T, Q> const& Value, vec<L, T, Q> const& Min, vec<L, T, Q> const& Max) + { + return greaterThan(Value, Min) && lessThan(Value, Max); + } + + template <length_t L, typename T, qualifier Q> + GLM_FUNC_QUALIFIER vec<L, bool, Q> closeBounded(vec<L, T, Q> const& Value, vec<L, T, Q> const& Min, vec<L, T, Q> 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 0000000000000000000000000000000000000000..f1b00a6b39cfbe32ae1fa1b4ec76654f992fb164 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/gtx/compatibility.hpp @@ -0,0 +1,133 @@ +/// @ref gtx_compatibility +/// @file glm/gtx/compatibility.hpp +/// +/// @see core (dependence) +/// +/// @defgroup gtx_compatibility GLM_GTX_compatibility +/// @ingroup gtx +/// +/// Include <glm/gtx/compatibility.hpp> 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" + +#if GLM_MESSAGES == GLM_ENABLE && !defined(GLM_EXT_INCLUDED) +# ifndef GLM_ENABLE_EXPERIMENTAL +# pragma message("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.") +# else +# pragma message("GLM: GLM_GTX_compatibility extension included") +# endif +#endif + +#if GLM_COMPILER & GLM_COMPILER_VC +# include <cfloat> +#elif GLM_COMPILER & GLM_COMPILER_GCC +# include <cmath> +# if(GLM_PLATFORM & GLM_PLATFORM_ANDROID) +# undef isfinite +# endif +#endif//GLM_COMPILER + +namespace glm +{ + /// @addtogroup gtx_compatibility + /// @{ + + template<typename T> 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<typename T, qualifier Q> 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<typename T, qualifier Q> 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<typename T, qualifier Q> 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<typename T, qualifier Q> 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<typename T, qualifier Q> 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<typename T, qualifier Q> 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<typename T, qualifier Q> 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<typename T, qualifier Q> 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<typename T, qualifier Q> 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<typename T, qualifier Q> 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<typename T, qualifier Q> GLM_FUNC_QUALIFIER T atan2(T x, T y){return atan(x, y);} //!< \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<typename T, qualifier Q> GLM_FUNC_QUALIFIER vec<2, T, Q> atan2(const vec<2, T, Q>& x, const vec<2, T, Q>& y){return atan(x, y);} //!< \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<typename T, qualifier Q> GLM_FUNC_QUALIFIER vec<3, T, Q> atan2(const vec<3, T, Q>& x, const vec<3, T, Q>& y){return atan(x, y);} //!< \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<typename T, qualifier Q> GLM_FUNC_QUALIFIER vec<4, T, Q> atan2(const vec<4, T, Q>& x, const vec<4, T, Q>& y){return atan(x, y);} //!< \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<typename genType> 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<typename T, qualifier Q> 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<typename T, qualifier Q> 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<typename T, qualifier Q> 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<typename T, qualifier Q> 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 0000000000000000000000000000000000000000..1d49496b6c6e817f67f416cac7f3881d8b54ece1 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/gtx/compatibility.inl @@ -0,0 +1,62 @@ +#include <limits> + +namespace glm +{ + // isfinite + template<typename genType> + 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<genType>::is_integer || std::denorm_absent == std::numeric_limits<genType>::has_denorm) + return std::numeric_limits<genType>::min() <= x && std::numeric_limits<genType>::max() >= x; + else + return -std::numeric_limits<genType>::max() <= x && std::numeric_limits<genType>::max() >= x; +# endif + } + + template<typename T, qualifier Q> + GLM_FUNC_QUALIFIER vec<1, bool, Q> isfinite( + vec<1, T, Q> const& x) + { + return vec<1, bool, Q>( + isfinite(x.x)); + } + + template<typename T, qualifier Q> + 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<typename T, qualifier Q> + 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<typename T, qualifier Q> + 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 0000000000000000000000000000000000000000..34a2b0a37517023bd31f7466a356924ce6312e0b --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/gtx/component_wise.hpp @@ -0,0 +1,69 @@ +/// @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 <glm/gtx/component_wise.hpp> to use the features of this extension. +/// +/// Operations between components of a type + +#pragma once + +// Dependencies +#include "../detail/setup.hpp" +#include "../detail/qualifier.hpp" + +#if GLM_MESSAGES == GLM_ENABLE && !defined(GLM_EXT_INCLUDED) +# ifndef GLM_ENABLE_EXPERIMENTAL +# pragma message("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.") +# else +# pragma message("GLM: GLM_GTX_component_wise extension included") +# endif +#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<typename floatType, length_t L, typename T, qualifier Q> + GLM_FUNC_DECL vec<L, floatType, Q> compNormalize(vec<L, T, Q> 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<length_t L, typename T, typename floatType, qualifier Q> + GLM_FUNC_DECL vec<L, T, Q> compScale(vec<L, floatType, Q> const& v); + + /// Add all vector components together. + /// @see gtx_component_wise + template<typename genType> + GLM_FUNC_DECL typename genType::value_type compAdd(genType const& v); + + /// Multiply all vector components together. + /// @see gtx_component_wise + template<typename genType> + GLM_FUNC_DECL typename genType::value_type compMul(genType const& v); + + /// Find the minimum value between single vector components. + /// @see gtx_component_wise + template<typename genType> + GLM_FUNC_DECL typename genType::value_type compMin(genType const& v); + + /// Find the maximum value between single vector components. + /// @see gtx_component_wise + template<typename genType> + GLM_FUNC_DECL typename genType::value_type compMax(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 0000000000000000000000000000000000000000..cbbc7d41ec007021d1f199eb106c87396a5fc03a --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/gtx/component_wise.inl @@ -0,0 +1,127 @@ +/// @ref gtx_component_wise + +#include <limits> + +namespace glm{ +namespace detail +{ + template<length_t L, typename T, typename floatType, qualifier Q, bool isInteger, bool signedType> + struct compute_compNormalize + {}; + + template<length_t L, typename T, typename floatType, qualifier Q> + struct compute_compNormalize<L, T, floatType, Q, true, true> + { + GLM_FUNC_QUALIFIER static vec<L, floatType, Q> call(vec<L, T, Q> const& v) + { + floatType const Min = static_cast<floatType>(std::numeric_limits<T>::min()); + floatType const Max = static_cast<floatType>(std::numeric_limits<T>::max()); + return (vec<L, floatType, Q>(v) - Min) / (Max - Min) * static_cast<floatType>(2) - static_cast<floatType>(1); + } + }; + + template<length_t L, typename T, typename floatType, qualifier Q> + struct compute_compNormalize<L, T, floatType, Q, true, false> + { + GLM_FUNC_QUALIFIER static vec<L, floatType, Q> call(vec<L, T, Q> const& v) + { + return vec<L, floatType, Q>(v) / static_cast<floatType>(std::numeric_limits<T>::max()); + } + }; + + template<length_t L, typename T, typename floatType, qualifier Q> + struct compute_compNormalize<L, T, floatType, Q, false, true> + { + GLM_FUNC_QUALIFIER static vec<L, floatType, Q> call(vec<L, T, Q> const& v) + { + return v; + } + }; + + template<length_t L, typename T, typename floatType, qualifier Q, bool isInteger, bool signedType> + struct compute_compScale + {}; + + template<length_t L, typename T, typename floatType, qualifier Q> + struct compute_compScale<L, T, floatType, Q, true, true> + { + GLM_FUNC_QUALIFIER static vec<L, T, Q> call(vec<L, floatType, Q> const& v) + { + floatType const Max = static_cast<floatType>(std::numeric_limits<T>::max()) + static_cast<floatType>(0.5); + vec<L, floatType, Q> const Scaled(v * Max); + vec<L, T, Q> const Result(Scaled - static_cast<floatType>(0.5)); + return Result; + } + }; + + template<length_t L, typename T, typename floatType, qualifier Q> + struct compute_compScale<L, T, floatType, Q, true, false> + { + GLM_FUNC_QUALIFIER static vec<L, T, Q> call(vec<L, floatType, Q> const& v) + { + return vec<L, T, Q>(vec<L, floatType, Q>(v) * static_cast<floatType>(std::numeric_limits<T>::max())); + } + }; + + template<length_t L, typename T, typename floatType, qualifier Q> + struct compute_compScale<L, T, floatType, Q, false, true> + { + GLM_FUNC_QUALIFIER static vec<L, T, Q> call(vec<L, floatType, Q> const& v) + { + return v; + } + }; +}//namespace detail + + template<typename floatType, length_t L, typename T, qualifier Q> + GLM_FUNC_QUALIFIER vec<L, floatType, Q> compNormalize(vec<L, T, Q> const& v) + { + GLM_STATIC_ASSERT(std::numeric_limits<floatType>::is_iec559, "'compNormalize' accepts only floating-point types for 'floatType' template parameter"); + + return detail::compute_compNormalize<L, T, floatType, Q, std::numeric_limits<T>::is_integer, std::numeric_limits<T>::is_signed>::call(v); + } + + template<typename T, length_t L, typename floatType, qualifier Q> + GLM_FUNC_QUALIFIER vec<L, T, Q> compScale(vec<L, floatType, Q> const& v) + { + GLM_STATIC_ASSERT(std::numeric_limits<floatType>::is_iec559, "'compScale' accepts only floating-point types for 'floatType' template parameter"); + + return detail::compute_compScale<L, T, floatType, Q, std::numeric_limits<T>::is_integer, std::numeric_limits<T>::is_signed>::call(v); + } + + template<length_t L, typename T, qualifier Q> + GLM_FUNC_QUALIFIER T compAdd(vec<L, T, Q> const& v) + { + T Result(0); + for(length_t i = 0, n = v.length(); i < n; ++i) + Result += v[i]; + return Result; + } + + template<length_t L, typename T, qualifier Q> + GLM_FUNC_QUALIFIER T compMul(vec<L, T, Q> const& v) + { + T Result(1); + for(length_t i = 0, n = v.length(); i < n; ++i) + Result *= v[i]; + return Result; + } + + template<length_t L, typename T, qualifier Q> + GLM_FUNC_QUALIFIER T compMin(vec<L, T, Q> 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<length_t L, typename T, qualifier Q> + GLM_FUNC_QUALIFIER T compMax(vec<L, T, Q> const& v) + { + T Result(v[0]); + for(length_t i = 1, n = v.length(); i < n; ++i) + Result = max(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 0000000000000000000000000000000000000000..6a51ab7d39ffd673cb7bb70d48b46b1c7e8b4c03 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/gtx/dual_quaternion.hpp @@ -0,0 +1,274 @@ +/// @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 <glm/gtx/dual_quaternion.hpp> 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" + +#if GLM_MESSAGES == GLM_ENABLE && !defined(GLM_EXT_INCLUDED) +# ifndef GLM_ENABLE_EXPERIMENTAL +# pragma message("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.") +# else +# pragma message("GLM: GLM_GTX_dual_quaternion extension included") +# endif +#endif + +namespace glm +{ + /// @addtogroup gtx_dual_quaternion + /// @{ + + template<typename T, qualifier Q = defaultp> + struct tdualquat + { + // -- Implementation detail -- + + typedef T value_type; + typedef qua<T, Q> part_type; + + // -- Data -- + + qua<T, Q> 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_FUNC_DECL GLM_CONSTEXPR tdualquat() GLM_DEFAULT; + GLM_FUNC_DECL GLM_CONSTEXPR tdualquat(tdualquat<T, Q> const& d) GLM_DEFAULT; + template<qualifier P> + GLM_FUNC_DECL GLM_CONSTEXPR tdualquat(tdualquat<T, P> const& d); + + // -- Explicit basic constructors -- + + GLM_FUNC_DECL GLM_CONSTEXPR tdualquat(qua<T, Q> const& real); + GLM_FUNC_DECL GLM_CONSTEXPR tdualquat(qua<T, Q> const& orientation, vec<3, T, Q> const& translation); + GLM_FUNC_DECL GLM_CONSTEXPR tdualquat(qua<T, Q> const& real, qua<T, Q> const& dual); + + // -- Conversion constructors -- + + template<typename U, qualifier P> + GLM_FUNC_DECL GLM_CONSTEXPR GLM_EXPLICIT tdualquat(tdualquat<U, P> const& q); + + GLM_FUNC_DECL GLM_EXPLICIT GLM_CONSTEXPR tdualquat(mat<2, 4, T, Q> const& holder_mat); + GLM_FUNC_DECL GLM_EXPLICIT GLM_CONSTEXPR tdualquat(mat<3, 4, T, Q> const& aug_mat); + + // -- Unary arithmetic operators -- + + GLM_FUNC_DECL tdualquat<T, Q> & operator=(tdualquat<T, Q> const& m) GLM_DEFAULT; + + template<typename U> + GLM_FUNC_DECL tdualquat<T, Q> & operator=(tdualquat<U, Q> const& m); + template<typename U> + GLM_FUNC_DECL tdualquat<T, Q> & operator*=(U s); + template<typename U> + GLM_FUNC_DECL tdualquat<T, Q> & operator/=(U s); + }; + + // -- Unary bit operators -- + + template<typename T, qualifier Q> + GLM_FUNC_DECL tdualquat<T, Q> operator+(tdualquat<T, Q> const& q); + + template<typename T, qualifier Q> + GLM_FUNC_DECL tdualquat<T, Q> operator-(tdualquat<T, Q> const& q); + + // -- Binary operators -- + + template<typename T, qualifier Q> + GLM_FUNC_DECL tdualquat<T, Q> operator+(tdualquat<T, Q> const& q, tdualquat<T, Q> const& p); + + template<typename T, qualifier Q> + GLM_FUNC_DECL tdualquat<T, Q> operator*(tdualquat<T, Q> const& q, tdualquat<T, Q> const& p); + + template<typename T, qualifier Q> + GLM_FUNC_DECL vec<3, T, Q> operator*(tdualquat<T, Q> const& q, vec<3, T, Q> const& v); + + template<typename T, qualifier Q> + GLM_FUNC_DECL vec<3, T, Q> operator*(vec<3, T, Q> const& v, tdualquat<T, Q> const& q); + + template<typename T, qualifier Q> + GLM_FUNC_DECL vec<4, T, Q> operator*(tdualquat<T, Q> const& q, vec<4, T, Q> const& v); + + template<typename T, qualifier Q> + GLM_FUNC_DECL vec<4, T, Q> operator*(vec<4, T, Q> const& v, tdualquat<T, Q> const& q); + + template<typename T, qualifier Q> + GLM_FUNC_DECL tdualquat<T, Q> operator*(tdualquat<T, Q> const& q, T const& s); + + template<typename T, qualifier Q> + GLM_FUNC_DECL tdualquat<T, Q> operator*(T const& s, tdualquat<T, Q> const& q); + + template<typename T, qualifier Q> + GLM_FUNC_DECL tdualquat<T, Q> operator/(tdualquat<T, Q> const& q, T const& s); + + // -- Boolean operators -- + + template<typename T, qualifier Q> + GLM_FUNC_DECL bool operator==(tdualquat<T, Q> const& q1, tdualquat<T, Q> const& q2); + + template<typename T, qualifier Q> + GLM_FUNC_DECL bool operator!=(tdualquat<T, Q> const& q1, tdualquat<T, Q> const& q2); + + /// Creates an identity dual quaternion. + /// + /// @see gtx_dual_quaternion + template <typename T, qualifier Q> + GLM_FUNC_DECL tdualquat<T, Q> dual_quat_identity(); + + /// Returns the normalized quaternion. + /// + /// @see gtx_dual_quaternion + template<typename T, qualifier Q> + GLM_FUNC_DECL tdualquat<T, Q> normalize(tdualquat<T, Q> const& q); + + /// Returns the linear interpolation of two dual quaternion. + /// + /// @see gtc_dual_quaternion + template<typename T, qualifier Q> + GLM_FUNC_DECL tdualquat<T, Q> lerp(tdualquat<T, Q> const& x, tdualquat<T, Q> const& y, T const& a); + + /// Returns the q inverse. + /// + /// @see gtx_dual_quaternion + template<typename T, qualifier Q> + GLM_FUNC_DECL tdualquat<T, Q> inverse(tdualquat<T, Q> const& q); + + /// Converts a quaternion to a 2 * 4 matrix. + /// + /// @see gtx_dual_quaternion + template<typename T, qualifier Q> + GLM_FUNC_DECL mat<2, 4, T, Q> mat2x4_cast(tdualquat<T, Q> const& x); + + /// Converts a quaternion to a 3 * 4 matrix. + /// + /// @see gtx_dual_quaternion + template<typename T, qualifier Q> + GLM_FUNC_DECL mat<3, 4, T, Q> mat3x4_cast(tdualquat<T, Q> const& x); + + /// Converts a 2 * 4 matrix (matrix which holds real and dual parts) to a quaternion. + /// + /// @see gtx_dual_quaternion + template<typename T, qualifier Q> + GLM_FUNC_DECL tdualquat<T, Q> 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<typename T, qualifier Q> + GLM_FUNC_DECL tdualquat<T, Q> dualquat_cast(mat<3, 4, T, Q> const& x); + + + /// Dual-quaternion of low single-qualifier floating-point numbers. + /// + /// @see gtx_dual_quaternion + typedef tdualquat<float, lowp> lowp_dualquat; + + /// Dual-quaternion of medium single-qualifier floating-point numbers. + /// + /// @see gtx_dual_quaternion + typedef tdualquat<float, mediump> mediump_dualquat; + + /// Dual-quaternion of high single-qualifier floating-point numbers. + /// + /// @see gtx_dual_quaternion + typedef tdualquat<float, highp> highp_dualquat; + + + /// Dual-quaternion of low single-qualifier floating-point numbers. + /// + /// @see gtx_dual_quaternion + typedef tdualquat<float, lowp> lowp_fdualquat; + + /// Dual-quaternion of medium single-qualifier floating-point numbers. + /// + /// @see gtx_dual_quaternion + typedef tdualquat<float, mediump> mediump_fdualquat; + + /// Dual-quaternion of high single-qualifier floating-point numbers. + /// + /// @see gtx_dual_quaternion + typedef tdualquat<float, highp> highp_fdualquat; + + + /// Dual-quaternion of low double-qualifier floating-point numbers. + /// + /// @see gtx_dual_quaternion + typedef tdualquat<double, lowp> lowp_ddualquat; + + /// Dual-quaternion of medium double-qualifier floating-point numbers. + /// + /// @see gtx_dual_quaternion + typedef tdualquat<double, mediump> mediump_ddualquat; + + /// Dual-quaternion of high double-qualifier floating-point numbers. + /// + /// @see gtx_dual_quaternion + typedef tdualquat<double, highp> 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 0000000000000000000000000000000000000000..fad07ea842c1f86ce0aba7e7c78bb85c3781fafe --- /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 <limits> + +namespace glm +{ + // -- Component accesses -- + + template<typename T, qualifier Q> + GLM_FUNC_QUALIFIER typename tdualquat<T, Q>::part_type & tdualquat<T, Q>::operator[](typename tdualquat<T, Q>::length_type i) + { + assert(i >= 0 && i < this->length()); + return (&real)[i]; + } + + template<typename T, qualifier Q> + GLM_FUNC_QUALIFIER typename tdualquat<T, Q>::part_type const& tdualquat<T, Q>::operator[](typename tdualquat<T, Q>::length_type i) const + { + assert(i >= 0 && i < this->length()); + return (&real)[i]; + } + + // -- Implicit basic constructors -- + +# if GLM_CONFIG_DEFAULTED_FUNCTIONS == GLM_DISABLE + template<typename T, qualifier Q> + GLM_FUNC_QUALIFIER GLM_CONSTEXPR tdualquat<T, Q>::tdualquat() +# if GLM_CONFIG_DEFAULTED_FUNCTIONS != GLM_DISABLE + : real(qua<T, Q>()) + , dual(qua<T, Q>(0, 0, 0, 0)) +# endif + {} + + template<typename T, qualifier Q> + GLM_FUNC_QUALIFIER GLM_CONSTEXPR tdualquat<T, Q>::tdualquat(tdualquat<T, Q> const& d) + : real(d.real) + , dual(d.dual) + {} +# endif + + template<typename T, qualifier Q> + template<qualifier P> + GLM_FUNC_QUALIFIER GLM_CONSTEXPR tdualquat<T, Q>::tdualquat(tdualquat<T, P> const& d) + : real(d.real) + , dual(d.dual) + {} + + // -- Explicit basic constructors -- + + template<typename T, qualifier Q> + GLM_FUNC_QUALIFIER GLM_CONSTEXPR tdualquat<T, Q>::tdualquat(qua<T, Q> const& r) + : real(r), dual(qua<T, Q>(0, 0, 0, 0)) + {} + + template<typename T, qualifier Q> + GLM_FUNC_QUALIFIER GLM_CONSTEXPR tdualquat<T, Q>::tdualquat(qua<T, Q> const& q, vec<3, T, Q> const& p) + : real(q), dual( + 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<typename T, qualifier Q> + GLM_FUNC_QUALIFIER GLM_CONSTEXPR tdualquat<T, Q>::tdualquat(qua<T, Q> const& r, qua<T, Q> const& d) + : real(r), dual(d) + {} + + // -- Conversion constructors -- + + template<typename T, qualifier Q> + template<typename U, qualifier P> + GLM_FUNC_QUALIFIER GLM_CONSTEXPR tdualquat<T, Q>::tdualquat(tdualquat<U, P> const& q) + : real(q.real) + , dual(q.dual) + {} + + template<typename T, qualifier Q> + GLM_FUNC_QUALIFIER GLM_CONSTEXPR tdualquat<T, Q>::tdualquat(mat<2, 4, T, Q> const& m) + { + *this = dualquat_cast(m); + } + + template<typename T, qualifier Q> + GLM_FUNC_QUALIFIER GLM_CONSTEXPR tdualquat<T, Q>::tdualquat(mat<3, 4, T, Q> const& m) + { + *this = dualquat_cast(m); + } + + // -- Unary arithmetic operators -- + +# if GLM_CONFIG_DEFAULTED_FUNCTIONS == GLM_DISABLE + template<typename T, qualifier Q> + GLM_FUNC_QUALIFIER tdualquat<T, Q> & tdualquat<T, Q>::operator=(tdualquat<T, Q> const& q) + { + this->real = q.real; + this->dual = q.dual; + return *this; + } +# endif + + template<typename T, qualifier Q> + template<typename U> + GLM_FUNC_QUALIFIER tdualquat<T, Q> & tdualquat<T, Q>::operator=(tdualquat<U, Q> const& q) + { + this->real = q.real; + this->dual = q.dual; + return *this; + } + + template<typename T, qualifier Q> + template<typename U> + GLM_FUNC_QUALIFIER tdualquat<T, Q> & tdualquat<T, Q>::operator*=(U s) + { + this->real *= static_cast<T>(s); + this->dual *= static_cast<T>(s); + return *this; + } + + template<typename T, qualifier Q> + template<typename U> + GLM_FUNC_QUALIFIER tdualquat<T, Q> & tdualquat<T, Q>::operator/=(U s) + { + this->real /= static_cast<T>(s); + this->dual /= static_cast<T>(s); + return *this; + } + + // -- Unary bit operators -- + + template<typename T, qualifier Q> + GLM_FUNC_QUALIFIER tdualquat<T, Q> operator+(tdualquat<T, Q> const& q) + { + return q; + } + + template<typename T, qualifier Q> + GLM_FUNC_QUALIFIER tdualquat<T, Q> operator-(tdualquat<T, Q> const& q) + { + return tdualquat<T, Q>(-q.real, -q.dual); + } + + // -- Binary operators -- + + template<typename T, qualifier Q> + GLM_FUNC_QUALIFIER tdualquat<T, Q> operator+(tdualquat<T, Q> const& q, tdualquat<T, Q> const& p) + { + return tdualquat<T, Q>(q.real + p.real,q.dual + p.dual); + } + + template<typename T, qualifier Q> + GLM_FUNC_QUALIFIER tdualquat<T, Q> operator*(tdualquat<T, Q> const& p, tdualquat<T, Q> const& o) + { + return tdualquat<T, Q>(p.real * o.real,p.real * o.dual + p.dual * o.real); + } + + template<typename T, qualifier Q> + GLM_FUNC_QUALIFIER vec<3, T, Q> operator*(tdualquat<T, Q> 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<typename T, qualifier Q> + GLM_FUNC_QUALIFIER vec<3, T, Q> operator*(vec<3, T, Q> const& v, tdualquat<T, Q> const& q) + { + return glm::inverse(q) * v; + } + + template<typename T, qualifier Q> + GLM_FUNC_QUALIFIER vec<4, T, Q> operator*(tdualquat<T, Q> const& q, vec<4, T, Q> const& v) + { + return vec<4, T, Q>(q * vec<3, T, Q>(v), v.w); + } + + template<typename T, qualifier Q> + GLM_FUNC_QUALIFIER vec<4, T, Q> operator*(vec<4, T, Q> const& v, tdualquat<T, Q> const& q) + { + return glm::inverse(q) * v; + } + + template<typename T, qualifier Q> + GLM_FUNC_QUALIFIER tdualquat<T, Q> operator*(tdualquat<T, Q> const& q, T const& s) + { + return tdualquat<T, Q>(q.real * s, q.dual * s); + } + + template<typename T, qualifier Q> + GLM_FUNC_QUALIFIER tdualquat<T, Q> operator*(T const& s, tdualquat<T, Q> const& q) + { + return q * s; + } + + template<typename T, qualifier Q> + GLM_FUNC_QUALIFIER tdualquat<T, Q> operator/(tdualquat<T, Q> const& q, T const& s) + { + return tdualquat<T, Q>(q.real / s, q.dual / s); + } + + // -- Boolean operators -- + + template<typename T, qualifier Q> + GLM_FUNC_QUALIFIER bool operator==(tdualquat<T, Q> const& q1, tdualquat<T, Q> const& q2) + { + return (q1.real == q2.real) && (q1.dual == q2.dual); + } + + template<typename T, qualifier Q> + GLM_FUNC_QUALIFIER bool operator!=(tdualquat<T, Q> const& q1, tdualquat<T, Q> const& q2) + { + return (q1.real != q2.real) || (q1.dual != q2.dual); + } + + // -- Operations -- + + template<typename T, qualifier Q> + GLM_FUNC_QUALIFIER tdualquat<T, Q> dual_quat_identity() + { + return tdualquat<T, Q>( + qua<T, Q>(static_cast<T>(1), static_cast<T>(0), static_cast<T>(0), static_cast<T>(0)), + qua<T, Q>(static_cast<T>(0), static_cast<T>(0), static_cast<T>(0), static_cast<T>(0))); + } + + template<typename T, qualifier Q> + GLM_FUNC_QUALIFIER tdualquat<T, Q> normalize(tdualquat<T, Q> const& q) + { + return q / length(q.real); + } + + template<typename T, qualifier Q> + GLM_FUNC_QUALIFIER tdualquat<T, Q> lerp(tdualquat<T, Q> const& x, tdualquat<T, Q> const& y, T const& a) + { + // Dual Quaternion Linear blend aka DLB: + // Lerp is only defined in [0, 1] + assert(a >= static_cast<T>(0)); + assert(a <= static_cast<T>(1)); + T const k = dot(x.real,y.real) < static_cast<T>(0) ? -a : a; + T const one(1); + return tdualquat<T, Q>(x * (one - a) + y * k); + } + + template<typename T, qualifier Q> + GLM_FUNC_QUALIFIER tdualquat<T, Q> inverse(tdualquat<T, Q> const& q) + { + const glm::qua<T, Q> real = conjugate(q.real); + const glm::qua<T, Q> dual = conjugate(q.dual); + return tdualquat<T, Q>(real, dual + (real * (-2.0f * dot(real,dual)))); + } + + template<typename T, qualifier Q> + GLM_FUNC_QUALIFIER mat<2, 4, T, Q> mat2x4_cast(tdualquat<T, Q> 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<typename T, qualifier Q> + GLM_FUNC_QUALIFIER mat<3, 4, T, Q> mat3x4_cast(tdualquat<T, Q> const& x) + { + qua<T, Q> r = x.real / length2(x.real); + + qua<T, Q> 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<T>(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<typename T, qualifier Q> + GLM_FUNC_QUALIFIER tdualquat<T, Q> dualquat_cast(mat<2, 4, T, Q> const& x) + { + return tdualquat<T, Q>( + qua<T, Q>( x[0].w, x[0].x, x[0].y, x[0].z ), + qua<T, Q>( x[1].w, x[1].x, x[1].y, x[1].z )); + } + + template<typename T, qualifier Q> + GLM_FUNC_QUALIFIER tdualquat<T, Q> dualquat_cast(mat<3, 4, T, Q> const& x) + { + qua<T, Q> real; + + T const trace = x[0].x + x[1].y + x[2].z; + if(trace > static_cast<T>(0)) + { + T const r = sqrt(T(1) + trace); + T const invr = static_cast<T>(0.5) / r; + real.w = static_cast<T>(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<T>(0.5) / r; + real.x = static_cast<T>(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<T>(0.5) / r; + real.x = (x[1].x + x[0].y) * invr; + real.y = static_cast<T>(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<T>(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<T>(0.5) * r; + real.w = (x[1].x - x[0].y) * invr; + } + + qua<T, Q> dual; + dual.x = static_cast<T>(0.5) * ( x[0].w * real.w + x[1].w * real.z - x[2].w * real.y); + dual.y = static_cast<T>(0.5) * (-x[0].w * real.z + x[1].w * real.w + x[2].w * real.x); + dual.z = static_cast<T>(0.5) * ( x[0].w * real.y - x[1].w * real.x + x[2].w * real.w); + dual.w = -static_cast<T>(0.5) * ( x[0].w * real.x + x[1].w * real.y + x[2].w * real.z); + return tdualquat<T, Q>(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 0000000000000000000000000000000000000000..57f3d61b182672fa9aac192ff78a64ee1e7df395 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/gtx/easing.hpp @@ -0,0 +1,219 @@ +/// @ref gtx_easing +/// @file glm/gtx/easing.hpp +/// @author Robert Chisholm +/// +/// @see core (dependence) +/// +/// @defgroup gtx_easing GLM_GTX_easing +/// @ingroup gtx +/// +/// Include <glm/gtx/easing.hpp> to use the features of this extension. +/// +/// Easing functions for animations and transitons +/// 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" + +#if GLM_MESSAGES == GLM_ENABLE && !defined(GLM_EXT_INCLUDED) +# ifndef GLM_ENABLE_EXPERIMENTAL +# pragma message("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.") +# else +# pragma message("GLM: GLM_GTX_easing extension included") +# endif +#endif + +namespace glm{ + /// @addtogroup gtx_easing + /// @{ + + /// Modelled after the line y = x + /// @see gtx_easing + template <typename genType> + GLM_FUNC_DECL genType linearInterpolation(genType const & a); + + /// Modelled after the parabola y = x^2 + /// @see gtx_easing + template <typename genType> + GLM_FUNC_DECL genType quadraticEaseIn(genType const & a); + + /// Modelled after the parabola y = -x^2 + 2x + /// @see gtx_easing + template <typename genType> + 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 <typename genType> + GLM_FUNC_DECL genType quadraticEaseInOut(genType const & a); + + /// Modelled after the cubic y = x^3 + template <typename genType> + GLM_FUNC_DECL genType cubicEaseIn(genType const & a); + + /// Modelled after the cubic y = (x - 1)^3 + 1 + /// @see gtx_easing + template <typename genType> + 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 <typename genType> + GLM_FUNC_DECL genType cubicEaseInOut(genType const & a); + + /// Modelled after the quartic x^4 + /// @see gtx_easing + template <typename genType> + GLM_FUNC_DECL genType quarticEaseIn(genType const & a); + + /// Modelled after the quartic y = 1 - (x - 1)^4 + /// @see gtx_easing + template <typename genType> + 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 <typename genType> + GLM_FUNC_DECL genType quarticEaseInOut(genType const & a); + + /// Modelled after the quintic y = x^5 + /// @see gtx_easing + template <typename genType> + GLM_FUNC_DECL genType quinticEaseIn(genType const & a); + + /// Modelled after the quintic y = (x - 1)^5 + 1 + /// @see gtx_easing + template <typename genType> + 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 <typename genType> + GLM_FUNC_DECL genType quinticEaseInOut(genType const & a); + + /// Modelled after quarter-cycle of sine wave + /// @see gtx_easing + template <typename genType> + GLM_FUNC_DECL genType sineEaseIn(genType const & a); + + /// Modelled after quarter-cycle of sine wave (different phase) + /// @see gtx_easing + template <typename genType> + GLM_FUNC_DECL genType sineEaseOut(genType const & a); + + /// Modelled after half sine wave + /// @see gtx_easing + template <typename genType> + GLM_FUNC_DECL genType sineEaseInOut(genType const & a); + + /// Modelled after shifted quadrant IV of unit circle + /// @see gtx_easing + template <typename genType> + GLM_FUNC_DECL genType circularEaseIn(genType const & a); + + /// Modelled after shifted quadrant II of unit circle + /// @see gtx_easing + template <typename genType> + 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 <typename genType> + GLM_FUNC_DECL genType circularEaseInOut(genType const & a); + + /// Modelled after the exponential function y = 2^(10(x - 1)) + /// @see gtx_easing + template <typename genType> + GLM_FUNC_DECL genType exponentialEaseIn(genType const & a); + + /// Modelled after the exponential function y = -2^(-10x) + 1 + /// @see gtx_easing + template <typename genType> + 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 <typename genType> + 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 <typename genType> + 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 <typename genType> + 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 <typename genType> + GLM_FUNC_DECL genType elasticEaseInOut(genType const & a); + + /// @see gtx_easing + template <typename genType> + GLM_FUNC_DECL genType backEaseIn(genType const& a); + + /// @see gtx_easing + template <typename genType> + GLM_FUNC_DECL genType backEaseOut(genType const& a); + + /// @see gtx_easing + template <typename genType> + GLM_FUNC_DECL genType backEaseInOut(genType const& a); + + /// @param a parameter + /// @param o Optional overshoot modifier + /// @see gtx_easing + template <typename genType> + GLM_FUNC_DECL genType backEaseIn(genType const& a, genType const& o); + + /// @param a parameter + /// @param o Optional overshoot modifier + /// @see gtx_easing + template <typename genType> + GLM_FUNC_DECL genType backEaseOut(genType const& a, genType const& o); + + /// @param a parameter + /// @param o Optional overshoot modifier + /// @see gtx_easing + template <typename genType> + GLM_FUNC_DECL genType backEaseInOut(genType const& a, genType const& o); + + /// @see gtx_easing + template <typename genType> + GLM_FUNC_DECL genType bounceEaseIn(genType const& a); + + /// @see gtx_easing + template <typename genType> + GLM_FUNC_DECL genType bounceEaseOut(genType const& a); + + /// @see gtx_easing + template <typename genType> + 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 0000000000000000000000000000000000000000..4b7d05b719600ab2121f5c34f945f403a556225b --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/gtx/easing.inl @@ -0,0 +1,436 @@ +/// @ref gtx_easing + +#include <cmath> + +namespace glm{ + + template <typename genType> + GLM_FUNC_QUALIFIER genType linearInterpolation(genType const& a) + { + // Only defined in [0, 1] + assert(a >= zero<genType>()); + assert(a <= one<genType>()); + + return a; + } + + template <typename genType> + GLM_FUNC_QUALIFIER genType quadraticEaseIn(genType const& a) + { + // Only defined in [0, 1] + assert(a >= zero<genType>()); + assert(a <= one<genType>()); + + return a * a; + } + + template <typename genType> + GLM_FUNC_QUALIFIER genType quadraticEaseOut(genType const& a) + { + // Only defined in [0, 1] + assert(a >= zero<genType>()); + assert(a <= one<genType>()); + + return -(a * (a - static_cast<genType>(2))); + } + + template <typename genType> + GLM_FUNC_QUALIFIER genType quadraticEaseInOut(genType const& a) + { + // Only defined in [0, 1] + assert(a >= zero<genType>()); + assert(a <= one<genType>()); + + if(a < static_cast<genType>(0.5)) + { + return static_cast<genType>(2) * a * a; + } + else + { + return (-static_cast<genType>(2) * a * a) + (4 * a) - one<genType>(); + } + } + + template <typename genType> + GLM_FUNC_QUALIFIER genType cubicEaseIn(genType const& a) + { + // Only defined in [0, 1] + assert(a >= zero<genType>()); + assert(a <= one<genType>()); + + return a * a * a; + } + + template <typename genType> + GLM_FUNC_QUALIFIER genType cubicEaseOut(genType const& a) + { + // Only defined in [0, 1] + assert(a >= zero<genType>()); + assert(a <= one<genType>()); + + genType const f = a - one<genType>(); + return f * f * f + one<genType>(); + } + + template <typename genType> + GLM_FUNC_QUALIFIER genType cubicEaseInOut(genType const& a) + { + // Only defined in [0, 1] + assert(a >= zero<genType>()); + assert(a <= one<genType>()); + + if (a < static_cast<genType>(0.5)) + { + return static_cast<genType>(4) * a * a * a; + } + else + { + genType const f = ((static_cast<genType>(2) * a) - static_cast<genType>(2)); + return static_cast<genType>(0.5) * f * f * f + one<genType>(); + } + } + + template <typename genType> + GLM_FUNC_QUALIFIER genType quarticEaseIn(genType const& a) + { + // Only defined in [0, 1] + assert(a >= zero<genType>()); + assert(a <= one<genType>()); + + return a * a * a * a; + } + + template <typename genType> + GLM_FUNC_QUALIFIER genType quarticEaseOut(genType const& a) + { + // Only defined in [0, 1] + assert(a >= zero<genType>()); + assert(a <= one<genType>()); + + genType const f = (a - one<genType>()); + return f * f * f * (one<genType>() - a) + one<genType>(); + } + + template <typename genType> + GLM_FUNC_QUALIFIER genType quarticEaseInOut(genType const& a) + { + // Only defined in [0, 1] + assert(a >= zero<genType>()); + assert(a <= one<genType>()); + + if(a < static_cast<genType>(0.5)) + { + return static_cast<genType>(8) * a * a * a * a; + } + else + { + genType const f = (a - one<genType>()); + return -static_cast<genType>(8) * f * f * f * f + one<genType>(); + } + } + + template <typename genType> + GLM_FUNC_QUALIFIER genType quinticEaseIn(genType const& a) + { + // Only defined in [0, 1] + assert(a >= zero<genType>()); + assert(a <= one<genType>()); + + return a * a * a * a * a; + } + + template <typename genType> + GLM_FUNC_QUALIFIER genType quinticEaseOut(genType const& a) + { + // Only defined in [0, 1] + assert(a >= zero<genType>()); + assert(a <= one<genType>()); + + genType const f = (a - one<genType>()); + return f * f * f * f * f + one<genType>(); + } + + template <typename genType> + GLM_FUNC_QUALIFIER genType quinticEaseInOut(genType const& a) + { + // Only defined in [0, 1] + assert(a >= zero<genType>()); + assert(a <= one<genType>()); + + if(a < static_cast<genType>(0.5)) + { + return static_cast<genType>(16) * a * a * a * a * a; + } + else + { + genType const f = ((static_cast<genType>(2) * a) - static_cast<genType>(2)); + return static_cast<genType>(0.5) * f * f * f * f * f + one<genType>(); + } + } + + template <typename genType> + GLM_FUNC_QUALIFIER genType sineEaseIn(genType const& a) + { + // Only defined in [0, 1] + assert(a >= zero<genType>()); + assert(a <= one<genType>()); + + return sin((a - one<genType>()) * half_pi<genType>()) + one<genType>(); + } + + template <typename genType> + GLM_FUNC_QUALIFIER genType sineEaseOut(genType const& a) + { + // Only defined in [0, 1] + assert(a >= zero<genType>()); + assert(a <= one<genType>()); + + return sin(a * half_pi<genType>()); + } + + template <typename genType> + GLM_FUNC_QUALIFIER genType sineEaseInOut(genType const& a) + { + // Only defined in [0, 1] + assert(a >= zero<genType>()); + assert(a <= one<genType>()); + + return static_cast<genType>(0.5) * (one<genType>() - cos(a * pi<genType>())); + } + + template <typename genType> + GLM_FUNC_QUALIFIER genType circularEaseIn(genType const& a) + { + // Only defined in [0, 1] + assert(a >= zero<genType>()); + assert(a <= one<genType>()); + + return one<genType>() - sqrt(one<genType>() - (a * a)); + } + + template <typename genType> + GLM_FUNC_QUALIFIER genType circularEaseOut(genType const& a) + { + // Only defined in [0, 1] + assert(a >= zero<genType>()); + assert(a <= one<genType>()); + + return sqrt((static_cast<genType>(2) - a) * a); + } + + template <typename genType> + GLM_FUNC_QUALIFIER genType circularEaseInOut(genType const& a) + { + // Only defined in [0, 1] + assert(a >= zero<genType>()); + assert(a <= one<genType>()); + + if(a < static_cast<genType>(0.5)) + { + return static_cast<genType>(0.5) * (one<genType>() - std::sqrt(one<genType>() - static_cast<genType>(4) * (a * a))); + } + else + { + return static_cast<genType>(0.5) * (std::sqrt(-((static_cast<genType>(2) * a) - static_cast<genType>(3)) * ((static_cast<genType>(2) * a) - one<genType>())) + one<genType>()); + } + } + + template <typename genType> + GLM_FUNC_QUALIFIER genType exponentialEaseIn(genType const& a) + { + // Only defined in [0, 1] + assert(a >= zero<genType>()); + assert(a <= one<genType>()); + + if(a <= zero<genType>()) + return a; + else + { + genType const Complementary = a - one<genType>(); + genType const Two = static_cast<genType>(2); + + return glm::pow(Two, Complementary * static_cast<genType>(10)); + } + } + + template <typename genType> + GLM_FUNC_QUALIFIER genType exponentialEaseOut(genType const& a) + { + // Only defined in [0, 1] + assert(a >= zero<genType>()); + assert(a <= one<genType>()); + + if(a >= one<genType>()) + return a; + else + { + return one<genType>() - glm::pow(static_cast<genType>(2), -static_cast<genType>(10) * a); + } + } + + template <typename genType> + GLM_FUNC_QUALIFIER genType exponentialEaseInOut(genType const& a) + { + // Only defined in [0, 1] + assert(a >= zero<genType>()); + assert(a <= one<genType>()); + + if(a < static_cast<genType>(0.5)) + return static_cast<genType>(0.5) * glm::pow(static_cast<genType>(2), (static_cast<genType>(20) * a) - static_cast<genType>(10)); + else + return -static_cast<genType>(0.5) * glm::pow(static_cast<genType>(2), (-static_cast<genType>(20) * a) + static_cast<genType>(10)) + one<genType>(); + } + + template <typename genType> + GLM_FUNC_QUALIFIER genType elasticEaseIn(genType const& a) + { + // Only defined in [0, 1] + assert(a >= zero<genType>()); + assert(a <= one<genType>()); + + return std::sin(static_cast<genType>(13) * half_pi<genType>() * a) * glm::pow(static_cast<genType>(2), static_cast<genType>(10) * (a - one<genType>())); + } + + template <typename genType> + GLM_FUNC_QUALIFIER genType elasticEaseOut(genType const& a) + { + // Only defined in [0, 1] + assert(a >= zero<genType>()); + assert(a <= one<genType>()); + + return std::sin(-static_cast<genType>(13) * half_pi<genType>() * (a + one<genType>())) * glm::pow(static_cast<genType>(2), -static_cast<genType>(10) * a) + one<genType>(); + } + + template <typename genType> + GLM_FUNC_QUALIFIER genType elasticEaseInOut(genType const& a) + { + // Only defined in [0, 1] + assert(a >= zero<genType>()); + assert(a <= one<genType>()); + + if(a < static_cast<genType>(0.5)) + return static_cast<genType>(0.5) * std::sin(static_cast<genType>(13) * half_pi<genType>() * (static_cast<genType>(2) * a)) * glm::pow(static_cast<genType>(2), static_cast<genType>(10) * ((static_cast<genType>(2) * a) - one<genType>())); + else + return static_cast<genType>(0.5) * (std::sin(-static_cast<genType>(13) * half_pi<genType>() * ((static_cast<genType>(2) * a - one<genType>()) + one<genType>())) * glm::pow(static_cast<genType>(2), -static_cast<genType>(10) * (static_cast<genType>(2) * a - one<genType>())) + static_cast<genType>(2)); + } + + template <typename genType> + GLM_FUNC_QUALIFIER genType backEaseIn(genType const& a, genType const& o) + { + // Only defined in [0, 1] + assert(a >= zero<genType>()); + assert(a <= one<genType>()); + + genType z = ((o + one<genType>()) * a) - o; + return (a * a * z); + } + + template <typename genType> + GLM_FUNC_QUALIFIER genType backEaseOut(genType const& a, genType const& o) + { + // Only defined in [0, 1] + assert(a >= zero<genType>()); + assert(a <= one<genType>()); + + genType n = a - one<genType>(); + genType z = ((o + one<genType>()) * n) + o; + return (n * n * z) + one<genType>(); + } + + template <typename genType> + GLM_FUNC_QUALIFIER genType backEaseInOut(genType const& a, genType const& o) + { + // Only defined in [0, 1] + assert(a >= zero<genType>()); + assert(a <= one<genType>()); + + genType s = o * static_cast<genType>(1.525); + genType x = static_cast<genType>(0.5); + genType n = a / static_cast<genType>(0.5); + + if (n < static_cast<genType>(1)) + { + genType z = ((s + static_cast<genType>(1)) * n) - s; + genType m = n * n * z; + return x * m; + } + else + { + n -= static_cast<genType>(2); + genType z = ((s + static_cast<genType>(1)) * n) + s; + genType m = (n*n*z) + static_cast<genType>(2); + return x * m; + } + } + + template <typename genType> + GLM_FUNC_QUALIFIER genType backEaseIn(genType const& a) + { + return backEaseIn(a, static_cast<genType>(1.70158)); + } + + template <typename genType> + GLM_FUNC_QUALIFIER genType backEaseOut(genType const& a) + { + return backEaseOut(a, static_cast<genType>(1.70158)); + } + + template <typename genType> + GLM_FUNC_QUALIFIER genType backEaseInOut(genType const& a) + { + return backEaseInOut(a, static_cast<genType>(1.70158)); + } + + template <typename genType> + GLM_FUNC_QUALIFIER genType bounceEaseOut(genType const& a) + { + // Only defined in [0, 1] + assert(a >= zero<genType>()); + assert(a <= one<genType>()); + + if(a < static_cast<genType>(4.0 / 11.0)) + { + return (static_cast<genType>(121) * a * a) / static_cast<genType>(16); + } + else if(a < static_cast<genType>(8.0 / 11.0)) + { + return (static_cast<genType>(363.0 / 40.0) * a * a) - (static_cast<genType>(99.0 / 10.0) * a) + static_cast<genType>(17.0 / 5.0); + } + else if(a < static_cast<genType>(9.0 / 10.0)) + { + return (static_cast<genType>(4356.0 / 361.0) * a * a) - (static_cast<genType>(35442.0 / 1805.0) * a) + static_cast<genType>(16061.0 / 1805.0); + } + else + { + return (static_cast<genType>(54.0 / 5.0) * a * a) - (static_cast<genType>(513.0 / 25.0) * a) + static_cast<genType>(268.0 / 25.0); + } + } + + template <typename genType> + GLM_FUNC_QUALIFIER genType bounceEaseIn(genType const& a) + { + // Only defined in [0, 1] + assert(a >= zero<genType>()); + assert(a <= one<genType>()); + + return one<genType>() - bounceEaseOut(one<genType>() - a); + } + + template <typename genType> + GLM_FUNC_QUALIFIER genType bounceEaseInOut(genType const& a) + { + // Only defined in [0, 1] + assert(a >= zero<genType>()); + assert(a <= one<genType>()); + + if(a < static_cast<genType>(0.5)) + { + return static_cast<genType>(0.5) * (one<genType>() - bounceEaseOut(a * static_cast<genType>(2))); + } + else + { + return static_cast<genType>(0.5) * bounceEaseOut(a * static_cast<genType>(2) - one<genType>()) + static_cast<genType>(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 0000000000000000000000000000000000000000..27236973af6079a54aa1183d3d50f38d381a1ab3 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/gtx/euler_angles.hpp @@ -0,0 +1,335 @@ +/// @ref gtx_euler_angles +/// @file glm/gtx/euler_angles.hpp +/// +/// @see core (dependence) +/// +/// @defgroup gtx_euler_angles GLM_GTX_euler_angles +/// @ingroup gtx +/// +/// Include <glm/gtx/euler_angles.hpp> 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" + +#if GLM_MESSAGES == GLM_ENABLE && !defined(GLM_EXT_INCLUDED) +# ifndef GLM_ENABLE_EXPERIMENTAL +# pragma message("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.") +# else +# pragma message("GLM: GLM_GTX_euler_angles extension included") +# endif +#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<typename T> + 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<typename T> + 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<typename T> + 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 <typename T> + 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 <typename T> + 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 <typename T> + 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<typename T> + 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<typename T> + 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<typename T> + 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<typename T> + 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<typename T> + 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<typename T> + 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<typename T> + 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<typename T> + 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 <typename T> + 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 <typename T> + 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 <typename T> + 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 <typename T> + 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 <typename T> + 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 <typename T> + 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 <typename T> + 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 <typename T> + 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 <typename T> + 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 <typename T> + 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<typename T> + 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<typename T> + 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<typename T> + 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<typename T, qualifier Q> + 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<typename T, qualifier Q> + 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<typename T> + GLM_FUNC_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 <typename T> + GLM_FUNC_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 <typename T> + GLM_FUNC_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 <typename T> + GLM_FUNC_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 <typename T> + GLM_FUNC_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 <typename T> + GLM_FUNC_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 <typename T> + GLM_FUNC_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 <typename T> + GLM_FUNC_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 <typename T> + GLM_FUNC_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 <typename T> + GLM_FUNC_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 <typename T> + GLM_FUNC_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 <typename T> + GLM_FUNC_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 0000000000000000000000000000000000000000..68c50124e80eb446a454508bf925f62247cb04e5 --- /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<typename T> + 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<typename T> + 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<typename T> + 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 <typename T> + 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 <typename T> + 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 <typename T> + 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<typename T> + 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<typename T> + 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<typename T> + GLM_FUNC_QUALIFIER mat<4, 4, T, defaultp> eulerAngleXZ + ( + T const& angleX, + T const& angleZ + ) + { + return eulerAngleX(angleX) * eulerAngleZ(angleZ); + } + + template<typename T> + GLM_FUNC_QUALIFIER mat<4, 4, T, defaultp> eulerAngleZX + ( + T const& angleZ, + T const& angleX + ) + { + return eulerAngleZ(angleZ) * eulerAngleX(angleX); + } + + template<typename T> + GLM_FUNC_QUALIFIER mat<4, 4, T, defaultp> eulerAngleYZ + ( + T const& angleY, + T const& angleZ + ) + { + return eulerAngleY(angleY) * eulerAngleZ(angleZ); + } + + template<typename T> + GLM_FUNC_QUALIFIER mat<4, 4, T, defaultp> eulerAngleZY + ( + T const& angleZ, + T const& angleY + ) + { + return eulerAngleZ(angleZ) * eulerAngleY(angleY); + } + + template<typename T> + 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<T>(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<T>(0); + Result[2][0] =-s2; + Result[2][1] = s1 * c2; + Result[2][2] = c1 * c2; + Result[2][3] = static_cast<T>(0); + Result[3][0] = static_cast<T>(0); + Result[3][1] = static_cast<T>(0); + Result[3][2] = static_cast<T>(0); + Result[3][3] = static_cast<T>(1); + return Result; + } + + template<typename T> + 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<T>(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<T>(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<T>(0); + Result[3][0] = static_cast<T>(0); + Result[3][1] = static_cast<T>(0); + Result[3][2] = static_cast<T>(0); + Result[3][3] = static_cast<T>(1); + return Result; + } + + template <typename T> + 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<T>(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<T>(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<T>(0); + Result[3][0] = static_cast<T>(0); + Result[3][1] = static_cast<T>(0); + Result[3][2] = static_cast<T>(0); + Result[3][3] = static_cast<T>(1); + return Result; + } + + template <typename T> + 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<T>(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<T>(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<T>(0); + Result[3][0] = static_cast<T>(0); + Result[3][1] = static_cast<T>(0); + Result[3][2] = static_cast<T>(0); + Result[3][3] = static_cast<T>(1); + return Result; + } + + template <typename T> + 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<T>(0); + Result[1][0] = s1 * s2; + Result[1][1] = c2; + Result[1][2] = c1 * s2; + Result[1][3] = static_cast<T>(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<T>(0); + Result[3][0] = static_cast<T>(0); + Result[3][1] = static_cast<T>(0); + Result[3][2] = static_cast<T>(0); + Result[3][3] = static_cast<T>(1); + return Result; + } + + template <typename T> + 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<T>(0); + Result[1][0] =-c1 * s2; + Result[1][1] = c2; + Result[1][2] = s1 * s2; + Result[1][3] = static_cast<T>(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<T>(0); + Result[3][0] = static_cast<T>(0); + Result[3][1] = static_cast<T>(0); + Result[3][2] = static_cast<T>(0); + Result[3][3] = static_cast<T>(1); + return Result; + } + + template <typename T> + 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<T>(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<T>(0); + Result[2][0] = c1 * s2; + Result[2][1] = s1 * s2; + Result[2][2] = c2; + Result[2][3] = static_cast<T>(0); + Result[3][0] = static_cast<T>(0); + Result[3][1] = static_cast<T>(0); + Result[3][2] = static_cast<T>(0); + Result[3][3] = static_cast<T>(1); + return Result; + } + + template <typename T> + 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<T>(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<T>(0); + Result[2][0] = s1 * s2; + Result[2][1] =-c1 * s2; + Result[2][2] = c2; + Result[2][3] = static_cast<T>(0); + Result[3][0] = static_cast<T>(0); + Result[3][1] = static_cast<T>(0); + Result[3][2] = static_cast<T>(0); + Result[3][3] = static_cast<T>(1); + return Result; + } + + template <typename T> + 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<T>(0); + Result[1][0] =-s2; + Result[1][1] = c1 * c2; + Result[1][2] = c2 * s1; + Result[1][3] = static_cast<T>(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<T>(0); + Result[3][0] = static_cast<T>(0); + Result[3][1] = static_cast<T>(0); + Result[3][2] = static_cast<T>(0); + Result[3][3] = static_cast<T>(1); + return Result; + } + + template <typename T> + 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<T>(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<T>(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<T>(0); + Result[3][0] = static_cast<T>(0); + Result[3][1] = static_cast<T>(0); + Result[3][2] = static_cast<T>(0); + Result[3][3] = static_cast<T>(1); + return Result; + } + + template <typename T> + 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<T>(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<T>(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<T>(0); + Result[3][0] = static_cast<T>(0); + Result[3][1] = static_cast<T>(0); + Result[3][2] = static_cast<T>(0); + Result[3][3] = static_cast<T>(1); + return Result; + } + + template <typename T> + 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<T>(0); + Result[1][0] =-c2 * s1; + Result[1][1] = c1 * c2; + Result[1][2] = s2; + Result[1][3] = static_cast<T>(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<T>(0); + Result[3][0] = static_cast<T>(0); + Result[3][1] = static_cast<T>(0); + Result[3][2] = static_cast<T>(0); + Result[3][3] = static_cast<T>(1); + return Result; + } + + template<typename T> + 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<T>(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<T>(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<T>(0); + Result[3][0] = static_cast<T>(0); + Result[3][1] = static_cast<T>(0); + Result[3][2] = static_cast<T>(0); + Result[3][3] = static_cast<T>(1); + return Result; + } + + template<typename T> + 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<typename T> + 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] = 0.0f; + Result[1][0] = -s; + Result[1][1] = c; + Result[1][2] = 0.0f; + Result[2][0] = 0.0f; + Result[2][1] = 0.0f; + Result[2][2] = 1.0f; + return Result; + } + + template<typename T, qualifier Q> + 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<typename T, qualifier Q> + GLM_FUNC_QUALIFIER mat<4, 4, T, Q> orientate4 + ( + vec<3, T, Q> const& angles + ) + { + return yawPitchRoll(angles.z, angles.x, angles.y); + } + + template<typename T> + GLM_FUNC_DECL void extractEulerAngleXYZ(mat<4, 4, T, defaultp> const& M, + T & t1, + T & t2, + T & t3) + { + T T1 = glm::atan2<T, defaultp>(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<T, defaultp>(-M[2][0], C2); + T S1 = glm::sin(T1); + T C1 = glm::cos(T1); + T T3 = glm::atan2<T, defaultp>(S1*M[0][2] - C1*M[0][1], C1*M[1][1] - S1*M[1][2 ]); + t1 = -T1; + t2 = -T2; + t3 = -T3; + } + + template <typename T> + GLM_FUNC_QUALIFIER void extractEulerAngleYXZ(mat<4, 4, T, defaultp> const & M, + T & t1, + T & t2, + T & t3) + { + T T1 = glm::atan2<T, defaultp>(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<T, defaultp>(-M[2][1], C2); + T S1 = glm::sin(T1); + T C1 = glm::cos(T1); + T T3 = glm::atan2<T, defaultp>(S1*M[1][2] - C1*M[1][0], C1*M[0][0] - S1*M[0][2]); + t1 = T1; + t2 = T2; + t3 = T3; + } + + template <typename T> + GLM_FUNC_QUALIFIER void extractEulerAngleXZX(mat<4, 4, T, defaultp> const & M, + T & t1, + T & t2, + T & t3) + { + T T1 = glm::atan2<T, defaultp>(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<T, defaultp>(S2, M[0][0]); + T S1 = glm::sin(T1); + T C1 = glm::cos(T1); + T T3 = glm::atan2<T, defaultp>(C1*M[1][2] - S1*M[1][1], C1*M[2][2] - S1*M[2][1]); + t1 = T1; + t2 = T2; + t3 = T3; + } + + template <typename T> + GLM_FUNC_QUALIFIER void extractEulerAngleXYX(mat<4, 4, T, defaultp> const & M, + T & t1, + T & t2, + T & t3) + { + T T1 = glm::atan2<T, defaultp>(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<T, defaultp>(S2, M[0][0]); + T S1 = glm::sin(T1); + T C1 = glm::cos(T1); + T T3 = glm::atan2<T, defaultp>(-C1*M[2][1] - S1*M[2][2], C1*M[1][1] + S1*M[1][2]); + t1 = T1; + t2 = T2; + t3 = T3; + } + + template <typename T> + GLM_FUNC_QUALIFIER void extractEulerAngleYXY(mat<4, 4, T, defaultp> const & M, + T & t1, + T & t2, + T & t3) + { + T T1 = glm::atan2<T, defaultp>(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<T, defaultp>(S2, M[1][1]); + T S1 = glm::sin(T1); + T C1 = glm::cos(T1); + T T3 = glm::atan2<T, defaultp>(C1*M[2][0] - S1*M[2][2], C1*M[0][0] - S1*M[0][2]); + t1 = T1; + t2 = T2; + t3 = T3; + } + + template <typename T> + GLM_FUNC_QUALIFIER void extractEulerAngleYZY(mat<4, 4, T, defaultp> const & M, + T & t1, + T & t2, + T & t3) + { + T T1 = glm::atan2<T, defaultp>(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<T, defaultp>(S2, M[1][1]); + T S1 = glm::sin(T1); + T C1 = glm::cos(T1); + T T3 = glm::atan2<T, defaultp>(-S1*M[0][0] - C1*M[0][2], S1*M[2][0] + C1*M[2][2]); + t1 = T1; + t2 = T2; + t3 = T3; + } + + template <typename T> + GLM_FUNC_QUALIFIER void extractEulerAngleZYZ(mat<4, 4, T, defaultp> const & M, + T & t1, + T & t2, + T & t3) + { + T T1 = glm::atan2<T, defaultp>(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<T, defaultp>(S2, M[2][2]); + T S1 = glm::sin(T1); + T C1 = glm::cos(T1); + T T3 = glm::atan2<T, defaultp>(C1*M[0][1] - S1*M[0][0], C1*M[1][1] - S1*M[1][0]); + t1 = T1; + t2 = T2; + t3 = T3; + } + + template <typename T> + GLM_FUNC_QUALIFIER void extractEulerAngleZXZ(mat<4, 4, T, defaultp> const & M, + T & t1, + T & t2, + T & t3) + { + T T1 = glm::atan2<T, defaultp>(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<T, defaultp>(S2, M[2][2]); + T S1 = glm::sin(T1); + T C1 = glm::cos(T1); + T T3 = glm::atan2<T, defaultp>(-C1*M[1][0] - S1*M[1][1], C1*M[0][0] + S1*M[0][1]); + t1 = T1; + t2 = T2; + t3 = T3; + } + + template <typename T> + GLM_FUNC_QUALIFIER void extractEulerAngleXZY(mat<4, 4, T, defaultp> const & M, + T & t1, + T & t2, + T & t3) + { + T T1 = glm::atan2<T, defaultp>(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<T, defaultp>(-M[1][0], C2); + T S1 = glm::sin(T1); + T C1 = glm::cos(T1); + T T3 = glm::atan2<T, defaultp>(S1*M[0][1] - C1*M[0][2], C1*M[2][2] - S1*M[2][1]); + t1 = T1; + t2 = T2; + t3 = T3; + } + + template <typename T> + GLM_FUNC_QUALIFIER void extractEulerAngleYZX(mat<4, 4, T, defaultp> const & M, + T & t1, + T & t2, + T & t3) + { + T T1 = glm::atan2<T, defaultp>(-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<T, defaultp>(M[0][1], C2); + T S1 = glm::sin(T1); + T C1 = glm::cos(T1); + T T3 = glm::atan2<T, defaultp>(S1*M[1][0] + C1*M[1][2], S1*M[2][0] + C1*M[2][2]); + t1 = T1; + t2 = T2; + t3 = T3; + } + + template <typename T> + GLM_FUNC_QUALIFIER void extractEulerAngleZYX(mat<4, 4, T, defaultp> const & M, + T & t1, + T & t2, + T & t3) + { + T T1 = glm::atan2<T, defaultp>(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<T, defaultp>(-M[0][2], C2); + T S1 = glm::sin(T1); + T C1 = glm::cos(T1); + T T3 = glm::atan2<T, defaultp>(S1*M[2][0] - C1*M[2][1], C1*M[1][1] - S1*M[1][0]); + t1 = T1; + t2 = T2; + t3 = T3; + } + + template <typename T> + GLM_FUNC_QUALIFIER void extractEulerAngleZXY(mat<4, 4, T, defaultp> const & M, + T & t1, + T & t2, + T & t3) + { + T T1 = glm::atan2<T, defaultp>(-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<T, defaultp>(M[1][2], C2); + T S1 = glm::sin(T1); + T C1 = glm::cos(T1); + T T3 = glm::atan2<T, defaultp>(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 0000000000000000000000000000000000000000..28b7c5c014a45222c522ef146d687ec77ce62651 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/gtx/extend.hpp @@ -0,0 +1,42 @@ +/// @ref gtx_extend +/// @file glm/gtx/extend.hpp +/// +/// @see core (dependence) +/// +/// @defgroup gtx_extend GLM_GTX_extend +/// @ingroup gtx +/// +/// Include <glm/gtx/extend.hpp> 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" + +#if GLM_MESSAGES == GLM_ENABLE && !defined(GLM_EXT_INCLUDED) +# ifndef GLM_ENABLE_EXPERIMENTAL +# pragma message("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.") +# else +# pragma message("GLM: GLM_GTX_extend extension included") +# endif +#endif + +namespace glm +{ + /// @addtogroup gtx_extend + /// @{ + + /// Extends of Length the Origin position using the (Source - Origin) direction. + /// @see gtx_extend + template<typename genType> + 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 0000000000000000000000000000000000000000..32128eb209ac74cf9c875c501cdc2c98956a3528 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/gtx/extend.inl @@ -0,0 +1,48 @@ +/// @ref gtx_extend + +namespace glm +{ + template<typename genType> + GLM_FUNC_QUALIFIER genType extend + ( + genType const& Origin, + genType const& Source, + genType const& Distance + ) + { + return Origin + (Source - Origin) * Distance; + } + + template<typename T, qualifier Q> + 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<typename T, qualifier Q> + 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<typename T, qualifier Q> + 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 0000000000000000000000000000000000000000..025eda294a836830f9974f57db2e21a0611e3bc8 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/gtx/extended_min_max.hpp @@ -0,0 +1,137 @@ +/// @ref gtx_extended_min_max +/// @file glm/gtx/extended_min_max.hpp +/// +/// @see core (dependence) +/// +/// @defgroup gtx_extended_min_max GLM_GTX_extented_min_max +/// @ingroup gtx +/// +/// Include <glm/gtx/extented_min_max.hpp> 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" + +#if GLM_MESSAGES == GLM_ENABLE && !defined(GLM_EXT_INCLUDED) +# ifndef GLM_ENABLE_EXPERIMENTAL +# pragma message("GLM: GLM_GTX_extented_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.") +# else +# pragma message("GLM: GLM_GTX_extented_min_max extension included") +# endif +#endif + +namespace glm +{ + /// @addtogroup gtx_extended_min_max + /// @{ + + /// Return the minimum component-wise values of 3 inputs + /// @see gtx_extented_min_max + template<typename T> + 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<typename T, template<typename> class C> + GLM_FUNC_DECL C<T> min( + C<T> const& x, + typename C<T>::T const& y, + typename C<T>::T const& z); + + /// Return the minimum component-wise values of 3 inputs + /// @see gtx_extented_min_max + template<typename T, template<typename> class C> + GLM_FUNC_DECL C<T> min( + C<T> const& x, + C<T> const& y, + C<T> const& z); + + /// Return the minimum component-wise values of 4 inputs + /// @see gtx_extented_min_max + template<typename T> + 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<typename T, template<typename> class C> + GLM_FUNC_DECL C<T> min( + C<T> const& x, + typename C<T>::T const& y, + typename C<T>::T const& z, + typename C<T>::T const& w); + + /// Return the minimum component-wise values of 4 inputs + /// @see gtx_extented_min_max + template<typename T, template<typename> class C> + GLM_FUNC_DECL C<T> min( + C<T> const& x, + C<T> const& y, + C<T> const& z, + C<T> const& w); + + /// Return the maximum component-wise values of 3 inputs + /// @see gtx_extented_min_max + template<typename T> + 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<typename T, template<typename> class C> + GLM_FUNC_DECL C<T> max( + C<T> const& x, + typename C<T>::T const& y, + typename C<T>::T const& z); + + /// Return the maximum component-wise values of 3 inputs + /// @see gtx_extented_min_max + template<typename T, template<typename> class C> + GLM_FUNC_DECL C<T> max( + C<T> const& x, + C<T> const& y, + C<T> const& z); + + /// Return the maximum component-wise values of 4 inputs + /// @see gtx_extented_min_max + template<typename T> + 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<typename T, template<typename> class C> + GLM_FUNC_DECL C<T> max( + C<T> const& x, + typename C<T>::T const& y, + typename C<T>::T const& z, + typename C<T>::T const& w); + + /// Return the maximum component-wise values of 4 inputs + /// @see gtx_extented_min_max + template<typename T, template<typename> class C> + GLM_FUNC_DECL C<T> max( + C<T> const& x, + C<T> const& y, + C<T> const& z, + C<T> 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 0000000000000000000000000000000000000000..de5998fadd654ac9cfdcdcb8deb298fd02f5ca9f --- /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<typename T> + GLM_FUNC_QUALIFIER T min( + T const& x, + T const& y, + T const& z) + { + return glm::min(glm::min(x, y), z); + } + + template<typename T, template<typename> class C> + GLM_FUNC_QUALIFIER C<T> min + ( + C<T> const& x, + typename C<T>::T const& y, + typename C<T>::T const& z + ) + { + return glm::min(glm::min(x, y), z); + } + + template<typename T, template<typename> class C> + GLM_FUNC_QUALIFIER C<T> min + ( + C<T> const& x, + C<T> const& y, + C<T> const& z + ) + { + return glm::min(glm::min(x, y), z); + } + + template<typename T> + 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<typename T, template<typename> class C> + GLM_FUNC_QUALIFIER C<T> min + ( + C<T> const& x, + typename C<T>::T const& y, + typename C<T>::T const& z, + typename C<T>::T const& w + ) + { + return glm::min(glm::min(x, y), glm::min(z, w)); + } + + template<typename T, template<typename> class C> + GLM_FUNC_QUALIFIER C<T> min + ( + C<T> const& x, + C<T> const& y, + C<T> const& z, + C<T> const& w + ) + { + return glm::min(glm::min(x, y), glm::min(z, w)); + } + + template<typename T> + GLM_FUNC_QUALIFIER T max( + T const& x, + T const& y, + T const& z) + { + return glm::max(glm::max(x, y), z); + } + + template<typename T, template<typename> class C> + GLM_FUNC_QUALIFIER C<T> max + ( + C<T> const& x, + typename C<T>::T const& y, + typename C<T>::T const& z + ) + { + return glm::max(glm::max(x, y), z); + } + + template<typename T, template<typename> class C> + GLM_FUNC_QUALIFIER C<T> max + ( + C<T> const& x, + C<T> const& y, + C<T> const& z + ) + { + return glm::max(glm::max(x, y), z); + } + + template<typename T> + 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<typename T, template<typename> class C> + GLM_FUNC_QUALIFIER C<T> max + ( + C<T> const& x, + typename C<T>::T const& y, + typename C<T>::T const& z, + typename C<T>::T const& w + ) + { + return glm::max(glm::max(x, y), glm::max(z, w)); + } + + template<typename T, template<typename> class C> + GLM_FUNC_QUALIFIER C<T> max + ( + C<T> const& x, + C<T> const& y, + C<T> const& z, + C<T> 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 0000000000000000000000000000000000000000..5522df7883c8bdaec64f287606d0a2aa526ed0d5 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/gtx/exterior_product.hpp @@ -0,0 +1,45 @@ +/// @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 <glm/gtx/exterior_product.hpp> 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" + +#if GLM_MESSAGES == GLM_ENABLE && !defined(GLM_EXT_INCLUDED) +# ifndef GLM_ENABLE_EXPERIMENTAL +# pragma message("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.") +# else +# pragma message("GLM: GLM_GTX_exterior_product extension included") +# endif +#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 <a href="https://en.wikipedia.org/wiki/Exterior_algebra#Cross_and_triple_products">Exterior product</a> + template<typename T, qualifier Q> + GLM_FUNC_DECL 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 0000000000000000000000000000000000000000..93661fd3fd7f581806610df4293bdc8bf5c4a71c --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/gtx/exterior_product.inl @@ -0,0 +1,26 @@ +/// @ref gtx_exterior_product + +#include <limits> + +namespace glm { +namespace detail +{ + template<typename T, qualifier Q, bool Aligned> + struct compute_cross_vec2 + { + GLM_FUNC_QUALIFIER static T call(vec<2, T, Q> const& v, vec<2, T, Q> const& u) + { + GLM_STATIC_ASSERT(std::numeric_limits<T>::is_iec559, "'cross' accepts only floating-point inputs"); + + return v.x * u.y - u.x * v.y; + } + }; +}//namespace detail + + template<typename T, qualifier Q> + GLM_FUNC_QUALIFIER T cross(vec<2, T, Q> const& x, vec<2, T, Q> const& y) + { + return detail::compute_cross_vec2<T, Q, detail::is_aligned<Q>::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 0000000000000000000000000000000000000000..6fb7286528cf085a623f66bbfc836261159a0354 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/gtx/fast_exponential.hpp @@ -0,0 +1,95 @@ +/// @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 <glm/gtx/fast_exponential.hpp> to use the features of this extension. +/// +/// Fast but less accurate implementations of exponential based functions. + +#pragma once + +// Dependency: +#include "../glm.hpp" + +#if GLM_MESSAGES == GLM_ENABLE && !defined(GLM_EXT_INCLUDED) +# ifndef GLM_ENABLE_EXPERIMENTAL +# pragma message("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.") +# else +# pragma message("GLM: GLM_GTX_fast_exponential extension included") +# endif +#endif + +namespace glm +{ + /// @addtogroup gtx_fast_exponential + /// @{ + + /// Faster than the common pow function but less accurate. + /// @see gtx_fast_exponential + template<typename genType> + GLM_FUNC_DECL genType fastPow(genType x, genType y); + + /// Faster than the common pow function but less accurate. + /// @see gtx_fast_exponential + template<length_t L, typename T, qualifier Q> + GLM_FUNC_DECL vec<L, T, Q> fastPow(vec<L, T, Q> const& x, vec<L, T, Q> const& y); + + /// Faster than the common pow function but less accurate. + /// @see gtx_fast_exponential + template<typename genTypeT, typename genTypeU> + GLM_FUNC_DECL genTypeT fastPow(genTypeT x, genTypeU y); + + /// Faster than the common pow function but less accurate. + /// @see gtx_fast_exponential + template<length_t L, typename T, qualifier Q> + GLM_FUNC_DECL vec<L, T, Q> fastPow(vec<L, T, Q> const& x); + + /// Faster than the common exp function but less accurate. + /// @see gtx_fast_exponential + template<typename T> + GLM_FUNC_DECL T fastExp(T x); + + /// Faster than the common exp function but less accurate. + /// @see gtx_fast_exponential + template<length_t L, typename T, qualifier Q> + GLM_FUNC_DECL vec<L, T, Q> fastExp(vec<L, T, Q> const& x); + + /// Faster than the common log function but less accurate. + /// @see gtx_fast_exponential + template<typename T> + GLM_FUNC_DECL T fastLog(T x); + + /// Faster than the common exp2 function but less accurate. + /// @see gtx_fast_exponential + template<length_t L, typename T, qualifier Q> + GLM_FUNC_DECL vec<L, T, Q> fastLog(vec<L, T, Q> const& x); + + /// Faster than the common exp2 function but less accurate. + /// @see gtx_fast_exponential + template<typename T> + GLM_FUNC_DECL T fastExp2(T x); + + /// Faster than the common exp2 function but less accurate. + /// @see gtx_fast_exponential + template<length_t L, typename T, qualifier Q> + GLM_FUNC_DECL vec<L, T, Q> fastExp2(vec<L, T, Q> const& x); + + /// Faster than the common log2 function but less accurate. + /// @see gtx_fast_exponential + template<typename T> + GLM_FUNC_DECL T fastLog2(T x); + + /// Faster than the common log2 function but less accurate. + /// @see gtx_fast_exponential + template<length_t L, typename T, qualifier Q> + GLM_FUNC_DECL vec<L, T, Q> fastLog2(vec<L, T, Q> 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 0000000000000000000000000000000000000000..f139e505636b6ecc187b2f544590669155ba0aec --- /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<typename genType> + GLM_FUNC_QUALIFIER genType fastPow(genType x, genType y) + { + return exp(y * log(x)); + } + + template<length_t L, typename T, qualifier Q> + GLM_FUNC_QUALIFIER vec<L, T, Q> fastPow(vec<L, T, Q> const& x, vec<L, T, Q> const& y) + { + return exp(y * log(x)); + } + + template<typename T> + GLM_FUNC_QUALIFIER T fastPow(T x, int y) + { + T f = static_cast<T>(1); + for(int i = 0; i < y; ++i) + f *= x; + return f; + } + + template<length_t L, typename T, qualifier Q> + GLM_FUNC_QUALIFIER vec<L, T, Q> fastPow(vec<L, T, Q> const& x, vec<L, int, Q> const& y) + { + vec<L, T, Q> 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<typename T> + 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<length_t L, typename T, qualifier Q> + GLM_FUNC_QUALIFIER vec<L, T, Q> fastExp(vec<L, T, Q> const& x) + { + return detail::functor1<vec, L, T, T, Q>::call(fastExp, x); + } + + // fastLog + template<typename genType> + 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<length_t L, typename T, qualifier Q> + GLM_FUNC_QUALIFIER vec<L, T, Q> fastLog(vec<L, T, Q> const& x) + { + return detail::functor1<vec, L, T, T, Q>::call(fastLog, x); + } + + //fastExp2, ln2 = 0.69314718055994530941723212145818f + template<typename genType> + GLM_FUNC_QUALIFIER genType fastExp2(genType x) + { + return fastExp(0.69314718055994530941723212145818f * x); + } + + template<length_t L, typename T, qualifier Q> + GLM_FUNC_QUALIFIER vec<L, T, Q> fastExp2(vec<L, T, Q> const& x) + { + return detail::functor1<vec, L, T, T, Q>::call(fastExp2, x); + } + + // fastLog2, ln2 = 0.69314718055994530941723212145818f + template<typename genType> + GLM_FUNC_QUALIFIER genType fastLog2(genType x) + { + return fastLog(x) / 0.69314718055994530941723212145818f; + } + + template<length_t L, typename T, qualifier Q> + GLM_FUNC_QUALIFIER vec<L, T, Q> fastLog2(vec<L, T, Q> const& x) + { + return detail::functor1<vec, L, T, T, Q>::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 0000000000000000000000000000000000000000..9fb3f2fce0af2e6555ac65d1a7c3ce05c14de118 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/gtx/fast_square_root.hpp @@ -0,0 +1,92 @@ +/// @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 <glm/gtx/fast_square_root.hpp> 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" + +#if GLM_MESSAGES == GLM_ENABLE && !defined(GLM_EXT_INCLUDED) +# ifndef GLM_ENABLE_EXPERIMENTAL +# pragma message("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.") +# else +# pragma message("GLM: GLM_GTX_fast_square_root extension included") +# endif +#endif + +namespace glm +{ + /// @addtogroup gtx_fast_square_root + /// @{ + + /// Faster than the common sqrt function but less accurate. + /// + /// @see gtx_fast_square_root extension. + template<typename genType> + GLM_FUNC_DECL genType fastSqrt(genType x); + + /// Faster than the common sqrt function but less accurate. + /// + /// @see gtx_fast_square_root extension. + template<length_t L, typename T, qualifier Q> + GLM_FUNC_DECL vec<L, T, Q> fastSqrt(vec<L, T, Q> const& x); + + /// Faster than the common inversesqrt function but less accurate. + /// + /// @see gtx_fast_square_root extension. + template<typename genType> + GLM_FUNC_DECL genType fastInverseSqrt(genType x); + + /// Faster than the common inversesqrt function but less accurate. + /// + /// @see gtx_fast_square_root extension. + template<length_t L, typename T, qualifier Q> + GLM_FUNC_DECL vec<L, T, Q> fastInverseSqrt(vec<L, T, Q> const& x); + + /// Faster than the common length function but less accurate. + /// + /// @see gtx_fast_square_root extension. + template<typename genType> + GLM_FUNC_DECL genType fastLength(genType x); + + /// Faster than the common length function but less accurate. + /// + /// @see gtx_fast_square_root extension. + template<length_t L, typename T, qualifier Q> + GLM_FUNC_DECL T fastLength(vec<L, T, Q> const& x); + + /// Faster than the common distance function but less accurate. + /// + /// @see gtx_fast_square_root extension. + template<typename genType> + 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<length_t L, typename T, qualifier Q> + GLM_FUNC_DECL T fastDistance(vec<L, T, Q> const& x, vec<L, T, Q> const& y); + + /// Faster than the common normalize function but less accurate. + /// + /// @see gtx_fast_square_root extension. + template<typename genType> + GLM_FUNC_DECL genType fastNormalize(genType 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 0000000000000000000000000000000000000000..4e6c6de90e2dd3dad64fc3bc54ee5235f6fe4ead --- /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<typename genType> + GLM_FUNC_QUALIFIER genType fastSqrt(genType x) + { + GLM_STATIC_ASSERT(std::numeric_limits<genType>::is_iec559, "'fastSqrt' only accept floating-point input"); + + return genType(1) / fastInverseSqrt(x); + } + + template<length_t L, typename T, qualifier Q> + GLM_FUNC_QUALIFIER vec<L, T, Q> fastSqrt(vec<L, T, Q> const& x) + { + return detail::functor1<vec, L, T, T, Q>::call(fastSqrt, x); + } + + // fastInversesqrt + template<typename genType> + GLM_FUNC_QUALIFIER genType fastInverseSqrt(genType x) + { + return detail::compute_inversesqrt<1, genType, lowp, detail::is_aligned<lowp>::value>::call(vec<1, genType, lowp>(x)).x; + } + + template<length_t L, typename T, qualifier Q> + GLM_FUNC_QUALIFIER vec<L, T, Q> fastInverseSqrt(vec<L, T, Q> const& x) + { + return detail::compute_inversesqrt<L, T, Q, detail::is_aligned<Q>::value>::call(x); + } + + // fastLength + template<typename genType> + GLM_FUNC_QUALIFIER genType fastLength(genType x) + { + GLM_STATIC_ASSERT(std::numeric_limits<genType>::is_iec559, "'fastLength' only accept floating-point inputs"); + + return abs(x); + } + + template<length_t L, typename T, qualifier Q> + GLM_FUNC_QUALIFIER T fastLength(vec<L, T, Q> const& x) + { + GLM_STATIC_ASSERT(std::numeric_limits<T>::is_iec559, "'fastLength' only accept floating-point inputs"); + + return fastSqrt(dot(x, x)); + } + + // fastDistance + template<typename genType> + GLM_FUNC_QUALIFIER genType fastDistance(genType x, genType y) + { + return fastLength(y - x); + } + + template<length_t L, typename T, qualifier Q> + GLM_FUNC_QUALIFIER T fastDistance(vec<L, T, Q> const& x, vec<L, T, Q> const& y) + { + return fastLength(y - x); + } + + // fastNormalize + template<typename genType> + GLM_FUNC_QUALIFIER genType fastNormalize(genType x) + { + return x > genType(0) ? genType(1) : -genType(1); + } + + template<length_t L, typename T, qualifier Q> + GLM_FUNC_QUALIFIER vec<L, T, Q> fastNormalize(vec<L, T, Q> 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 0000000000000000000000000000000000000000..2650d6e4d6e3f0b1e12a4c44b8a046d788bcbc90 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/gtx/fast_trigonometry.hpp @@ -0,0 +1,79 @@ +/// @ref gtx_fast_trigonometry +/// @file glm/gtx/fast_trigonometry.hpp +/// +/// @see core (dependence) +/// +/// @defgroup gtx_fast_trigonometry GLM_GTX_fast_trigonometry +/// @ingroup gtx +/// +/// Include <glm/gtx/fast_trigonometry.hpp> to use the features of this extension. +/// +/// Fast but less accurate implementations of trigonometric functions. + +#pragma once + +// Dependency: +#include "../gtc/constants.hpp" + +#if GLM_MESSAGES == GLM_ENABLE && !defined(GLM_EXT_INCLUDED) +# ifndef GLM_ENABLE_EXPERIMENTAL +# pragma message("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.") +# else +# pragma message("GLM: GLM_GTX_fast_trigonometry extension included") +# endif +#endif + +namespace glm +{ + /// @addtogroup gtx_fast_trigonometry + /// @{ + + /// Wrap an angle to [0 2pi[ + /// From GLM_GTX_fast_trigonometry extension. + template<typename T> + GLM_FUNC_DECL T wrapAngle(T angle); + + /// Faster than the common sin function but less accurate. + /// From GLM_GTX_fast_trigonometry extension. + template<typename T> + GLM_FUNC_DECL T fastSin(T angle); + + /// Faster than the common cos function but less accurate. + /// From GLM_GTX_fast_trigonometry extension. + template<typename T> + 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<typename T> + 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<typename T> + 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<typename T> + 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<typename T> + 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<typename T> + 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 0000000000000000000000000000000000000000..1a710cbcd08d48ebabfaa09e6314c3397e0d0fd5 --- /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<length_t L, typename T, qualifier Q> + GLM_FUNC_QUALIFIER vec<L, T, Q> taylorCos(vec<L, T, Q> const& x) + { + return static_cast<T>(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<typename T> + 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<length_t L, typename T, qualifier Q> + GLM_FUNC_QUALIFIER vec<L, T, Q> cos_52s(vec<L, T, Q> const& x) + { + return detail::functor1<vec, L, T, T, Q>::call(cos_52s, x); + } +}//namespace detail + + // wrapAngle + template<typename T> + GLM_FUNC_QUALIFIER T wrapAngle(T angle) + { + return abs<T>(mod<T>(angle, two_pi<T>())); + } + + template<length_t L, typename T, qualifier Q> + GLM_FUNC_QUALIFIER vec<L, T, Q> wrapAngle(vec<L, T, Q> const& x) + { + return detail::functor1<vec, L, T, T, Q>::call(wrapAngle, x); + } + + // cos + template<typename T> + GLM_FUNC_QUALIFIER T fastCos(T x) + { + T const angle(wrapAngle<T>(x)); + + if(angle < half_pi<T>()) + return detail::cos_52s(angle); + if(angle < pi<T>()) + return -detail::cos_52s(pi<T>() - angle); + if(angle < (T(3) * half_pi<T>())) + return -detail::cos_52s(angle - pi<T>()); + + return detail::cos_52s(two_pi<T>() - angle); + } + + template<length_t L, typename T, qualifier Q> + GLM_FUNC_QUALIFIER vec<L, T, Q> fastCos(vec<L, T, Q> const& x) + { + return detail::functor1<vec, L, T, T, Q>::call(fastCos, x); + } + + // sin + template<typename T> + GLM_FUNC_QUALIFIER T fastSin(T x) + { + return fastCos<T>(half_pi<T>() - x); + } + + template<length_t L, typename T, qualifier Q> + GLM_FUNC_QUALIFIER vec<L, T, Q> fastSin(vec<L, T, Q> const& x) + { + return detail::functor1<vec, L, T, T, Q>::call(fastSin, x); + } + + // tan + template<typename T> + 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<length_t L, typename T, qualifier Q> + GLM_FUNC_QUALIFIER vec<L, T, Q> fastTan(vec<L, T, Q> const& x) + { + return detail::functor1<vec, L, T, T, Q>::call(fastTan, x); + } + + // asin + template<typename T> + 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<length_t L, typename T, qualifier Q> + GLM_FUNC_QUALIFIER vec<L, T, Q> fastAsin(vec<L, T, Q> const& x) + { + return detail::functor1<vec, L, T, T, Q>::call(fastAsin, x); + } + + // acos + template<typename T> + GLM_FUNC_QUALIFIER T fastAcos(T x) + { + return T(1.5707963267948966192313216916398) - fastAsin(x); //(PI / 2) + } + + template<length_t L, typename T, qualifier Q> + GLM_FUNC_QUALIFIER vec<L, T, Q> fastAcos(vec<L, T, Q> const& x) + { + return detail::functor1<vec, L, T, T, Q>::call(fastAcos, x); + } + + // atan + template<typename T> + GLM_FUNC_QUALIFIER T fastAtan(T y, T x) + { + T sgn = sign(y) * sign(x); + return abs(fastAtan(y / x)) * sgn; + } + + template<length_t L, typename T, qualifier Q> + GLM_FUNC_QUALIFIER vec<L, T, Q> fastAtan(vec<L, T, Q> const& y, vec<L, T, Q> const& x) + { + return detail::functor2<vec, L, T, Q>::call(fastAtan, y, x); + } + + template<typename T> + 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<length_t L, typename T, qualifier Q> + GLM_FUNC_QUALIFIER vec<L, T, Q> fastAtan(vec<L, T, Q> const& x) + { + return detail::functor1<vec, L, T, T, Q>::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 0000000000000000000000000000000000000000..8cdbc5aaa9c3895ea1f0e7e3a817f78b813e10c3 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/gtx/float_notmalize.inl @@ -0,0 +1,13 @@ +/// @ref gtx_float_normalize + +#include <limits> + +namespace glm +{ + template<length_t L, typename T, qualifier Q> + GLM_FUNC_QUALIFIER vec<L, float, Q> floatNormalize(vec<L, T, Q> const& v) + { + return vec<L, float, Q>(v) / static_cast<float>(std::numeric_limits<T>::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 0000000000000000000000000000000000000000..9f4166c4c1c809bc1c4e88a190e172f1f8138fc7 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/gtx/functions.hpp @@ -0,0 +1,56 @@ +/// @ref gtx_functions +/// @file glm/gtx/functions.hpp +/// +/// @see core (dependence) +/// @see gtc_quaternion (dependence) +/// +/// @defgroup gtx_functions GLM_GTX_functions +/// @ingroup gtx +/// +/// Include <glm/gtx/functions.hpp> 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" + +#if GLM_MESSAGES == GLM_ENABLE && !defined(GLM_EXT_INCLUDED) +# ifndef GLM_ENABLE_EXPERIMENTAL +# pragma message("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.") +# else +# pragma message("GLM: GLM_GTX_functions extension included") +# endif +#endif + +namespace glm +{ + /// @addtogroup gtx_functions + /// @{ + + /// 1D gauss function + /// + /// @see gtc_epsilon + template<typename T> + GLM_FUNC_DECL T gauss( + T x, + T ExpectedValue, + T StandardDeviation); + + /// 2D gauss function + /// + /// @see gtc_epsilon + template<typename T, qualifier Q> + 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 0000000000000000000000000000000000000000..29cbb20b80fa501931a5bf9203a52171b4a42773 --- /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<typename T> + GLM_FUNC_QUALIFIER T gauss + ( + T x, + T ExpectedValue, + T StandardDeviation + ) + { + return exp(-((x - ExpectedValue) * (x - ExpectedValue)) / (static_cast<T>(2) * StandardDeviation * StandardDeviation)) / (StandardDeviation * sqrt(static_cast<T>(6.28318530717958647692528676655900576))); + } + + template<typename T, qualifier Q> + 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<T>(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 0000000000000000000000000000000000000000..6f85bf482d9fdd16ab823462741b98c43d337b01 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/gtx/gradient_paint.hpp @@ -0,0 +1,53 @@ +/// @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 <glm/gtx/gradient_paint.hpp> 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" + +#if GLM_MESSAGES == GLM_ENABLE && !defined(GLM_EXT_INCLUDED) +# ifndef GLM_ENABLE_EXPERIMENTAL +# pragma message("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.") +# else +# pragma message("GLM: GLM_GTX_gradient_paint extension included") +# endif +#endif + +namespace glm +{ + /// @addtogroup gtx_gradient_paint + /// @{ + + /// Return a color from a radial gradient. + /// @see - gtx_gradient_paint + template<typename T, qualifier Q> + 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<typename T, qualifier Q> + 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 0000000000000000000000000000000000000000..4c495e62cbffd88b88fcd7086c692c2f67f157d1 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/gtx/gradient_paint.inl @@ -0,0 +1,36 @@ +/// @ref gtx_gradient_paint + +namespace glm +{ + template<typename T, qualifier Q> + 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<typename T, qualifier Q> + 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 0000000000000000000000000000000000000000..3c8596892ce68ce2e463c00a5fa938004a0eef7c --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/gtx/handed_coordinate_space.hpp @@ -0,0 +1,50 @@ +/// @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 <glm/gtx/handed_coordinate_system.hpp> 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" + +#if GLM_MESSAGES == GLM_ENABLE && !defined(GLM_EXT_INCLUDED) +# ifndef GLM_ENABLE_EXPERIMENTAL +# pragma message("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.") +# else +# pragma message("GLM: GLM_GTX_handed_coordinate_space extension included") +# endif +#endif + +namespace glm +{ + /// @addtogroup gtx_handed_coordinate_space + /// @{ + + //! Return if a trihedron right handed or not. + //! From GLM_GTX_handed_coordinate_space extension. + template<typename T, qualifier Q> + 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<typename T, qualifier Q> + 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 0000000000000000000000000000000000000000..e43c17bd3120931fff5438f5db175852896a1bbb --- /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<typename T, qualifier Q> + 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<typename T, qualifier Q> + 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 0000000000000000000000000000000000000000..05dae9f4b07ed70ab0f70fab061034899db62439 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/gtx/hash.hpp @@ -0,0 +1,142 @@ +/// @ref gtx_hash +/// @file glm/gtx/hash.hpp +/// +/// @see core (dependence) +/// +/// @defgroup gtx_hash GLM_GTX_hash +/// @ingroup gtx +/// +/// Include <glm/gtx/hash.hpp> to use the features of this extension. +/// +/// Add std::hash support for glm types + +#pragma once + +#if GLM_MESSAGES == GLM_ENABLE && !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 <functional> + +#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 !GLM_HAS_CXX11_STL +# error "GLM_GTX_hash requires C++11 standard library support" +#endif + +namespace std +{ + template<typename T, glm::qualifier Q> + struct hash<glm::vec<1, T,Q> > + { + GLM_FUNC_DECL size_t operator()(glm::vec<1, T, Q> const& v) const; + }; + + template<typename T, glm::qualifier Q> + struct hash<glm::vec<2, T,Q> > + { + GLM_FUNC_DECL size_t operator()(glm::vec<2, T, Q> const& v) const; + }; + + template<typename T, glm::qualifier Q> + struct hash<glm::vec<3, T,Q> > + { + GLM_FUNC_DECL size_t operator()(glm::vec<3, T, Q> const& v) const; + }; + + template<typename T, glm::qualifier Q> + struct hash<glm::vec<4, T,Q> > + { + GLM_FUNC_DECL size_t operator()(glm::vec<4, T, Q> const& v) const; + }; + + template<typename T, glm::qualifier Q> + struct hash<glm::qua<T,Q>> + { + GLM_FUNC_DECL size_t operator()(glm::qua<T, Q> const& q) const; + }; + + template<typename T, glm::qualifier Q> + struct hash<glm::tdualquat<T,Q> > + { + GLM_FUNC_DECL size_t operator()(glm::tdualquat<T,Q> const& q) const; + }; + + template<typename T, glm::qualifier Q> + struct hash<glm::mat<2, 2, T,Q> > + { + GLM_FUNC_DECL size_t operator()(glm::mat<2, 2, T,Q> const& m) const; + }; + + template<typename T, glm::qualifier Q> + struct hash<glm::mat<2, 3, T,Q> > + { + GLM_FUNC_DECL size_t operator()(glm::mat<2, 3, T,Q> const& m) const; + }; + + template<typename T, glm::qualifier Q> + struct hash<glm::mat<2, 4, T,Q> > + { + GLM_FUNC_DECL size_t operator()(glm::mat<2, 4, T,Q> const& m) const; + }; + + template<typename T, glm::qualifier Q> + struct hash<glm::mat<3, 2, T,Q> > + { + GLM_FUNC_DECL size_t operator()(glm::mat<3, 2, T,Q> const& m) const; + }; + + template<typename T, glm::qualifier Q> + struct hash<glm::mat<3, 3, T,Q> > + { + GLM_FUNC_DECL size_t operator()(glm::mat<3, 3, T,Q> const& m) const; + }; + + template<typename T, glm::qualifier Q> + struct hash<glm::mat<3, 4, T,Q> > + { + GLM_FUNC_DECL size_t operator()(glm::mat<3, 4, T,Q> const& m) const; + }; + + template<typename T, glm::qualifier Q> + struct hash<glm::mat<4, 2, T,Q> > + { + GLM_FUNC_DECL size_t operator()(glm::mat<4, 2, T,Q> const& m) const; + }; + + template<typename T, glm::qualifier Q> + struct hash<glm::mat<4, 3, T,Q> > + { + GLM_FUNC_DECL size_t operator()(glm::mat<4, 3, T,Q> const& m) const; + }; + + template<typename T, glm::qualifier Q> + struct hash<glm::mat<4, 4, T,Q> > + { + GLM_FUNC_DECL size_t operator()(glm::mat<4, 4, T,Q> const& m) const; + }; +} // namespace std + +#include "hash.inl" 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 0000000000000000000000000000000000000000..ff71ca9f7eaf19cc43fd4edcafb52609d0d11e49 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/gtx/hash.inl @@ -0,0 +1,184 @@ +/// @ref gtx_hash +/// +/// @see core (dependence) +/// +/// @defgroup gtx_hash GLM_GTX_hash +/// @ingroup gtx +/// +/// @brief Add std::hash support for glm types +/// +/// <glm/gtx/hash.inl> need to be included to use the features of this extension. + +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<typename T, glm::qualifier Q> + GLM_FUNC_QUALIFIER size_t hash<glm::vec<1, T, Q>>::operator()(glm::vec<1, T, Q> const& v) const + { + hash<T> hasher; + return hasher(v.x); + } + + template<typename T, glm::qualifier Q> + GLM_FUNC_QUALIFIER size_t hash<glm::vec<2, T, Q>>::operator()(glm::vec<2, T, Q> const& v) const + { + size_t seed = 0; + hash<T> hasher; + glm::detail::hash_combine(seed, hasher(v.x)); + glm::detail::hash_combine(seed, hasher(v.y)); + return seed; + } + + template<typename T, glm::qualifier Q> + GLM_FUNC_QUALIFIER size_t hash<glm::vec<3, T, Q>>::operator()(glm::vec<3, T, Q> const& v) const + { + size_t seed = 0; + hash<T> 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<typename T, glm::qualifier Q> + GLM_FUNC_QUALIFIER size_t hash<glm::vec<4, T, Q>>::operator()(glm::vec<4, T, Q> const& v) const + { + size_t seed = 0; + hash<T> 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<typename T, glm::qualifier Q> + GLM_FUNC_QUALIFIER size_t hash<glm::qua<T, Q>>::operator()(glm::qua<T,Q> const& q) const + { + size_t seed = 0; + hash<T> 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<typename T, glm::qualifier Q> + GLM_FUNC_QUALIFIER size_t hash<glm::tdualquat<T, Q>>::operator()(glm::tdualquat<T, Q> const& q) const + { + size_t seed = 0; + hash<glm::qua<T, Q>> hasher; + glm::detail::hash_combine(seed, hasher(q.real)); + glm::detail::hash_combine(seed, hasher(q.dual)); + return seed; + } + + template<typename T, glm::qualifier Q> + GLM_FUNC_QUALIFIER size_t hash<glm::mat<2, 2, T, Q>>::operator()(glm::mat<2, 2, T, Q> const& m) const + { + size_t seed = 0; + hash<glm::vec<2, T, Q>> hasher; + glm::detail::hash_combine(seed, hasher(m[0])); + glm::detail::hash_combine(seed, hasher(m[1])); + return seed; + } + + template<typename T, glm::qualifier Q> + GLM_FUNC_QUALIFIER size_t hash<glm::mat<2, 3, T, Q>>::operator()(glm::mat<2, 3, T, Q> const& m) const + { + size_t seed = 0; + hash<glm::vec<3, T, Q>> hasher; + glm::detail::hash_combine(seed, hasher(m[0])); + glm::detail::hash_combine(seed, hasher(m[1])); + return seed; + } + + template<typename T, glm::qualifier Q> + GLM_FUNC_QUALIFIER size_t hash<glm::mat<2, 4, T, Q>>::operator()(glm::mat<2, 4, T, Q> const& m) const + { + size_t seed = 0; + hash<glm::vec<4, T, Q>> hasher; + glm::detail::hash_combine(seed, hasher(m[0])); + glm::detail::hash_combine(seed, hasher(m[1])); + return seed; + } + + template<typename T, glm::qualifier Q> + GLM_FUNC_QUALIFIER size_t hash<glm::mat<3, 2, T, Q>>::operator()(glm::mat<3, 2, T, Q> const& m) const + { + size_t seed = 0; + hash<glm::vec<2, T, Q>> 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<typename T, glm::qualifier Q> + GLM_FUNC_QUALIFIER size_t hash<glm::mat<3, 3, T, Q>>::operator()(glm::mat<3, 3, T, Q> const& m) const + { + size_t seed = 0; + hash<glm::vec<3, T, Q>> 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<typename T, glm::qualifier Q> + GLM_FUNC_QUALIFIER size_t hash<glm::mat<3, 4, T, Q>>::operator()(glm::mat<3, 4, T, Q> const& m) const + { + size_t seed = 0; + hash<glm::vec<4, T, Q>> 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<typename T, glm::qualifier Q> + GLM_FUNC_QUALIFIER size_t hash<glm::mat<4, 2, T,Q>>::operator()(glm::mat<4, 2, T,Q> const& m) const + { + size_t seed = 0; + hash<glm::vec<2, T, Q>> 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<typename T, glm::qualifier Q> + GLM_FUNC_QUALIFIER size_t hash<glm::mat<4, 3, T,Q>>::operator()(glm::mat<4, 3, T,Q> const& m) const + { + size_t seed = 0; + hash<glm::vec<3, T, Q>> 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<typename T, glm::qualifier Q> + GLM_FUNC_QUALIFIER size_t hash<glm::mat<4, 4, T,Q>>::operator()(glm::mat<4, 4, T, Q> const& m) const + { + size_t seed = 0; + hash<glm::vec<4, T, Q>> 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 0000000000000000000000000000000000000000..d0b4c61a3fd41484952f38aec2d97c7a2db8c47d --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/gtx/integer.hpp @@ -0,0 +1,76 @@ +/// @ref gtx_integer +/// @file glm/gtx/integer.hpp +/// +/// @see core (dependence) +/// +/// @defgroup gtx_integer GLM_GTX_integer +/// @ingroup gtx +/// +/// Include <glm/gtx/integer.hpp> to use the features of this extension. +/// +/// Add support for integer for core functions + +#pragma once + +// Dependency: +#include "../glm.hpp" +#include "../gtc/integer.hpp" + +#if GLM_MESSAGES == GLM_ENABLE && !defined(GLM_EXT_INCLUDED) +# ifndef GLM_ENABLE_EXPERIMENTAL +# pragma message("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.") +# else +# pragma message("GLM: GLM_GTX_integer extension included") +# endif +#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<typename genType> + 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 0000000000000000000000000000000000000000..956366b250f8c84e94d638dcd5f8a8744991bf51 --- /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<typename genType> + GLM_FUNC_QUALIFIER genType factorial(genType const& x) + { + genType Temp = x; + genType Result; + for(Result = 1; Temp > 1; --Temp) + Result *= Temp; + return Result; + } + + template<typename T, qualifier Q> + 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<typename T, qualifier Q> + 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<typename T, qualifier Q> + 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 - 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 0000000000000000000000000000000000000000..3c78f2b8e22fb932060cf773cedbc8523570a961 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/gtx/intersect.hpp @@ -0,0 +1,92 @@ +/// @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 <glm/gtx/intersect.hpp> to use the features of this extension. +/// +/// Add intersection functions + +#pragma once + +// Dependency: +#include <cfloat> +#include <limits> +#include "../glm.hpp" +#include "../geometric.hpp" +#include "../gtx/closest_point.hpp" +#include "../gtx/vector_query.hpp" + +#if GLM_MESSAGES == GLM_ENABLE && !defined(GLM_EXT_INCLUDED) +# ifndef GLM_ENABLE_EXPERIMENTAL +# pragma message("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.") +# else +# pragma message("GLM: GLM_GTX_closest_point extension included") +# endif +#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<typename genType> + 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<typename T, qualifier Q> + 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<typename genType> + 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<typename genType> + GLM_FUNC_DECL bool intersectRaySphere( + genType const& rayStarting, genType const& rayNormalizedDirection, + genType const& sphereCenter, typename genType::value_type const sphereRadiusSquered, + typename genType::value_type & intersectionDistance); + + //! Compute the intersection of a ray and a sphere. + //! From GLM_GTX_intersect extension. + template<typename genType> + 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<typename genType> + 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 0000000000000000000000000000000000000000..54ecb4d909cda670167649a581d3f0af8450e2f2 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/gtx/intersect.inl @@ -0,0 +1,200 @@ +/// @ref gtx_intersect + +namespace glm +{ + template<typename genType> + 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<typename genType::value_type>::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<typename genType::value_type>(0)) { // allow only intersections + intersectionDistance = tmp_intersectionDistance; + return true; + } + } + + return false; + } + + template<typename T, qualifier Q> + 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 > std::numeric_limits<T>::epsilon()) + { + // 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<T>(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<T>(0)) || ((baryPosition.x + baryPosition.y) > det)) + return false; + } + else if(det < -std::numeric_limits<T>::epsilon()) + { + // 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<T>(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<T>(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<T>(1) / det; + + // calculate distance, ray intersects triangle + distance = glm::dot(edge2, Perpendicular) * inv_det; + baryPosition *= inv_det; + + return true; + } + + template<typename genType> + 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<typename genType::value_type>::epsilon(); + + genType edge1 = vert1 - vert0; + genType edge2 = vert2 - vert0; + + genType Perpendicular = cross(dir, edge2); + + float det = dot(edge1, Perpendicular); + + if (det > -Epsilon && det < Epsilon) + return false; + typename genType::value_type inv_det = typename genType::value_type(1) / det; + + genType Tengant = orig - vert0; + + position.y = dot(Tengant, Perpendicular) * inv_det; + if (position.y < typename genType::value_type(0) || position.y > typename genType::value_type(1)) + return false; + + genType Cotengant = cross(Tengant, edge1); + + position.z = dot(dir, Cotengant) * 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, Cotengant) * inv_det; + + return true; + } + + template<typename genType> + GLM_FUNC_QUALIFIER bool intersectRaySphere + ( + genType const& rayStarting, genType const& rayNormalizedDirection, + genType const& sphereCenter, const typename genType::value_type sphereRadiusSquered, + typename genType::value_type & intersectionDistance + ) + { + typename genType::value_type Epsilon = std::numeric_limits<typename genType::value_type>::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 > sphereRadiusSquered ) + { + return false; + } + typename genType::value_type t1 = sqrt( sphereRadiusSquered - dSquared ); + intersectionDistance = t0 > t1 + Epsilon ? t0 - t1 : t0 + t1; + return intersectionDistance > Epsilon; + } + + template<typename genType> + 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<typename genType> + 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<typename genType::value_type>::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 0000000000000000000000000000000000000000..8d974f00456c7ff5a3f104efb244707b382e02f0 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/gtx/io.hpp @@ -0,0 +1,201 @@ +/// @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 <glm/gtx/io.hpp> 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" + +#if GLM_MESSAGES == GLM_ENABLE && !defined(GLM_EXT_INCLUDED) +# ifndef GLM_ENABLE_EXPERIMENTAL +# pragma message("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.") +# else +# pragma message("GLM: GLM_GTX_io extension included") +# endif +#endif + +#include <iosfwd> // std::basic_ostream<> (fwd) +#include <locale> // std::locale, std::locale::facet, std::locale::id +#include <utility> // std::pair<> + +namespace glm +{ + /// @addtogroup gtx_io + /// @{ + + namespace io + { + enum order_type { column_major, row_major}; + + template<typename CTy> + 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_DECL explicit format_punct(size_t a = 0); + GLM_FUNC_DECL explicit format_punct(format_punct const&); + }; + + template<typename CTy, typename CTr = std::char_traits<CTy> > + class basic_state_saver { + + public: + + GLM_FUNC_DECL explicit basic_state_saver(std::basic_ios<CTy,CTr>&); + GLM_FUNC_DECL ~basic_state_saver(); + + private: + + typedef ::std::basic_ios<CTy,CTr> 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<char> state_saver; + typedef basic_state_saver<wchar_t> wstate_saver; + + template<typename CTy, typename CTr = std::char_traits<CTy> > + class basic_format_saver + { + public: + + GLM_FUNC_DECL explicit basic_format_saver(std::basic_ios<CTy,CTr>&); + GLM_FUNC_DECL ~basic_format_saver(); + + private: + + basic_state_saver<CTy> const bss_; + + GLM_FUNC_DECL basic_format_saver& operator=(basic_format_saver const&); + }; + + typedef basic_format_saver<char> format_saver; + typedef basic_format_saver<wchar_t> wformat_saver; + + struct precision + { + unsigned value; + + GLM_FUNC_DECL explicit precision(unsigned); + }; + + struct width + { + unsigned value; + + GLM_FUNC_DECL explicit width(unsigned); + }; + + template<typename CTy> + struct delimeter + { + CTy value[3]; + + GLM_FUNC_DECL explicit delimeter(CTy /* left */, CTy /* right */, CTy /* separator */ = ','); + }; + + struct order + { + order_type value; + + GLM_FUNC_DECL explicit order(order_type); + }; + + // functions, inlined (inline) + + template<typename FTy, typename CTy, typename CTr> + FTy const& get_facet(std::basic_ios<CTy,CTr>&); + template<typename FTy, typename CTy, typename CTr> + std::basic_ios<CTy,CTr>& formatted(std::basic_ios<CTy,CTr>&); + template<typename FTy, typename CTy, typename CTr> + std::basic_ios<CTy,CTr>& unformattet(std::basic_ios<CTy,CTr>&); + + template<typename CTy, typename CTr> + std::basic_ostream<CTy, CTr>& operator<<(std::basic_ostream<CTy, CTr>&, precision const&); + template<typename CTy, typename CTr> + std::basic_ostream<CTy, CTr>& operator<<(std::basic_ostream<CTy, CTr>&, width const&); + template<typename CTy, typename CTr> + std::basic_ostream<CTy, CTr>& operator<<(std::basic_ostream<CTy, CTr>&, delimeter<CTy> const&); + template<typename CTy, typename CTr> + std::basic_ostream<CTy, CTr>& operator<<(std::basic_ostream<CTy, CTr>&, order const&); + }//namespace io + + template<typename CTy, typename CTr, typename T, qualifier Q> + GLM_FUNC_DECL std::basic_ostream<CTy,CTr>& operator<<(std::basic_ostream<CTy,CTr>&, qua<T, Q> const&); + template<typename CTy, typename CTr, typename T, qualifier Q> + GLM_FUNC_DECL std::basic_ostream<CTy,CTr>& operator<<(std::basic_ostream<CTy,CTr>&, vec<1, T, Q> const&); + template<typename CTy, typename CTr, typename T, qualifier Q> + GLM_FUNC_DECL std::basic_ostream<CTy,CTr>& operator<<(std::basic_ostream<CTy,CTr>&, vec<2, T, Q> const&); + template<typename CTy, typename CTr, typename T, qualifier Q> + GLM_FUNC_DECL std::basic_ostream<CTy,CTr>& operator<<(std::basic_ostream<CTy,CTr>&, vec<3, T, Q> const&); + template<typename CTy, typename CTr, typename T, qualifier Q> + GLM_FUNC_DECL std::basic_ostream<CTy,CTr>& operator<<(std::basic_ostream<CTy,CTr>&, vec<4, T, Q> const&); + template<typename CTy, typename CTr, typename T, qualifier Q> + GLM_FUNC_DECL std::basic_ostream<CTy,CTr>& operator<<(std::basic_ostream<CTy,CTr>&, mat<2, 2, T, Q> const&); + template<typename CTy, typename CTr, typename T, qualifier Q> + GLM_FUNC_DECL std::basic_ostream<CTy,CTr>& operator<<(std::basic_ostream<CTy,CTr>&, mat<2, 3, T, Q> const&); + template<typename CTy, typename CTr, typename T, qualifier Q> + GLM_FUNC_DECL std::basic_ostream<CTy,CTr>& operator<<(std::basic_ostream<CTy,CTr>&, mat<2, 4, T, Q> const&); + template<typename CTy, typename CTr, typename T, qualifier Q> + GLM_FUNC_DECL std::basic_ostream<CTy,CTr>& operator<<(std::basic_ostream<CTy,CTr>&, mat<3, 2, T, Q> const&); + template<typename CTy, typename CTr, typename T, qualifier Q> + GLM_FUNC_DECL std::basic_ostream<CTy,CTr>& operator<<(std::basic_ostream<CTy,CTr>&, mat<3, 3, T, Q> const&); + template<typename CTy, typename CTr, typename T, qualifier Q> + GLM_FUNC_DECL std::basic_ostream<CTy,CTr>& operator<<(std::basic_ostream<CTy,CTr>&, mat<3, 4, T, Q> const&); + template<typename CTy, typename CTr, typename T, qualifier Q> + GLM_FUNC_DECL std::basic_ostream<CTy,CTr>& operator<<(std::basic_ostream<CTy,CTr>&, mat<4, 2, T, Q> const&); + template<typename CTy, typename CTr, typename T, qualifier Q> + GLM_FUNC_DECL std::basic_ostream<CTy,CTr>& operator<<(std::basic_ostream<CTy,CTr>&, mat<4, 3, T, Q> const&); + template<typename CTy, typename CTr, typename T, qualifier Q> + GLM_FUNC_DECL std::basic_ostream<CTy,CTr>& operator<<(std::basic_ostream<CTy,CTr>&, mat<4, 4, T, Q> const&); + + template<typename CTy, typename CTr, typename T, qualifier Q> + GLM_FUNC_DECL std::basic_ostream<CTy,CTr> & operator<<(std::basic_ostream<CTy,CTr> &, + std::pair<mat<4, 4, T, Q> const, mat<4, 4, T, Q> const> const&); + + /// @} +}//namespace glm + +#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 0000000000000000000000000000000000000000..a3a1bb6c26b4175373a6ec45595cada792567c1c --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/gtx/io.inl @@ -0,0 +1,440 @@ +/// @ref gtx_io +/// @author Jan P Springer (regnirpsj@gmail.com) + +#include <iomanip> // std::fixed, std::setfill<>, std::setprecision, std::right, std::setw +#include <ostream> // std::basic_ostream<> +#include "../gtc/matrix_access.hpp" // glm::col, glm::row +#include "../gtx/type_trait.hpp" // glm::type<> + +namespace glm{ +namespace io +{ + template<typename CTy> + GLM_FUNC_QUALIFIER format_punct<CTy>::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<typename CTy> + GLM_FUNC_QUALIFIER format_punct<CTy>::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<typename CTy> std::locale::id format_punct<CTy>::id; + + template<typename CTy, typename CTr> + GLM_FUNC_QUALIFIER basic_state_saver<CTy, CTr>::basic_state_saver(std::basic_ios<CTy, CTr>& a) + : state_(a) + , flags_(a.flags()) + , precision_(a.precision()) + , width_(a.width()) + , fill_(a.fill()) + , locale_(a.getloc()) + {} + + template<typename CTy, typename CTr> + GLM_FUNC_QUALIFIER basic_state_saver<CTy, CTr>::~basic_state_saver() + { + state_.imbue(locale_); + state_.fill(fill_); + state_.width(width_); + state_.precision(precision_); + state_.flags(flags_); + } + + template<typename CTy, typename CTr> + GLM_FUNC_QUALIFIER basic_format_saver<CTy, CTr>::basic_format_saver(std::basic_ios<CTy, CTr>& a) + : bss_(a) + { + a.imbue(std::locale(a.getloc(), new format_punct<CTy>(get_facet<format_punct<CTy> >(a)))); + } + + template<typename CTy, typename CTr> + GLM_FUNC_QUALIFIER + basic_format_saver<CTy, CTr>::~basic_format_saver() + {} + + GLM_FUNC_QUALIFIER precision::precision(unsigned a) + : value(a) + {} + + GLM_FUNC_QUALIFIER width::width(unsigned a) + : value(a) + {} + + template<typename CTy> + GLM_FUNC_QUALIFIER delimeter<CTy>::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<typename FTy, typename CTy, typename CTr> + GLM_FUNC_QUALIFIER FTy const& get_facet(std::basic_ios<CTy, CTr>& ios) + { + if(!std::has_facet<FTy>(ios.getloc())) + ios.imbue(std::locale(ios.getloc(), new FTy)); + + return std::use_facet<FTy>(ios.getloc()); + } + + template<typename CTy, typename CTr> + GLM_FUNC_QUALIFIER std::basic_ios<CTy, CTr>& formatted(std::basic_ios<CTy, CTr>& ios) + { + const_cast<format_punct<CTy>&>(get_facet<format_punct<CTy> >(ios)).formatted = true; + return ios; + } + + template<typename CTy, typename CTr> + GLM_FUNC_QUALIFIER std::basic_ios<CTy, CTr>& unformatted(std::basic_ios<CTy, CTr>& ios) + { + const_cast<format_punct<CTy>&>(get_facet<format_punct<CTy> >(ios)).formatted = false; + return ios; + } + + template<typename CTy, typename CTr> + GLM_FUNC_QUALIFIER std::basic_ostream<CTy, CTr>& operator<<(std::basic_ostream<CTy, CTr>& os, precision const& a) + { + const_cast<format_punct<CTy>&>(get_facet<format_punct<CTy> >(os)).precision = a.value; + return os; + } + + template<typename CTy, typename CTr> + GLM_FUNC_QUALIFIER std::basic_ostream<CTy, CTr>& operator<<(std::basic_ostream<CTy, CTr>& os, width const& a) + { + const_cast<format_punct<CTy>&>(get_facet<format_punct<CTy> >(os)).width = a.value; + return os; + } + + template<typename CTy, typename CTr> + GLM_FUNC_QUALIFIER std::basic_ostream<CTy, CTr>& operator<<(std::basic_ostream<CTy, CTr>& os, delimeter<CTy> const& a) + { + format_punct<CTy> & fmt(const_cast<format_punct<CTy>&>(get_facet<format_punct<CTy> >(os))); + + fmt.delim_left = a.value[0]; + fmt.delim_right = a.value[1]; + fmt.separator = a.value[2]; + + return os; + } + + template<typename CTy, typename CTr> + GLM_FUNC_QUALIFIER std::basic_ostream<CTy, CTr>& operator<<(std::basic_ostream<CTy, CTr>& os, order const& a) + { + const_cast<format_punct<CTy>&>(get_facet<format_punct<CTy> >(os)).order = a.value; + return os; + } +} // namespace io + +namespace detail +{ + template<typename CTy, typename CTr, typename V> + GLM_FUNC_QUALIFIER std::basic_ostream<CTy, CTr>& + print_vector_on(std::basic_ostream<CTy, CTr>& os, V const& a) + { + typename std::basic_ostream<CTy, CTr>::sentry const cerberus(os); + + if(cerberus) + { + io::format_punct<CTy> const& fmt(io::get_facet<io::format_punct<CTy> >(os)); + + length_t const& components(type<V>::components); + + if(fmt.formatted) + { + io::basic_state_saver<CTy> const bss(os); + + os << std::fixed << std::right << std::setprecision(fmt.precision) << std::setfill(fmt.space) << fmt.delim_left; + + for(length_t i(0); i < components; ++i) + { + os << std::setw(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<typename CTy, typename CTr, typename T, qualifier Q> + GLM_FUNC_QUALIFIER std::basic_ostream<CTy,CTr>& operator<<(std::basic_ostream<CTy,CTr>& os, qua<T, Q> const& a) + { + return detail::print_vector_on(os, a); + } + + template<typename CTy, typename CTr, typename T, qualifier Q> + GLM_FUNC_QUALIFIER std::basic_ostream<CTy,CTr>& operator<<(std::basic_ostream<CTy,CTr>& os, vec<1, T, Q> const& a) + { + return detail::print_vector_on(os, a); + } + + template<typename CTy, typename CTr, typename T, qualifier Q> + GLM_FUNC_QUALIFIER std::basic_ostream<CTy,CTr>& operator<<(std::basic_ostream<CTy,CTr>& os, vec<2, T, Q> const& a) + { + return detail::print_vector_on(os, a); + } + + template<typename CTy, typename CTr, typename T, qualifier Q> + GLM_FUNC_QUALIFIER std::basic_ostream<CTy,CTr>& operator<<(std::basic_ostream<CTy,CTr>& os, vec<3, T, Q> const& a) + { + return detail::print_vector_on(os, a); + } + + template<typename CTy, typename CTr, typename T, qualifier Q> + GLM_FUNC_QUALIFIER std::basic_ostream<CTy,CTr>& operator<<(std::basic_ostream<CTy,CTr>& os, vec<4, T, Q> const& a) + { + return detail::print_vector_on(os, a); + } + +namespace detail +{ + template<typename CTy, typename CTr, template<length_t, length_t, typename, qualifier> class M, length_t C, length_t R, typename T, qualifier Q> + GLM_FUNC_QUALIFIER std::basic_ostream<CTy, CTr>& print_matrix_on(std::basic_ostream<CTy, CTr>& os, M<C, R, T, Q> const& a) + { + typename std::basic_ostream<CTy,CTr>::sentry const cerberus(os); + + if(cerberus) + { + io::format_punct<CTy> const& fmt(io::get_facet<io::format_punct<CTy> >(os)); + + length_t const& cols(type<M<C, R, T, Q> >::cols); + length_t const& rows(type<M<C, R, T, Q> >::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<typename CTy, typename CTr, typename T, qualifier Q> + GLM_FUNC_QUALIFIER std::basic_ostream<CTy,CTr>& operator<<(std::basic_ostream<CTy,CTr>& os, mat<2, 2, T, Q> const& a) + { + return detail::print_matrix_on(os, a); + } + + template<typename CTy, typename CTr, typename T, qualifier Q> + GLM_FUNC_QUALIFIER std::basic_ostream<CTy,CTr>& operator<<(std::basic_ostream<CTy,CTr>& os, mat<2, 3, T, Q> const& a) + { + return detail::print_matrix_on(os, a); + } + + template<typename CTy, typename CTr, typename T, qualifier Q> + GLM_FUNC_QUALIFIER std::basic_ostream<CTy,CTr>& operator<<(std::basic_ostream<CTy,CTr>& os, mat<2, 4, T, Q> const& a) + { + return detail::print_matrix_on(os, a); + } + + template<typename CTy, typename CTr, typename T, qualifier Q> + GLM_FUNC_QUALIFIER std::basic_ostream<CTy,CTr>& operator<<(std::basic_ostream<CTy,CTr>& os, mat<3, 2, T, Q> const& a) + { + return detail::print_matrix_on(os, a); + } + + template<typename CTy, typename CTr, typename T, qualifier Q> + GLM_FUNC_QUALIFIER std::basic_ostream<CTy,CTr>& operator<<(std::basic_ostream<CTy,CTr>& os, mat<3, 3, T, Q> const& a) + { + return detail::print_matrix_on(os, a); + } + + template<typename CTy, typename CTr, typename T, qualifier Q> + GLM_FUNC_QUALIFIER std::basic_ostream<CTy,CTr> & operator<<(std::basic_ostream<CTy,CTr>& os, mat<3, 4, T, Q> const& a) + { + return detail::print_matrix_on(os, a); + } + + template<typename CTy, typename CTr, typename T, qualifier Q> + GLM_FUNC_QUALIFIER std::basic_ostream<CTy,CTr> & operator<<(std::basic_ostream<CTy,CTr>& os, mat<4, 2, T, Q> const& a) + { + return detail::print_matrix_on(os, a); + } + + template<typename CTy, typename CTr, typename T, qualifier Q> + GLM_FUNC_QUALIFIER std::basic_ostream<CTy,CTr> & operator<<(std::basic_ostream<CTy,CTr>& os, mat<4, 3, T, Q> const& a) + { + return detail::print_matrix_on(os, a); + } + + template<typename CTy, typename CTr, typename T, qualifier Q> + GLM_FUNC_QUALIFIER std::basic_ostream<CTy,CTr> & operator<<(std::basic_ostream<CTy,CTr>& os, mat<4, 4, T, Q> const& a) + { + return detail::print_matrix_on(os, a); + } + +namespace detail +{ + template<typename CTy, typename CTr, template<length_t, length_t, typename, qualifier> class M, length_t C, length_t R, typename T, qualifier Q> + GLM_FUNC_QUALIFIER std::basic_ostream<CTy, CTr>& print_matrix_pair_on(std::basic_ostream<CTy, CTr>& os, std::pair<M<C, R, T, Q> const, M<C, R, T, Q> const> const& a) + { + typename std::basic_ostream<CTy,CTr>::sentry const cerberus(os); + + if(cerberus) + { + io::format_punct<CTy> const& fmt(io::get_facet<io::format_punct<CTy> >(os)); + M<C, R, T, Q> const& ml(a.first); + M<C, R, T, Q> const& mr(a.second); + length_t const& cols(type<M<C, R, T, Q> >::cols); + length_t const& rows(type<M<C, R, T, Q> >::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<typename CTy, typename CTr, typename T, qualifier Q> + GLM_FUNC_QUALIFIER std::basic_ostream<CTy, CTr>& operator<<( + std::basic_ostream<CTy, CTr> & os, + std::pair<mat<4, 4, T, Q> const, + mat<4, 4, T, Q> const> const& a) + { + return detail::print_matrix_pair_on(os, a); + } +}//namespace glm 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 0000000000000000000000000000000000000000..ba28c9d7bffcb27c32dc13818eeaac4d9f231dd8 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/gtx/log_base.hpp @@ -0,0 +1,48 @@ +/// @ref gtx_log_base +/// @file glm/gtx/log_base.hpp +/// +/// @see core (dependence) +/// +/// @defgroup gtx_log_base GLM_GTX_log_base +/// @ingroup gtx +/// +/// Include <glm/gtx/log_base.hpp> 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" + +#if GLM_MESSAGES == GLM_ENABLE && !defined(GLM_EXT_INCLUDED) +# ifndef GLM_ENABLE_EXPERIMENTAL +# pragma message("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.") +# else +# pragma message("GLM: GLM_GTX_log_base extension included") +# endif +#endif + +namespace glm +{ + /// @addtogroup gtx_log_base + /// @{ + + /// Logarithm for any base. + /// From GLM_GTX_log_base. + template<typename genType> + GLM_FUNC_DECL genType log( + genType const& x, + genType const& base); + + /// Logarithm for any base. + /// From GLM_GTX_log_base. + template<length_t L, typename T, qualifier Q> + GLM_FUNC_DECL vec<L, T, Q> sign( + vec<L, T, Q> const& x, + vec<L, T, Q> 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 0000000000000000000000000000000000000000..4bbb8e895abbdac32e58cc4e66f700ac86ba17a4 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/gtx/log_base.inl @@ -0,0 +1,16 @@ +/// @ref gtx_log_base + +namespace glm +{ + template<typename genType> + GLM_FUNC_QUALIFIER genType log(genType const& x, genType const& base) + { + return glm::log(x) / glm::log(base); + } + + template<length_t L, typename T, qualifier Q> + GLM_FUNC_QUALIFIER vec<L, T, Q> log(vec<L, T, Q> const& x, vec<L, T, Q> 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 0000000000000000000000000000000000000000..1e585f9a4ffe8e9eadae27a26c6cb9dd5f5b294b --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/gtx/matrix_cross_product.hpp @@ -0,0 +1,47 @@ +/// @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 <glm/gtx/matrix_cross_product.hpp> to use the features of this extension. +/// +/// Build cross product matrices + +#pragma once + +// Dependency: +#include "../glm.hpp" + +#if GLM_MESSAGES == GLM_ENABLE && !defined(GLM_EXT_INCLUDED) +# ifndef GLM_ENABLE_EXPERIMENTAL +# pragma message("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.") +# else +# pragma message("GLM: GLM_GTX_matrix_cross_product extension included") +# endif +#endif + +namespace glm +{ + /// @addtogroup gtx_matrix_cross_product + /// @{ + + //! Build a cross product matrix. + //! From GLM_GTX_matrix_cross_product extension. + template<typename T, qualifier Q> + 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<typename T, qualifier Q> + 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 0000000000000000000000000000000000000000..3a153977cf59d977d3f4c318569751dee4f27331 --- /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<typename T, qualifier Q> + 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<typename T, qualifier Q> + 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 0000000000000000000000000000000000000000..acd7a7f0681a20ffeaa34d6ad9e911508776bf7f --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/gtx/matrix_decompose.hpp @@ -0,0 +1,46 @@ +/// @ref gtx_matrix_decompose +/// @file glm/gtx/matrix_decompose.hpp +/// +/// @see core (dependence) +/// +/// @defgroup gtx_matrix_decompose GLM_GTX_matrix_decompose +/// @ingroup gtx +/// +/// Include <glm/gtx/matrix_decompose.hpp> 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" + +#if GLM_MESSAGES == GLM_ENABLE && !defined(GLM_EXT_INCLUDED) +# ifndef GLM_ENABLE_EXPERIMENTAL +# pragma message("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.") +# else +# pragma message("GLM: GLM_GTX_matrix_decompose extension included") +# endif +#endif + +namespace glm +{ + /// @addtogroup gtx_matrix_decompose + /// @{ + + /// Decomposes a model matrix to translations, rotation and scale components + /// @see gtx_matrix_decompose + template<typename T, qualifier Q> + GLM_FUNC_DECL bool decompose( + mat<4, 4, T, Q> const& modelMatrix, + vec<3, T, Q> & scale, qua<T, Q> & orientation, vec<3, T, Q> & translation, vec<3, T, Q> & skew, vec<4, T, Q> & 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 0000000000000000000000000000000000000000..694f5eca74a44945cc6d59d363fb86090258d94a --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/gtx/matrix_decompose.inl @@ -0,0 +1,186 @@ +/// @ref gtx_matrix_decompose + +#include "../gtc/constants.hpp" +#include "../gtc/epsilon.hpp" + +namespace glm{ +namespace detail +{ + /// Make a linear combination of two vectors and return the result. + // result = (a * ascl) + (b * bscl) + template<typename T, qualifier Q> + 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<typename T, qualifier Q> + 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<typename T, qualifier Q> + GLM_FUNC_QUALIFIER bool decompose(mat<4, 4, T, Q> const& ModelMatrix, vec<3, T, Q> & Scale, qua<T, Q> & 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<T>(0), epsilon<T>())) + 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<T>(0); + PerspectiveMatrix[3][3] = static_cast<T>(1); + + /// TODO: Fixme! + if(epsilonEqual(determinant(PerspectiveMatrix), static_cast<T>(0), epsilon<T>())) + return false; + + // First, isolate perspective. This is the messiest. + if( + epsilonNotEqual(LocalMatrix[0][3], static_cast<T>(0), epsilon<T>()) || + epsilonNotEqual(LocalMatrix[1][3], static_cast<T>(0), epsilon<T>()) || + epsilonNotEqual(LocalMatrix[2][3], static_cast<T>(0), epsilon<T>())) + { + // 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<T>(0); + LocalMatrix[3][3] = static_cast<T>(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<T>(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<T>(1), -Skew.z); + + // Now, compute Y scale and normalize 2nd row. + Scale.y = length(Row[1]); + Row[1] = detail::scale(Row[1], static_cast<T>(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<T>(1), -Skew.y); + Skew.x = glm::dot(Row[1], Row[2]); + Row[2] = detail::combine(Row[2], Row[1], static_cast<T>(1), -Skew.x); + + // Next, get Z scale and normalize 3rd row. + Scale.z = length(Row[2]); + Row[2] = detail::scale(Row[2], static_cast<T>(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<T>(-1); + Row[i] *= static_cast<T>(-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<T>(0)) + { + root = sqrt(trace + static_cast<T>(1.0)); + Orientation.w = static_cast<T>(0.5) * root; + root = static_cast<T>(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]; + + root = sqrt(Row[i][i] - Row[j][j] - Row[k][k] + static_cast<T>(1.0)); + + Orientation[i] = static_cast<T>(0.5) * root; + root = static_cast<T>(0.5) / root; + Orientation[j] = root * (Row[i][j] + Row[j][i]); + Orientation[k] = root * (Row[i][k] + Row[k][i]); + Orientation.w = root * (Row[j][k] - Row[k][j]); + } // End if <= 0 + + return true; + } +}//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 0000000000000000000000000000000000000000..5a975d60b6c2ca9fb03b9a92541679ebe75f988c --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/gtx/matrix_factorisation.hpp @@ -0,0 +1,69 @@ +/// @ref gtx_matrix_factorisation +/// @file glm/gtx/matrix_factorisation.hpp +/// +/// @see core (dependence) +/// +/// @defgroup gtx_matrix_factorisation GLM_GTX_matrix_factorisation +/// @ingroup gtx +/// +/// Include <glm/gtx/matrix_factorisation.hpp> to use the features of this extension. +/// +/// Functions to factor matrices in various forms + +#pragma once + +// Dependency: +#include "../glm.hpp" + +#if GLM_MESSAGES == GLM_ENABLE && !defined(GLM_EXT_INCLUDED) +# ifndef GLM_ENABLE_EXPERIMENTAL +# pragma message("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.") +# else +# pragma message("GLM: GLM_GTX_matrix_factorisation extension included") +# endif +#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 <length_t C, length_t R, typename T, qualifier Q> + GLM_FUNC_DECL mat<C, R, T, Q> flipud(mat<C, R, T, Q> const& in); + + /// Flips the matrix columns right and left. + /// + /// From GLM_GTX_matrix_factorisation extension. + template <length_t C, length_t R, typename T, qualifier Q> + GLM_FUNC_DECL mat<C, R, T, Q> fliplr(mat<C, R, T, Q> 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 <length_t C, length_t R, typename T, qualifier Q> + GLM_FUNC_DECL void qr_decompose(mat<C, R, T, Q> const& in, mat<(C < R ? C : R), R, T, Q>& q, mat<C, (C < R ? C : R), T, Q>& 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 <length_t C, length_t R, typename T, qualifier Q> + GLM_FUNC_DECL void rq_decompose(mat<C, R, T, Q> const& in, mat<(C < R ? C : R), R, T, Q>& r, mat<C, (C < R ? C : R), T, Q>& 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 0000000000000000000000000000000000000000..c479b8ad99094b0a301ef29b31e112e7441ea143 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/gtx/matrix_factorisation.inl @@ -0,0 +1,84 @@ +/// @ref gtx_matrix_factorisation + +namespace glm +{ + template <length_t C, length_t R, typename T, qualifier Q> + GLM_FUNC_QUALIFIER mat<C, R, T, Q> flipud(mat<C, R, T, Q> const& in) + { + mat<R, C, T, Q> tin = transpose(in); + tin = fliplr(tin); + mat<C, R, T, Q> out = transpose(tin); + + return out; + } + + template <length_t C, length_t R, typename T, qualifier Q> + GLM_FUNC_QUALIFIER mat<C, R, T, Q> fliplr(mat<C, R, T, Q> const& in) + { + mat<C, R, T, Q> out; + for (length_t i = 0; i < C; i++) + { + out[i] = in[(C - i) - 1]; + } + + return out; + } + + template <length_t C, length_t R, typename T, qualifier Q> + GLM_FUNC_QUALIFIER void qr_decompose(mat<C, R, T, Q> const& in, mat<(C < R ? C : R), R, T, Q>& q, mat<C, (C < R ? C : R), T, Q>& r) + { + // Uses modified Gram-Schmidt method + // Source: https://en.wikipedia.org/wiki/Gram–Schmidt_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 <length_t C, length_t R, typename T, qualifier Q> + GLM_FUNC_QUALIFIER void rq_decompose(mat<C, R, T, Q> const& in, mat<(C < R ? C : R), R, T, Q>& r, mat<C, (C < R ? C : R), T, Q>& 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<R, C, T, Q> tin = transpose(in); + tin = fliplr(tin); + + mat<R, (C < R ? C : R), T, Q> 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 0000000000000000000000000000000000000000..7d5ad4cd9ad9f1a845a9fe7327a73399d1ea58a6 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/gtx/matrix_interpolation.hpp @@ -0,0 +1,60 @@ +/// @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 <glm/gtx/matrix_interpolation.hpp> to use the features of this extension. +/// +/// Allows to directly interpolate two matrices. + +#pragma once + +// Dependency: +#include "../glm.hpp" + +#if GLM_MESSAGES == GLM_ENABLE && !defined(GLM_EXT_INCLUDED) +# ifndef GLM_ENABLE_EXPERIMENTAL +# pragma message("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.") +# else +# pragma message("GLM: GLM_GTX_matrix_interpolation extension included") +# endif +#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<typename T, qualifier Q> + GLM_FUNC_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<typename T, qualifier Q> + 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<typename T, qualifier Q> + 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<typename T, qualifier Q> + 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 0000000000000000000000000000000000000000..de40b7d745ec138797ddc47ad94bbf32a1d9ca4e --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/gtx/matrix_interpolation.inl @@ -0,0 +1,129 @@ +/// @ref gtx_matrix_interpolation + +#include "../gtc/constants.hpp" + +namespace glm +{ + template<typename T, qualifier Q> + GLM_FUNC_QUALIFIER void axisAngle(mat<4, 4, T, Q> const& m, vec<3, T, Q> & axis, T& angle) + { + T epsilon = static_cast<T>(0.01); + T epsilon2 = static_cast<T>(0.1); + + if((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 ((abs(m[1][0] + m[0][1]) < epsilon2) && (abs(m[2][0] + m[0][2]) < epsilon2) && (abs(m[2][1] + m[1][2]) < epsilon2) && (abs(m[0][0] + m[1][1] + m[2][2] - static_cast<T>(3.0)) < epsilon2)) + { + angle = static_cast<T>(0.0); + axis.x = static_cast<T>(1.0); + axis.y = static_cast<T>(0.0); + axis.z = static_cast<T>(0.0); + return; + } + angle = static_cast<T>(3.1415926535897932384626433832795); + T xx = (m[0][0] + static_cast<T>(1.0)) * static_cast<T>(0.5); + T yy = (m[1][1] + static_cast<T>(1.0)) * static_cast<T>(0.5); + T zz = (m[2][2] + static_cast<T>(1.0)) * static_cast<T>(0.5); + T xy = (m[1][0] + m[0][1]) * static_cast<T>(0.25); + T xz = (m[2][0] + m[0][2]) * static_cast<T>(0.25); + T yz = (m[2][1] + m[1][2]) * static_cast<T>(0.25); + if((xx > yy) && (xx > zz)) + { + if(xx < epsilon) + { + axis.x = static_cast<T>(0.0); + axis.y = static_cast<T>(0.7071); + axis.z = static_cast<T>(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<T>(0.7071); + axis.y = static_cast<T>(0.0); + axis.z = static_cast<T>(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<T>(0.7071); + axis.y = static_cast<T>(0.7071); + axis.z = static_cast<T>(0.0); + } + else + { + axis.z = sqrt(zz); + axis.x = xz / axis.z; + axis.y = yz / axis.z; + } + } + return; + } + T s = sqrt((m[2][1] - m[1][2]) * (m[2][1] - m[1][2]) + (m[2][0] - m[0][2]) * (m[2][0] - m[0][2]) + (m[1][0] - m[0][1]) * (m[1][0] - m[0][1])); + if (glm::abs(s) < T(0.001)) + s = static_cast<T>(1); + T const angleCos = (m[0][0] + m[1][1] + m[2][2] - static_cast<T>(1)) * static_cast<T>(0.5); + if(angleCos - static_cast<T>(1) < epsilon) + angle = pi<T>() * static_cast<T>(0.25); + else + angle = acos(angleCos); + axis.x = (m[1][2] - m[2][1]) / s; + axis.y = (m[2][0] - m[0][2]) / s; + axis.z = (m[0][1] - m[1][0]) / s; + } + + template<typename T, qualifier Q> + 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<T>(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<T>(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<T>(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<T>(0.0), + static_cast<T>(0.0), static_cast<T>(0.0), static_cast<T>(0.0), static_cast<T>(1.0)); + } + + template<typename T, qualifier Q> + 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<T>(0.0), + m[1][0], m[1][1], m[1][2], static_cast<T>(0.0), + m[2][0], m[2][1], m[2][2], static_cast<T>(0.0), + static_cast<T>(0.0), static_cast<T>(0.0), static_cast<T>(0.0), static_cast<T>(1.0)); + } + + template<typename T, qualifier Q> + 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 0000000000000000000000000000000000000000..8c6bc22d14e96da6a01552dde90f5fecf6a2e1b8 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/gtx/matrix_major_storage.hpp @@ -0,0 +1,119 @@ +/// @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 <glm/gtx/matrix_major_storage.hpp> to use the features of this extension. +/// +/// Build matrices with specific matrix order, row or column + +#pragma once + +// Dependency: +#include "../glm.hpp" + +#if GLM_MESSAGES == GLM_ENABLE && !defined(GLM_EXT_INCLUDED) +# ifndef GLM_ENABLE_EXPERIMENTAL +# pragma message("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.") +# else +# pragma message("GLM: GLM_GTX_matrix_major_storage extension included") +# endif +#endif + +namespace glm +{ + /// @addtogroup gtx_matrix_major_storage + /// @{ + + //! Build a row major matrix from row vectors. + //! From GLM_GTX_matrix_major_storage extension. + template<typename T, qualifier Q> + 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<typename T, qualifier Q> + 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<typename T, qualifier Q> + 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<typename T, qualifier Q> + 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<typename T, qualifier Q> + 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<typename T, qualifier Q> + 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<typename T, qualifier Q> + 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<typename T, qualifier Q> + 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<typename T, qualifier Q> + 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<typename T, qualifier Q> + 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<typename T, qualifier Q> + 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<typename T, qualifier Q> + 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 0000000000000000000000000000000000000000..279dd3433d0bd6dd5509cc1da75ee5b212eac784 --- /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<typename T, qualifier Q> + 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<typename T, qualifier Q> + 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<typename T, qualifier Q> + 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<typename T, qualifier Q> + 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<typename T, qualifier Q> + 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<typename T, qualifier Q> + 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<typename T, qualifier Q> + 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<typename T, qualifier Q> + GLM_FUNC_QUALIFIER mat<2, 2, T, Q> colMajor2( + const mat<2, 2, T, Q>& m) + { + return mat<2, 2, T, Q>(m); + } + + template<typename T, qualifier Q> + 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<typename T, qualifier Q> + GLM_FUNC_QUALIFIER mat<3, 3, T, Q> colMajor3( + const mat<3, 3, T, Q>& m) + { + return mat<3, 3, T, Q>(m); + } + + template<typename T, qualifier Q> + 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<typename T, qualifier Q> + 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 0000000000000000000000000000000000000000..de6ff1f86f47f5b99d7be8d48637e97d5f98e668 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/gtx/matrix_operation.hpp @@ -0,0 +1,103 @@ +/// @ref gtx_matrix_operation +/// @file glm/gtx/matrix_operation.hpp +/// +/// @see core (dependence) +/// +/// @defgroup gtx_matrix_operation GLM_GTX_matrix_operation +/// @ingroup gtx +/// +/// Include <glm/gtx/matrix_operation.hpp> to use the features of this extension. +/// +/// Build diagonal matrices from vectors. + +#pragma once + +// Dependency: +#include "../glm.hpp" + +#if GLM_MESSAGES == GLM_ENABLE && !defined(GLM_EXT_INCLUDED) +# ifndef GLM_ENABLE_EXPERIMENTAL +# pragma message("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.") +# else +# pragma message("GLM: GLM_GTX_matrix_operation extension included") +# endif +#endif + +namespace glm +{ + /// @addtogroup gtx_matrix_operation + /// @{ + + //! Build a diagonal matrix. + //! From GLM_GTX_matrix_operation extension. + template<typename T, qualifier Q> + 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<typename T, qualifier Q> + 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<typename T, qualifier Q> + 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<typename T, qualifier Q> + 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<typename T, qualifier Q> + 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<typename T, qualifier Q> + 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<typename T, qualifier Q> + 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<typename T, qualifier Q> + 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<typename T, qualifier Q> + 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<typename T, qualifier Q> + 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<typename T, qualifier Q> + 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<typename T, qualifier Q> + 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 0000000000000000000000000000000000000000..9de83f82367157792446e91d3eeb627c1947bb3c --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/gtx/matrix_operation.inl @@ -0,0 +1,176 @@ +/// @ref gtx_matrix_operation + +namespace glm +{ + template<typename T, qualifier Q> + GLM_FUNC_QUALIFIER mat<2, 2, T, Q> diagonal2x2 + ( + vec<2, T, Q> const& v + ) + { + mat<2, 2, T, Q> Result(static_cast<T>(1)); + Result[0][0] = v[0]; + Result[1][1] = v[1]; + return Result; + } + + template<typename T, qualifier Q> + GLM_FUNC_QUALIFIER mat<2, 3, T, Q> diagonal2x3 + ( + vec<2, T, Q> const& v + ) + { + mat<2, 3, T, Q> Result(static_cast<T>(1)); + Result[0][0] = v[0]; + Result[1][1] = v[1]; + return Result; + } + + template<typename T, qualifier Q> + GLM_FUNC_QUALIFIER mat<2, 4, T, Q> diagonal2x4 + ( + vec<2, T, Q> const& v + ) + { + mat<2, 4, T, Q> Result(static_cast<T>(1)); + Result[0][0] = v[0]; + Result[1][1] = v[1]; + return Result; + } + + template<typename T, qualifier Q> + GLM_FUNC_QUALIFIER mat<3, 2, T, Q> diagonal3x2 + ( + vec<2, T, Q> const& v + ) + { + mat<3, 2, T, Q> Result(static_cast<T>(1)); + Result[0][0] = v[0]; + Result[1][1] = v[1]; + return Result; + } + + template<typename T, qualifier Q> + GLM_FUNC_QUALIFIER mat<3, 3, T, Q> diagonal3x3 + ( + vec<3, T, Q> const& v + ) + { + mat<3, 3, T, Q> Result(static_cast<T>(1)); + Result[0][0] = v[0]; + Result[1][1] = v[1]; + Result[2][2] = v[2]; + return Result; + } + + template<typename T, qualifier Q> + GLM_FUNC_QUALIFIER mat<3, 4, T, Q> diagonal3x4 + ( + vec<3, T, Q> const& v + ) + { + mat<3, 4, T, Q> Result(static_cast<T>(1)); + Result[0][0] = v[0]; + Result[1][1] = v[1]; + Result[2][2] = v[2]; + return Result; + } + + template<typename T, qualifier Q> + GLM_FUNC_QUALIFIER mat<4, 4, T, Q> diagonal4x4 + ( + vec<4, T, Q> const& v + ) + { + mat<4, 4, T, Q> Result(static_cast<T>(1)); + Result[0][0] = v[0]; + Result[1][1] = v[1]; + Result[2][2] = v[2]; + Result[3][3] = v[3]; + return Result; + } + + template<typename T, qualifier Q> + GLM_FUNC_QUALIFIER mat<4, 3, T, Q> diagonal4x3 + ( + vec<3, T, Q> const& v + ) + { + mat<4, 3, T, Q> Result(static_cast<T>(1)); + Result[0][0] = v[0]; + Result[1][1] = v[1]; + Result[2][2] = v[2]; + return Result; + } + + template<typename T, qualifier Q> + GLM_FUNC_QUALIFIER mat<4, 2, T, Q> diagonal4x2 + ( + vec<2, T, Q> const& v + ) + { + mat<4, 2, T, Q> Result(static_cast<T>(1)); + Result[0][0] = v[0]; + Result[1][1] = v[1]; + return Result; + } + + template<typename T, qualifier Q> + 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[1][0], + -m[0][1], +m[0][0]); + } + + template<typename T, qualifier Q> + 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<typename T, qualifier Q> + 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][2], 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, -m01, +m02, -m03, + -m10, +m11, -m12, +m13, + +m20, -m21, +m22, -m23, + -m30, +m31, -m32, +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 0000000000000000000000000000000000000000..8011b2b1d469efdb98c2c5f1fe98538644e2ac05 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/gtx/matrix_query.hpp @@ -0,0 +1,77 @@ +/// @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 <glm/gtx/matrix_query.hpp> to use the features of this extension. +/// +/// Query to evaluate matrix properties + +#pragma once + +// Dependency: +#include "../glm.hpp" +#include "../gtx/vector_query.hpp" +#include <limits> + +#if GLM_MESSAGES == GLM_ENABLE && !defined(GLM_EXT_INCLUDED) +# ifndef GLM_ENABLE_EXPERIMENTAL +# pragma message("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.") +# else +# pragma message("GLM: GLM_GTX_matrix_query extension included") +# endif +#endif + +namespace glm +{ + /// @addtogroup gtx_matrix_query + /// @{ + + /// Return whether a matrix a null matrix. + /// From GLM_GTX_matrix_query extension. + template<typename T, qualifier Q> + 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<typename T, qualifier Q> + 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<typename T, qualifier Q> + 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<length_t C, length_t R, typename T, qualifier Q, template<length_t, length_t, typename, qualifier> class matType> + GLM_FUNC_DECL bool isIdentity(matType<C, R, T, Q> const& m, T const& epsilon); + + /// Return whether a matrix is a normalized matrix. + /// From GLM_GTX_matrix_query extension. + template<typename T, qualifier Q> + 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<typename T, qualifier Q> + 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<typename T, qualifier Q> + 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<length_t C, length_t R, typename T, qualifier Q, template<length_t, length_t, typename, qualifier> class matType> + GLM_FUNC_DECL bool isOrthogonal(matType<C, R, T, Q> 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 0000000000000000000000000000000000000000..77bd23108e3bf3dd4880fc8072b8a7c9ee27e37e --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/gtx/matrix_query.inl @@ -0,0 +1,113 @@ +/// @ref gtx_matrix_query + +namespace glm +{ + template<typename T, qualifier Q> + 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<typename T, qualifier Q> + 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<typename T, qualifier Q> + 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<length_t C, length_t R, typename T, qualifier Q> + GLM_FUNC_QUALIFIER bool isIdentity(mat<C, R, T, Q> const& m, T const& epsilon) + { + bool result = true; + for(length_t i = 0; result && i < m[0].length() ; ++i) + { + for(length_t j = 0; result && j < i ; ++j) + result = abs(m[i][j]) <= epsilon; + if(result) + result = abs(m[i][i] - 1) <= epsilon; + for(length_t j = i + 1; result && j < m.length(); ++j) + result = abs(m[i][j]) <= epsilon; + } + return result; + } + + template<typename T, qualifier Q> + 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<typename T, qualifier Q> + 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<typename T, qualifier Q> + 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<length_t C, length_t R, typename T, qualifier Q> + GLM_FUNC_QUALIFIER bool isOrthogonal(mat<C, R, T, Q> const& m, T const& epsilon) + { + bool result = true; + for(length_t i(0); result && i < m.length() - 1; ++i) + for(length_t j(i + 1); result && j < m.length(); ++j) + result = areOrthogonal(m[i], m[j], epsilon); + + if(result) + { + mat<C, R, T, Q> tmp = transpose(m); + for(length_t i(0); result && i < m.length() - 1 ; ++i) + for(length_t j(i + 1); result && j < m.length(); ++j) + result = areOrthogonal(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 0000000000000000000000000000000000000000..5f9c540218511a9c47c79044049e534d30b9bfcb --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/gtx/matrix_transform_2d.hpp @@ -0,0 +1,81 @@ +/// @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 <glm/gtx/matrix_transform_2d.hpp> to use the features of this extension. +/// +/// Defines functions that generate common 2d transformation matrices. + +#pragma once + +// Dependency: +#include "../mat3x3.hpp" +#include "../vec2.hpp" + +#if GLM_MESSAGES == GLM_ENABLE && !defined(GLM_EXT_INCLUDED) +# ifndef GLM_ENABLE_EXPERIMENTAL +# pragma message("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.") +# else +# pragma message("GLM: GLM_GTX_matrix_transform_2d extension included") +# endif +#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<typename T, qualifier Q> + 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<typename T, qualifier Q> + 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<typename T, qualifier Q> + 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<typename T, qualifier Q> + 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<typename T, qualifier Q> + 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 0000000000000000000000000000000000000000..a68d24dc9825c97cf47753779ed97834ea77aba0 --- /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<typename T, qualifier Q> + 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<typename T, qualifier Q> + 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<typename T, qualifier Q> + 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<typename T, qualifier Q> + 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<typename T, qualifier Q> + 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 0000000000000000000000000000000000000000..b242e357e57a1b6e4c8b837e2d90841a0d0d5f7d --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/gtx/mixed_product.hpp @@ -0,0 +1,41 @@ +/// @ref gtx_mixed_product +/// @file glm/gtx/mixed_product.hpp +/// +/// @see core (dependence) +/// +/// @defgroup gtx_mixed_product GLM_GTX_mixed_producte +/// @ingroup gtx +/// +/// Include <glm/gtx/mixed_product.hpp> to use the features of this extension. +/// +/// Mixed product of 3 vectors. + +#pragma once + +// Dependency: +#include "../glm.hpp" + +#if GLM_MESSAGES == GLM_ENABLE && !defined(GLM_EXT_INCLUDED) +# ifndef GLM_ENABLE_EXPERIMENTAL +# pragma message("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.") +# else +# pragma message("GLM: GLM_GTX_mixed_product extension included") +# endif +#endif + +namespace glm +{ + /// @addtogroup gtx_mixed_product + /// @{ + + /// @brief Mixed product of 3 vectors (from GLM_GTX_mixed_product extension) + template<typename T, qualifier Q> + 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 0000000000000000000000000000000000000000..e5cdbdb49a2bb7457dd74ca08cdac0615d26b9c4 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/gtx/mixed_product.inl @@ -0,0 +1,15 @@ +/// @ref gtx_mixed_product + +namespace glm +{ + template<typename T, qualifier Q> + 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 0000000000000000000000000000000000000000..dfaebb7a8be26a65ed6769d87f75bcdc1d75bdb7 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/gtx/norm.hpp @@ -0,0 +1,88 @@ +/// @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 <glm/gtx/norm.hpp> 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" + +#if GLM_MESSAGES == GLM_ENABLE && !defined(GLM_EXT_INCLUDED) +# ifndef GLM_ENABLE_EXPERIMENTAL +# pragma message("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.") +# else +# pragma message("GLM: GLM_GTX_norm extension included") +# endif +#endif + +namespace glm +{ + /// @addtogroup gtx_norm + /// @{ + + /// Returns the squared length of x. + /// From GLM_GTX_norm extension. + template<length_t L, typename T, qualifier Q> + GLM_FUNC_DECL T length2(vec<L, T, Q> const& x); + + /// Returns the squared distance between p0 and p1, i.e., length2(p0 - p1). + /// From GLM_GTX_norm extension. + template<length_t L, typename T, qualifier Q> + GLM_FUNC_DECL T distance2(vec<L, T, Q> const& p0, vec<L, T, Q> const& p1); + + //! Returns the L1 norm between x and y. + //! From GLM_GTX_norm extension. + template<typename T, qualifier Q> + 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<typename T, qualifier Q> + 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<typename T, qualifier Q> + 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<typename T, qualifier Q> + 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<typename T, qualifier Q> + 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<typename T, qualifier Q> + 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<typename T, qualifier Q> + 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<typename T, qualifier Q> + 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 0000000000000000000000000000000000000000..6db561b37e0a062c71c6c3cdaabe021d0c1a62a4 --- /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<length_t L, typename T, qualifier Q, bool Aligned> + struct compute_length2 + { + GLM_FUNC_QUALIFIER static T call(vec<L, T, Q> const& v) + { + return dot(v, v); + } + }; +}//namespace detail + + template<typename genType> + GLM_FUNC_QUALIFIER genType length2(genType x) + { + GLM_STATIC_ASSERT(std::numeric_limits<genType>::is_iec559, "'length2' accepts only floating-point inputs"); + return x * x; + } + + template<length_t L, typename T, qualifier Q> + GLM_FUNC_QUALIFIER T length2(vec<L, T, Q> const& v) + { + GLM_STATIC_ASSERT(std::numeric_limits<T>::is_iec559, "'length2' accepts only floating-point inputs"); + return detail::compute_length2<L, T, Q, detail::is_aligned<Q>::value>::call(v); + } + + template<typename T> + GLM_FUNC_QUALIFIER T distance2(T p0, T p1) + { + GLM_STATIC_ASSERT(std::numeric_limits<T>::is_iec559, "'distance2' accepts only floating-point inputs"); + return length2(p1 - p0); + } + + template<length_t L, typename T, qualifier Q> + GLM_FUNC_QUALIFIER T distance2(vec<L, T, Q> const& p0, vec<L, T, Q> const& p1) + { + GLM_STATIC_ASSERT(std::numeric_limits<T>::is_iec559, "'distance2' accepts only floating-point inputs"); + return length2(p1 - p0); + } + + template<typename T, qualifier Q> + 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<typename T, qualifier Q> + GLM_FUNC_QUALIFIER T l1Norm(vec<3, T, Q> const& v) + { + return abs(v.x) + abs(v.y) + abs(v.z); + } + + template<typename T, qualifier Q> + GLM_FUNC_QUALIFIER T l2Norm(vec<3, T, Q> const& a, vec<3, T, Q> const& b + ) + { + return length(b - a); + } + + template<typename T, qualifier Q> + GLM_FUNC_QUALIFIER T l2Norm(vec<3, T, Q> const& v) + { + return length(v); + } + + template<typename T, qualifier Q> + 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<typename T, qualifier Q> + 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<typename T, qualifier Q> + GLM_FUNC_QUALIFIER T lMaxNorm(vec<3, T, Q> const& a, vec<3, T, Q> const& b) + { + return compMax(abs(b - a)); + } + + template<typename T, qualifier Q> + 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 0000000000000000000000000000000000000000..068682f75f2dac6596b58c6bac6d1dd02a49175c --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/gtx/normal.hpp @@ -0,0 +1,41 @@ +/// @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 <glm/gtx/normal.hpp> to use the features of this extension. +/// +/// Compute the normal of a triangle. + +#pragma once + +// Dependency: +#include "../glm.hpp" + +#if GLM_MESSAGES == GLM_ENABLE && !defined(GLM_EXT_INCLUDED) +# ifndef GLM_ENABLE_EXPERIMENTAL +# pragma message("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.") +# else +# pragma message("GLM: GLM_GTX_normal extension included") +# endif +#endif + +namespace glm +{ + /// @addtogroup gtx_normal + /// @{ + + /// Computes triangle normal from triangle points. + /// + /// @see gtx_normal + template<typename T, qualifier Q> + 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 0000000000000000000000000000000000000000..74f9fc9945854fbe607e87ef47bf506a332b8966 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/gtx/normal.inl @@ -0,0 +1,15 @@ +/// @ref gtx_normal + +namespace glm +{ + template<typename T, qualifier Q> + 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 0000000000000000000000000000000000000000..51958023f0144f0d2b42cb1d7a1619d03c1cde04 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/gtx/normalize_dot.hpp @@ -0,0 +1,49 @@ +/// @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 <glm/gtx/normalized_dot.hpp> 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" + +#if GLM_MESSAGES == GLM_ENABLE && !defined(GLM_EXT_INCLUDED) +# ifndef GLM_ENABLE_EXPERIMENTAL +# pragma message("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.") +# else +# pragma message("GLM: GLM_GTX_normalize_dot extension included") +# endif +#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<length_t L, typename T, qualifier Q> + GLM_FUNC_DECL T normalizeDot(vec<L, T, Q> const& x, vec<L, T, Q> 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<length_t L, typename T, qualifier Q> + GLM_FUNC_DECL T fastNormalizeDot(vec<L, T, Q> const& x, vec<L, T, Q> 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 0000000000000000000000000000000000000000..7bcd9a534a8f4df3a12118c746aadd6f264e264e --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/gtx/normalize_dot.inl @@ -0,0 +1,16 @@ +/// @ref gtx_normalize_dot + +namespace glm +{ + template<length_t L, typename T, qualifier Q> + GLM_FUNC_QUALIFIER T normalizeDot(vec<L, T, Q> const& x, vec<L, T, Q> const& y) + { + return glm::dot(x, y) * glm::inversesqrt(glm::dot(x, x) * glm::dot(y, y)); + } + + template<length_t L, typename T, qualifier Q> + GLM_FUNC_QUALIFIER T fastNormalizeDot(vec<L, T, Q> const& x, vec<L, T, Q> 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 0000000000000000000000000000000000000000..3a606bda040c8d91763c57fec09ea35e5890a24d --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/gtx/number_precision.hpp @@ -0,0 +1,61 @@ +/// @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 <glm/gtx/number_precision.hpp> to use the features of this extension. +/// +/// Defined size types. + +#pragma once + +// Dependency: +#include "../glm.hpp" +#include "../gtc/type_precision.hpp" + +#if GLM_MESSAGES == GLM_ENABLE && !defined(GLM_EXT_INCLUDED) +# ifndef GLM_ENABLE_EXPERIMENTAL +# pragma message("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.") +# else +# pragma message("GLM: GLM_GTX_number_precision extension included") +# endif +#endif + +namespace glm{ +namespace gtx +{ + ///////////////////////////// + // Unsigned int vector types + + /// @addtogroup gtx_number_precision + /// @{ + + typedef u8 u8vec1; //!< \brief 8bit unsigned integer scalar. (from GLM_GTX_number_precision extension) + typedef u16 u16vec1; //!< \brief 16bit unsigned integer scalar. (from GLM_GTX_number_precision extension) + typedef u32 u32vec1; //!< \brief 32bit unsigned integer scalar. (from GLM_GTX_number_precision extension) + typedef u64 u64vec1; //!< \brief 64bit unsigned integer scalar. (from GLM_GTX_number_precision extension) + + ////////////////////// + // Float vector types + + typedef f32 f32vec1; //!< \brief Single-qualifier floating-point scalar. (from GLM_GTX_number_precision extension) + typedef f64 f64vec1; //!< \brief Single-qualifier floating-point scalar. (from GLM_GTX_number_precision extension) + + ////////////////////// + // 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 gtx +}//namespace glm + +#include "number_precision.inl" diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/gtx/number_precision.inl b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/gtx/number_precision.inl new file mode 100644 index 0000000000000000000000000000000000000000..b39d71c3b49d322835a883ed9e5825206c2dc354 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/gtx/number_precision.inl @@ -0,0 +1,6 @@ +/// @ref gtx_number_precision + +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 0000000000000000000000000000000000000000..9284a474d491f748dfcf43c8ccbd3578622cb04b --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/gtx/optimum_pow.hpp @@ -0,0 +1,54 @@ +/// @ref gtx_optimum_pow +/// @file glm/gtx/optimum_pow.hpp +/// +/// @see core (dependence) +/// +/// @defgroup gtx_optimum_pow GLM_GTX_optimum_pow +/// @ingroup gtx +/// +/// Include <glm/gtx/optimum_pow.hpp> to use the features of this extension. +/// +/// Integer exponentiation of power functions. + +#pragma once + +// Dependency: +#include "../glm.hpp" + +#if GLM_MESSAGES == GLM_ENABLE && !defined(GLM_EXT_INCLUDED) +# ifndef GLM_ENABLE_EXPERIMENTAL +# pragma message("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.") +# else +# pragma message("GLM: GLM_GTX_optimum_pow extension included") +# endif +#endif + +namespace glm{ +namespace gtx +{ + /// @addtogroup gtx_optimum_pow + /// @{ + + /// Returns x raised to the power of 2. + /// + /// @see gtx_optimum_pow + template<typename genType> + GLM_FUNC_DECL genType pow2(genType const& x); + + /// Returns x raised to the power of 3. + /// + /// @see gtx_optimum_pow + template<typename genType> + GLM_FUNC_DECL genType pow3(genType const& x); + + /// Returns x raised to the power of 4. + /// + /// @see gtx_optimum_pow + template<typename genType> + GLM_FUNC_DECL genType pow4(genType const& x); + + /// @} +}//namespace gtx +}//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 0000000000000000000000000000000000000000..a26c19c18bfbd6b84d7c1be07d9448c6fbcb7e01 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/gtx/optimum_pow.inl @@ -0,0 +1,22 @@ +/// @ref gtx_optimum_pow + +namespace glm +{ + template<typename genType> + GLM_FUNC_QUALIFIER genType pow2(genType const& x) + { + return x * x; + } + + template<typename genType> + GLM_FUNC_QUALIFIER genType pow3(genType const& x) + { + return x * x * x; + } + + template<typename genType> + 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 0000000000000000000000000000000000000000..3e004fb06f9cd2e8d68f6a1cb073017a1bacfaf0 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/gtx/orthonormalize.hpp @@ -0,0 +1,49 @@ +/// @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 <glm/gtx/orthonormalize.hpp> to use the features of this extension. +/// +/// Orthonormalize matrices. + +#pragma once + +// Dependency: +#include "../vec3.hpp" +#include "../mat3x3.hpp" +#include "../geometric.hpp" + +#if GLM_MESSAGES == GLM_ENABLE && !defined(GLM_EXT_INCLUDED) +# ifndef GLM_ENABLE_EXPERIMENTAL +# pragma message("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.") +# else +# pragma message("GLM: GLM_GTX_orthonormalize extension included") +# endif +#endif + +namespace glm +{ + /// @addtogroup gtx_orthonormalize + /// @{ + + /// Returns the orthonormalized matrix of m. + /// + /// @see gtx_orthonormalize + template<typename T, qualifier Q> + GLM_FUNC_DECL mat<3, 3, T, Q> orthonormalize(mat<3, 3, T, Q> const& m); + + /// Orthonormalizes x according y. + /// + /// @see gtx_orthonormalize + template<typename T, qualifier Q> + 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 0000000000000000000000000000000000000000..cb553ba62157b3fca6c704777242bf473cdbe483 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/gtx/orthonormalize.inl @@ -0,0 +1,29 @@ +/// @ref gtx_orthonormalize + +namespace glm +{ + template<typename T, qualifier Q> + 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<typename T, qualifier Q> + 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/perpendicular.hpp b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/gtx/perpendicular.hpp new file mode 100644 index 0000000000000000000000000000000000000000..72b77b6e2388aada9c12070c804e0a02ba42ed86 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/gtx/perpendicular.hpp @@ -0,0 +1,41 @@ +/// @ref gtx_perpendicular +/// @file glm/gtx/perpendicular.hpp +/// +/// @see core (dependence) +/// @see gtx_projection (dependence) +/// +/// @defgroup gtx_perpendicular GLM_GTX_perpendicular +/// @ingroup gtx +/// +/// Include <glm/gtx/perpendicular.hpp> to use the features of this extension. +/// +/// Perpendicular of a vector from other one + +#pragma once + +// Dependency: +#include "../glm.hpp" +#include "../gtx/projection.hpp" + +#if GLM_MESSAGES == GLM_ENABLE && !defined(GLM_EXT_INCLUDED) +# ifndef GLM_ENABLE_EXPERIMENTAL +# pragma message("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.") +# else +# pragma message("GLM: GLM_GTX_perpendicular extension included") +# endif +#endif + +namespace glm +{ + /// @addtogroup gtx_perpendicular + /// @{ + + //! Projects x a perpendicular axis of Normal. + //! From GLM_GTX_perpendicular extension. + template<typename genType> + 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 0000000000000000000000000000000000000000..1e72f334230dee397361c2bae3af71600ee0a722 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/gtx/perpendicular.inl @@ -0,0 +1,10 @@ +/// @ref gtx_perpendicular + +namespace glm +{ + template<typename genType> + 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 0000000000000000000000000000000000000000..76beb82bd57c89ab1e8bcfa169b132f949f79e1a --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/gtx/polar_coordinates.hpp @@ -0,0 +1,48 @@ +/// @ref gtx_polar_coordinates +/// @file glm/gtx/polar_coordinates.hpp +/// +/// @see core (dependence) +/// +/// @defgroup gtx_polar_coordinates GLM_GTX_polar_coordinates +/// @ingroup gtx +/// +/// Include <glm/gtx/polar_coordinates.hpp> to use the features of this extension. +/// +/// Conversion from Euclidean space to polar space and revert. + +#pragma once + +// Dependency: +#include "../glm.hpp" + +#if GLM_MESSAGES == GLM_ENABLE && !defined(GLM_EXT_INCLUDED) +# ifndef GLM_ENABLE_EXPERIMENTAL +# pragma message("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.") +# else +# pragma message("GLM: GLM_GTX_polar_coordinates extension included") +# endif +#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<typename T, qualifier Q> + GLM_FUNC_DECL vec<3, T, Q> polar( + vec<3, T, Q> const& euclidean); + + /// Convert Polar to Euclidean coordinates. + /// + /// @see gtx_polar_coordinates + template<typename T, qualifier Q> + 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 0000000000000000000000000000000000000000..371c8dddebd1cf197ab8527b4bb8098edf733814 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/gtx/polar_coordinates.inl @@ -0,0 +1,36 @@ +/// @ref gtx_polar_coordinates + +namespace glm +{ + template<typename T, qualifier Q> + 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<typename T, qualifier Q> + 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 0000000000000000000000000000000000000000..678f3ad5a585f83b1a83d7d99960fae383dfb396 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/gtx/projection.hpp @@ -0,0 +1,43 @@ +/// @ref gtx_projection +/// @file glm/gtx/projection.hpp +/// +/// @see core (dependence) +/// +/// @defgroup gtx_projection GLM_GTX_projection +/// @ingroup gtx +/// +/// Include <glm/gtx/projection.hpp> to use the features of this extension. +/// +/// Projection of a vector to other one + +#pragma once + +// Dependency: +#include "../geometric.hpp" + +#if GLM_MESSAGES == GLM_ENABLE && !defined(GLM_EXT_INCLUDED) +# ifndef GLM_ENABLE_EXPERIMENTAL +# pragma message("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.") +# else +# pragma message("GLM: GLM_GTX_projection extension included") +# endif +#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<typename genType> + 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 0000000000000000000000000000000000000000..f23f884fb93a2c246d4560ec1f18c7292f9205c6 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/gtx/projection.inl @@ -0,0 +1,10 @@ +/// @ref gtx_projection + +namespace glm +{ + template<typename genType> + 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 0000000000000000000000000000000000000000..5c2b5ad0b574ca124eb9ad291b06236ccf7dfaca --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/gtx/quaternion.hpp @@ -0,0 +1,174 @@ +/// @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 <glm/gtx/quaternion.hpp> to use the features of this extension. +/// +/// Extented 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" + +#if GLM_MESSAGES == GLM_ENABLE && !defined(GLM_EXT_INCLUDED) +# ifndef GLM_ENABLE_EXPERIMENTAL +# pragma message("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.") +# else +# pragma message("GLM: GLM_GTX_quaternion extension included") +# endif +#endif + +namespace glm +{ + /// @addtogroup gtx_quaternion + /// @{ + + /// Create an identity quaternion. + /// + /// @see gtx_quaternion + template<typename T, qualifier Q> + GLM_FUNC_DECL GLM_CONSTEXPR qua<T, Q> quat_identity(); + + /// Compute a cross product between a quaternion and a vector. + /// + /// @see gtx_quaternion + template<typename T, qualifier Q> + GLM_FUNC_DECL vec<3, T, Q> cross( + qua<T, Q> const& q, + vec<3, T, Q> const& v); + + //! Compute a cross product between a vector and a quaternion. + /// + /// @see gtx_quaternion + template<typename T, qualifier Q> + GLM_FUNC_DECL vec<3, T, Q> cross( + vec<3, T, Q> const& v, + qua<T, Q> 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<typename T, qualifier Q> + GLM_FUNC_DECL qua<T, Q> squad( + qua<T, Q> const& q1, + qua<T, Q> const& q2, + qua<T, Q> const& s1, + qua<T, Q> const& s2, + T const& h); + + //! Returns an intermediate control point for squad interpolation. + /// + /// @see gtx_quaternion + template<typename T, qualifier Q> + GLM_FUNC_DECL qua<T, Q> intermediate( + qua<T, Q> const& prev, + qua<T, Q> const& curr, + qua<T, Q> const& next); + + //! Returns quarternion square root. + /// + /// @see gtx_quaternion + //template<typename T, qualifier Q> + //qua<T, Q> sqrt( + // qua<T, Q> const& q); + + //! Rotates a 3 components vector by a quaternion. + /// + /// @see gtx_quaternion + template<typename T, qualifier Q> + GLM_FUNC_DECL vec<3, T, Q> rotate( + qua<T, Q> const& q, + vec<3, T, Q> const& v); + + /// Rotates a 4 components vector by a quaternion. + /// + /// @see gtx_quaternion + template<typename T, qualifier Q> + GLM_FUNC_DECL vec<4, T, Q> rotate( + qua<T, Q> const& q, + vec<4, T, Q> const& v); + + /// Extract the real component of a quaternion. + /// + /// @see gtx_quaternion + template<typename T, qualifier Q> + GLM_FUNC_DECL T extractRealComponent( + qua<T, Q> const& q); + + /// Converts a quaternion to a 3 * 3 matrix. + /// + /// @see gtx_quaternion + template<typename T, qualifier Q> + GLM_FUNC_DECL mat<3, 3, T, Q> toMat3( + qua<T, Q> const& x){return mat3_cast(x);} + + /// Converts a quaternion to a 4 * 4 matrix. + /// + /// @see gtx_quaternion + template<typename T, qualifier Q> + GLM_FUNC_DECL mat<4, 4, T, Q> toMat4( + qua<T, Q> const& x){return mat4_cast(x);} + + /// Converts a 3 * 3 matrix to a quaternion. + /// + /// @see gtx_quaternion + template<typename T, qualifier Q> + GLM_FUNC_DECL qua<T, Q> toQuat( + mat<3, 3, T, Q> const& x){return quat_cast(x);} + + /// Converts a 4 * 4 matrix to a quaternion. + /// + /// @see gtx_quaternion + template<typename T, qualifier Q> + GLM_FUNC_DECL qua<T, Q> toQuat( + mat<4, 4, T, Q> const& x){return quat_cast(x);} + + /// Quaternion interpolation using the rotation short path. + /// + /// @see gtx_quaternion + template<typename T, qualifier Q> + GLM_FUNC_DECL qua<T, Q> shortMix( + qua<T, Q> const& x, + qua<T, Q> const& y, + T const& a); + + /// Quaternion normalized linear interpolation. + /// + /// @see gtx_quaternion + template<typename T, qualifier Q> + GLM_FUNC_DECL qua<T, Q> fastMix( + qua<T, Q> const& x, + qua<T, Q> 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<typename T, qualifier Q> + GLM_FUNC_DECL qua<T, Q> rotation( + vec<3, T, Q> const& orig, + vec<3, T, Q> const& dest); + + /// Returns the squared length of x. + /// + /// @see gtx_quaternion + template<typename T, qualifier Q> + GLM_FUNC_DECL GLM_CONSTEXPR T length2(qua<T, Q> 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 0000000000000000000000000000000000000000..d125bccc9a704a23035cca06fa592857ca91f87c --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/gtx/quaternion.inl @@ -0,0 +1,159 @@ +/// @ref gtx_quaternion + +#include <limits> +#include "../gtc/constants.hpp" + +namespace glm +{ + template<typename T, qualifier Q> + GLM_FUNC_QUALIFIER GLM_CONSTEXPR qua<T, Q> quat_identity() + { + return qua<T, Q>(static_cast<T>(1), static_cast<T>(0), static_cast<T>(0), static_cast<T>(0)); + } + + template<typename T, qualifier Q> + GLM_FUNC_QUALIFIER vec<3, T, Q> cross(vec<3, T, Q> const& v, qua<T, Q> const& q) + { + return inverse(q) * v; + } + + template<typename T, qualifier Q> + GLM_FUNC_QUALIFIER vec<3, T, Q> cross(qua<T, Q> const& q, vec<3, T, Q> const& v) + { + return q * v; + } + + template<typename T, qualifier Q> + GLM_FUNC_QUALIFIER qua<T, Q> squad + ( + qua<T, Q> const& q1, + qua<T, Q> const& q2, + qua<T, Q> const& s1, + qua<T, Q> const& s2, + T const& h) + { + return mix(mix(q1, q2, h), mix(s1, s2, h), static_cast<T>(2) * (static_cast<T>(1) - h) * h); + } + + template<typename T, qualifier Q> + GLM_FUNC_QUALIFIER qua<T, Q> intermediate + ( + qua<T, Q> const& prev, + qua<T, Q> const& curr, + qua<T, Q> const& next + ) + { + qua<T, Q> invQuat = inverse(curr); + return exp((log(next * invQuat) + log(prev * invQuat)) / static_cast<T>(-4)) * curr; + } + + template<typename T, qualifier Q> + GLM_FUNC_QUALIFIER vec<3, T, Q> rotate(qua<T, Q> const& q, vec<3, T, Q> const& v) + { + return q * v; + } + + template<typename T, qualifier Q> + GLM_FUNC_QUALIFIER vec<4, T, Q> rotate(qua<T, Q> const& q, vec<4, T, Q> const& v) + { + return q * v; + } + + template<typename T, qualifier Q> + GLM_FUNC_QUALIFIER T extractRealComponent(qua<T, Q> const& q) + { + T w = static_cast<T>(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<typename T, qualifier Q> + GLM_FUNC_QUALIFIER GLM_CONSTEXPR T length2(qua<T, Q> const& q) + { + return q.x * q.x + q.y * q.y + q.z * q.z + q.w * q.w; + } + + template<typename T, qualifier Q> + GLM_FUNC_QUALIFIER qua<T, Q> shortMix(qua<T, Q> const& x, qua<T, Q> const& y, T const& a) + { + if(a <= static_cast<T>(0)) return x; + if(a >= static_cast<T>(1)) return y; + + T fCos = dot(x, y); + qua<T, Q> y2(y); //BUG!!! qua<T> y2; + if(fCos < static_cast<T>(0)) + { + y2 = -y; + fCos = -fCos; + } + + //if(fCos > 1.0f) // problem + T k0, k1; + if(fCos > (static_cast<T>(1) - epsilon<T>())) + { + k0 = static_cast<T>(1) - a; + k1 = static_cast<T>(0) + a; //BUG!!! 1.0f + a; + } + else + { + T fSin = sqrt(T(1) - fCos * fCos); + T fAngle = atan(fSin, fCos); + T fOneOverSin = static_cast<T>(1) / fSin; + k0 = sin((static_cast<T>(1) - a) * fAngle) * fOneOverSin; + k1 = sin((static_cast<T>(0) + a) * fAngle) * fOneOverSin; + } + + return qua<T, Q>( + 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<typename T, qualifier Q> + GLM_FUNC_QUALIFIER qua<T, Q> fastMix(qua<T, Q> const& x, qua<T, Q> const& y, T const& a) + { + return glm::normalize(x * (static_cast<T>(1) - a) + (y * a)); + } + + template<typename T, qualifier Q> + GLM_FUNC_QUALIFIER qua<T, Q> 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<T>(1) - epsilon<T>()) { + // orig and dest point in the same direction + return quat_identity<T,Q>(); + } + + if(cosTheta < static_cast<T>(-1) + epsilon<T>()) + { + // 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<T>()) // bad luck, they were parallel, try again! + rotationAxis = cross(vec<3, T, Q>(1, 0, 0), orig); + + rotationAxis = normalize(rotationAxis); + return angleAxis(pi<T>(), rotationAxis); + } + + // Implementation from Stan Melax's Game Programming Gems 1 article + rotationAxis = cross(orig, dest); + + T s = sqrt((T(1) + cosTheta) * static_cast<T>(2)); + T invs = static_cast<T>(1) / s; + + return qua<T, Q>( + s * static_cast<T>(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 0000000000000000000000000000000000000000..93bcb9a65a0afc615bec388fe99681b95849ea4f --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/gtx/range.hpp @@ -0,0 +1,98 @@ +/// @ref gtx_range +/// @file glm/gtx/range.hpp +/// @author Joshua Moerman +/// +/// @defgroup gtx_range GLM_GTX_range +/// @ingroup gtx +/// +/// Include <glm/gtx/range.hpp> 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" + +#if GLM_MESSAGES == GLM_ENABLE && !defined(GLM_EXT_INCLUDED) +# ifndef GLM_ENABLE_EXPERIMENTAL +# pragma message("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.") +# else +# pragma message("GLM: GLM_GTX_range extension included") +# endif +#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<typename T, qualifier Q> + inline length_t components(vec<1, T, Q> const& v) + { + return v.length(); + } + + template<typename T, qualifier Q> + inline length_t components(vec<2, T, Q> const& v) + { + return v.length(); + } + + template<typename T, qualifier Q> + inline length_t components(vec<3, T, Q> const& v) + { + return v.length(); + } + + template<typename T, qualifier Q> + inline length_t components(vec<4, T, Q> const& v) + { + return v.length(); + } + + template<typename genType> + inline length_t components(genType const& m) + { + return m.length() * m[0].length(); + } + + template<typename genType> + inline typename genType::value_type const * begin(genType const& v) + { + return value_ptr(v); + } + + template<typename genType> + inline typename genType::value_type const * end(genType const& v) + { + return begin(v) + components(v); + } + + template<typename genType> + inline typename genType::value_type * begin(genType& v) + { + return value_ptr(v); + } + + template<typename genType> + 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 0000000000000000000000000000000000000000..86cbe77d9ae537ca6537a89d14f6ee0bfe50696b --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/gtx/raw_data.hpp @@ -0,0 +1,51 @@ +/// @ref gtx_raw_data +/// @file glm/gtx/raw_data.hpp +/// +/// @see core (dependence) +/// +/// @defgroup gtx_raw_data GLM_GTX_raw_data +/// @ingroup gtx +/// +/// Include <glm/gtx/raw_data.hpp> 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" + +#if GLM_MESSAGES == GLM_ENABLE && !defined(GLM_EXT_INCLUDED) +# ifndef GLM_ENABLE_EXPERIMENTAL +# pragma message("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.") +# else +# pragma message("GLM: GLM_GTX_raw_data extension included") +# endif +#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 0000000000000000000000000000000000000000..c740317d334e7f08181df5ac2522aef7e85bbdb4 --- /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 0000000000000000000000000000000000000000..2103ca08f15ea9576b25bdb0955771ee313d6e79 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/gtx/rotate_normalized_axis.hpp @@ -0,0 +1,68 @@ +/// @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 <glm/gtx/rotate_normalized_axis.hpp> 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" + +#if GLM_MESSAGES == GLM_ENABLE && !defined(GLM_EXT_INCLUDED) +# ifndef GLM_ENABLE_EXPERIMENTAL +# pragma message("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.") +# else +# pragma message("GLM: GLM_GTX_rotate_normalized_axis extension included") +# endif +#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<typename T, qualifier Q> + 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<typename T, qualifier Q> + GLM_FUNC_DECL qua<T, Q> rotateNormalizedAxis( + qua<T, Q> 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 0000000000000000000000000000000000000000..b2e9278c0ae5d18775fbe93919e410a1b963ca06 --- /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<typename T, qualifier Q> + 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<T>(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<typename T, qualifier Q> + GLM_FUNC_QUALIFIER qua<T, Q> rotateNormalizedAxis + ( + qua<T, Q> 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<T, Q>(cos(AngleRad * static_cast<T>(0.5)), Tmp.x * Sin, Tmp.y * Sin, Tmp.z * Sin); + //return gtc::quaternion::cross(q, tquat<T, Q>(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 0000000000000000000000000000000000000000..dcd5b95a6e5b1b484cec1261e4c00e93babba754 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/gtx/rotate_vector.hpp @@ -0,0 +1,123 @@ +/// @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 <glm/gtx/rotate_vector.hpp> 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" + +#if GLM_MESSAGES == GLM_ENABLE && !defined(GLM_EXT_INCLUDED) +# ifndef GLM_ENABLE_EXPERIMENTAL +# pragma message("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.") +# else +# pragma message("GLM: GLM_GTX_rotate_vector extension included") +# endif +#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<typename T, qualifier Q> + 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<typename T, qualifier Q> + 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<typename T, qualifier Q> + 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<typename T, qualifier Q> + 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<typename T, qualifier Q> + 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<typename T, qualifier Q> + 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<typename T, qualifier Q> + 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<typename T, qualifier Q> + 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<typename T, qualifier Q> + 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<typename T, qualifier Q> + 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<typename T, qualifier Q> + 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 0000000000000000000000000000000000000000..f8136e765e0567723bfcfe6b3b13c6334ab4d5c1 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/gtx/rotate_vector.inl @@ -0,0 +1,187 @@ +/// @ref gtx_rotate_vector + +namespace glm +{ + template<typename T, qualifier Q> + 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<T>(1) - a) * Alpha) / SinAlpha; + T t2 = sin(a * Alpha) / SinAlpha; + + // interpolate src vectors + return x * t1 + y * t2; + } + + template<typename T, qualifier Q> + 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<typename T, qualifier Q> + 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<typename T, qualifier Q> + 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<typename T, qualifier Q> + 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<typename T, qualifier Q> + 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<typename T, qualifier Q> + 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<typename T, qualifier Q> + 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<typename T, qualifier Q> + 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<typename T, qualifier Q> + 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<typename T, qualifier Q> + 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<typename T, qualifier Q> + 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<T>()))) + return mat<4, 4, T, Q>(static_cast<T>(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 0000000000000000000000000000000000000000..496ba193f19366c446cea26622e7ff71335e279c --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/gtx/scalar_multiplication.hpp @@ -0,0 +1,75 @@ +/// @ref gtx +/// @file glm/gtx/scalar_multiplication.hpp +/// @author Joshua Moerman +/// +/// Include <glm/gtx/scalar_multiplication.hpp> 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" + +#if GLM_MESSAGES == GLM_ENABLE && !defined(GLM_EXT_INCLUDED) +# ifndef GLM_ENABLE_EXPERIMENTAL +# pragma message("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.") +# else +# pragma message("GLM: GLM_GTX_scalar_multiplication extension included") +# endif +#endif + +#include "../vec2.hpp" +#include "../vec3.hpp" +#include "../vec4.hpp" +#include "../mat2x2.hpp" +#include <type_traits> + +namespace glm +{ + template<typename T, typename Vec> + using return_type_scalar_multiplication = typename std::enable_if< + !std::is_same<T, float>::value // T may not be a float + && std::is_arithmetic<T>::value, Vec // But it may be an int or double (no vec3 or mat3, ...) + >::type; + +#define GLM_IMPLEMENT_SCAL_MULT(Vec) \ + template<typename T> \ + return_type_scalar_multiplication<T, Vec> \ + operator*(T const& s, Vec rh){ \ + return rh *= static_cast<float>(s); \ + } \ + \ + template<typename T> \ + return_type_scalar_multiplication<T, Vec> \ + operator*(Vec lh, T const& s){ \ + return lh *= static_cast<float>(s); \ + } \ + \ + template<typename T> \ + return_type_scalar_multiplication<T, Vec> \ + operator/(Vec lh, T const& s){ \ + return lh *= 1.0f / static_cast<float>(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 0000000000000000000000000000000000000000..8be9c57b8b3501f28e2f35b692d5397c43f3a63a --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/gtx/scalar_relational.hpp @@ -0,0 +1,36 @@ +/// @ref gtx_scalar_relational +/// @file glm/gtx/scalar_relational.hpp +/// +/// @see core (dependence) +/// +/// @defgroup gtx_scalar_relational GLM_GTX_scalar_relational +/// @ingroup gtx +/// +/// Include <glm/gtx/scalar_relational.hpp> 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" + +#if GLM_MESSAGES == GLM_ENABLE && !defined(GLM_EXT_INCLUDED) +# ifndef GLM_ENABLE_EXPERIMENTAL +# pragma message("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.") +# else +# pragma message("GLM: GLM_GTX_extend extension included") +# endif +#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 0000000000000000000000000000000000000000..c2a121cff9771266eb1de59182a1dc962f9a5e54 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/gtx/scalar_relational.inl @@ -0,0 +1,88 @@ +/// @ref gtx_scalar_relational + +namespace glm +{ + template<typename T> + GLM_FUNC_QUALIFIER bool lessThan + ( + T const& x, + T const& y + ) + { + return x < y; + } + + template<typename T> + GLM_FUNC_QUALIFIER bool lessThanEqual + ( + T const& x, + T const& y + ) + { + return x <= y; + } + + template<typename T> + GLM_FUNC_QUALIFIER bool greaterThan + ( + T const& x, + T const& y + ) + { + return x > y; + } + + template<typename T> + GLM_FUNC_QUALIFIER bool greaterThanEqual + ( + T const& x, + T const& y + ) + { + return x >= y; + } + + template<typename T> + GLM_FUNC_QUALIFIER bool equal + ( + T const& x, + T const& y + ) + { + return detail::compute_equal<T, std::numeric_limits<T>::is_iec559>::call(x, y); + } + + template<typename T> + GLM_FUNC_QUALIFIER bool notEqual + ( + T const& x, + T const& y + ) + { + return !detail::compute_equal<T, std::numeric_limits<T>::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 0000000000000000000000000000000000000000..731c979e358a8f2967ab5b71da57bf68abefa94d --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/gtx/spline.hpp @@ -0,0 +1,65 @@ +/// @ref gtx_spline +/// @file glm/gtx/spline.hpp +/// +/// @see core (dependence) +/// +/// @defgroup gtx_spline GLM_GTX_spline +/// @ingroup gtx +/// +/// Include <glm/gtx/spline.hpp> to use the features of this extension. +/// +/// Spline functions + +#pragma once + +// Dependency: +#include "../glm.hpp" +#include "../gtx/optimum_pow.hpp" + +#if GLM_MESSAGES == GLM_ENABLE && !defined(GLM_EXT_INCLUDED) +# ifndef GLM_ENABLE_EXPERIMENTAL +# pragma message("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.") +# else +# pragma message("GLM: GLM_GTX_spline extension included") +# endif +#endif + +namespace glm +{ + /// @addtogroup gtx_spline + /// @{ + + /// Return a point from a catmull rom curve. + /// @see gtx_spline extension. + template<typename genType> + 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<typename genType> + 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<typename genType> + 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 0000000000000000000000000000000000000000..c3fd0565629139357a81ffdcae55f8e89b4831dd --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/gtx/spline.inl @@ -0,0 +1,60 @@ +/// @ref gtx_spline + +namespace glm +{ + template<typename genType> + 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<typename genType> + 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<typename genType> + 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 0000000000000000000000000000000000000000..cd3be8cb78926ab1f9620e848c30a43aa4198185 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/gtx/std_based_type.hpp @@ -0,0 +1,68 @@ +/// @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 <glm/gtx/std_based_type.hpp> to use the features of this extension. +/// +/// Adds vector types based on STL value types. + +#pragma once + +// Dependency: +#include "../glm.hpp" +#include <cstdlib> + +#if GLM_MESSAGES == GLM_ENABLE && !defined(GLM_EXT_INCLUDED) +# ifndef GLM_ENABLE_EXPERIMENTAL +# pragma message("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.") +# else +# pragma message("GLM: GLM_GTX_std_based_type extension included") +# endif +#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 0000000000000000000000000000000000000000..9c34bdb6e0f7348895bd59a256588731bb759da5 --- /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 0000000000000000000000000000000000000000..27846bf89f077a2c4000cdd58ca955ed0b86539d --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/gtx/string_cast.hpp @@ -0,0 +1,52 @@ +/// @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 <glm/gtx/string_cast.hpp> to use the features of this extension. +/// +/// Setup strings for GLM type values +/// +/// This extension is not supported with CUDA + +#pragma once + +// Dependency: +#include "../glm.hpp" +#include "../gtc/type_precision.hpp" +#include "../gtc/quaternion.hpp" +#include "../gtx/dual_quaternion.hpp" +#include <string> +#include <cmath> + +#if GLM_MESSAGES == GLM_ENABLE && !defined(GLM_EXT_INCLUDED) +# ifndef GLM_ENABLE_EXPERIMENTAL +# pragma message("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.") +# else +# pragma message("GLM: GLM_GTX_string_cast extension included") +# endif +#endif + +#if(GLM_COMPILER & GLM_COMPILER_CUDA) +# error "GLM_GTX_string_cast is not supported on CUDA compiler" +#endif + +namespace glm +{ + /// @addtogroup gtx_string_cast + /// @{ + + /// Create a string from a GLM vector or matrix typed variable. + /// @see gtx_string_cast extension. + template<typename genType> + 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 0000000000000000000000000000000000000000..f67751d41c2af4128d44bf73c055147d3b1c156d --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/gtx/string_cast.inl @@ -0,0 +1,492 @@ +/// @ref gtx_string_cast + +#include <cstdarg> +#include <cstdio> + +namespace glm{ +namespace detail +{ + template <typename T> + struct cast + { + typedef T value_type; + }; + + template <> + struct cast<float> + { + typedef double value_type; + }; + + GLM_FUNC_QUALIFIER std::string format(const char* msg, ...) + { + std::size_t const STRING_BUFFER(4096); + char text[STRING_BUFFER]; + va_list list; + + if(msg == GLM_NULLPTR) + return std::string(); + + va_start(list, msg); +# if (GLM_COMPILER & GLM_COMPILER_VC) + vsprintf_s(text, STRING_BUFFER, msg, list); +# else// + std::vsprintf(text, msg, list); +# endif// + va_end(list); + + return std::string(text); + } + + static const char* LabelTrue = "true"; + static const char* LabelFalse = "false"; + + template<typename T, bool isFloat = false> + struct literal + { + GLM_FUNC_QUALIFIER static char const * value() {return "%d";} + }; + + template<typename T> + struct literal<T, true> + { + GLM_FUNC_QUALIFIER static char const * value() {return "%f";} + }; + +# if GLM_MODEL == GLM_MODEL_32 && GLM_COMPILER && GLM_COMPILER_VC + template<> + struct literal<uint64_t, false> + { + GLM_FUNC_QUALIFIER static char const * value() {return "%lld";} + }; + + template<> + struct literal<int64_t, false> + { + GLM_FUNC_QUALIFIER static char const * value() {return "%lld";} + }; +# endif//GLM_MODEL == GLM_MODEL_32 && GLM_COMPILER && GLM_COMPILER_VC + + template<typename T> + struct prefix{}; + + template<> + struct prefix<float> + { + GLM_FUNC_QUALIFIER static char const * value() {return "";} + }; + + template<> + struct prefix<double> + { + GLM_FUNC_QUALIFIER static char const * value() {return "d";} + }; + + template<> + struct prefix<bool> + { + GLM_FUNC_QUALIFIER static char const * value() {return "b";} + }; + + template<> + struct prefix<uint8_t> + { + GLM_FUNC_QUALIFIER static char const * value() {return "u8";} + }; + + template<> + struct prefix<int8_t> + { + GLM_FUNC_QUALIFIER static char const * value() {return "i8";} + }; + + template<> + struct prefix<uint16_t> + { + GLM_FUNC_QUALIFIER static char const * value() {return "u16";} + }; + + template<> + struct prefix<int16_t> + { + GLM_FUNC_QUALIFIER static char const * value() {return "i16";} + }; + + template<> + struct prefix<uint32_t> + { + GLM_FUNC_QUALIFIER static char const * value() {return "u";} + }; + + template<> + struct prefix<int32_t> + { + GLM_FUNC_QUALIFIER static char const * value() {return "i";} + }; + + template<> + struct prefix<uint64_t> + { + GLM_FUNC_QUALIFIER static char const * value() {return "u64";} + }; + + template<> + struct prefix<int64_t> + { + GLM_FUNC_QUALIFIER static char const * value() {return "i64";} + }; + + template<typename matType> + struct compute_to_string + {}; + + template<qualifier Q> + struct compute_to_string<vec<1, bool, Q> > + { + 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<qualifier Q> + struct compute_to_string<vec<2, bool, Q> > + { + 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<qualifier Q> + struct compute_to_string<vec<3, bool, Q> > + { + 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<qualifier Q> + struct compute_to_string<vec<4, bool, Q> > + { + 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<typename T, qualifier Q> + struct compute_to_string<vec<1, T, Q> > + { + GLM_FUNC_QUALIFIER static std::string call(vec<1, T, Q> const& x) + { + char const * PrefixStr = prefix<T>::value(); + char const * LiteralStr = literal<T, std::numeric_limits<T>::is_iec559>::value(); + std::string FormatStr(detail::format("%svec1(%s)", + PrefixStr, + LiteralStr)); + + return detail::format(FormatStr.c_str(), + static_cast<typename cast<T>::value_type>(x[0])); + } + }; + + template<typename T, qualifier Q> + struct compute_to_string<vec<2, T, Q> > + { + GLM_FUNC_QUALIFIER static std::string call(vec<2, T, Q> const& x) + { + char const * PrefixStr = prefix<T>::value(); + char const * LiteralStr = literal<T, std::numeric_limits<T>::is_iec559>::value(); + std::string FormatStr(detail::format("%svec2(%s, %s)", + PrefixStr, + LiteralStr, LiteralStr)); + + return detail::format(FormatStr.c_str(), + static_cast<typename cast<T>::value_type>(x[0]), + static_cast<typename cast<T>::value_type>(x[1])); + } + }; + + template<typename T, qualifier Q> + struct compute_to_string<vec<3, T, Q> > + { + GLM_FUNC_QUALIFIER static std::string call(vec<3, T, Q> const& x) + { + char const * PrefixStr = prefix<T>::value(); + char const * LiteralStr = literal<T, std::numeric_limits<T>::is_iec559>::value(); + std::string FormatStr(detail::format("%svec3(%s, %s, %s)", + PrefixStr, + LiteralStr, LiteralStr, LiteralStr)); + + return detail::format(FormatStr.c_str(), + static_cast<typename cast<T>::value_type>(x[0]), + static_cast<typename cast<T>::value_type>(x[1]), + static_cast<typename cast<T>::value_type>(x[2])); + } + }; + + template<typename T, qualifier Q> + struct compute_to_string<vec<4, T, Q> > + { + GLM_FUNC_QUALIFIER static std::string call(vec<4, T, Q> const& x) + { + char const * PrefixStr = prefix<T>::value(); + char const * LiteralStr = literal<T, std::numeric_limits<T>::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<typename cast<T>::value_type>(x[0]), + static_cast<typename cast<T>::value_type>(x[1]), + static_cast<typename cast<T>::value_type>(x[2]), + static_cast<typename cast<T>::value_type>(x[3])); + } + }; + + + template<typename T, qualifier Q> + struct compute_to_string<mat<2, 2, T, Q> > + { + GLM_FUNC_QUALIFIER static std::string call(mat<2, 2, T, Q> const& x) + { + char const * PrefixStr = prefix<T>::value(); + char const * LiteralStr = literal<T, std::numeric_limits<T>::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<typename cast<T>::value_type>(x[0][0]), static_cast<typename cast<T>::value_type>(x[0][1]), + static_cast<typename cast<T>::value_type>(x[1][0]), static_cast<typename cast<T>::value_type>(x[1][1])); + } + }; + + template<typename T, qualifier Q> + struct compute_to_string<mat<2, 3, T, Q> > + { + GLM_FUNC_QUALIFIER static std::string call(mat<2, 3, T, Q> const& x) + { + char const * PrefixStr = prefix<T>::value(); + char const * LiteralStr = literal<T, std::numeric_limits<T>::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<typename cast<T>::value_type>(x[0][0]), static_cast<typename cast<T>::value_type>(x[0][1]), static_cast<typename cast<T>::value_type>(x[0][2]), + static_cast<typename cast<T>::value_type>(x[1][0]), static_cast<typename cast<T>::value_type>(x[1][1]), static_cast<typename cast<T>::value_type>(x[1][2])); + } + }; + + template<typename T, qualifier Q> + struct compute_to_string<mat<2, 4, T, Q> > + { + GLM_FUNC_QUALIFIER static std::string call(mat<2, 4, T, Q> const& x) + { + char const * PrefixStr = prefix<T>::value(); + char const * LiteralStr = literal<T, std::numeric_limits<T>::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<typename cast<T>::value_type>(x[0][0]), static_cast<typename cast<T>::value_type>(x[0][1]), static_cast<typename cast<T>::value_type>(x[0][2]), static_cast<typename cast<T>::value_type>(x[0][3]), + static_cast<typename cast<T>::value_type>(x[1][0]), static_cast<typename cast<T>::value_type>(x[1][1]), static_cast<typename cast<T>::value_type>(x[1][2]), static_cast<typename cast<T>::value_type>(x[1][3])); + } + }; + + template<typename T, qualifier Q> + struct compute_to_string<mat<3, 2, T, Q> > + { + GLM_FUNC_QUALIFIER static std::string call(mat<3, 2, T, Q> const& x) + { + char const * PrefixStr = prefix<T>::value(); + char const * LiteralStr = literal<T, std::numeric_limits<T>::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<typename cast<T>::value_type>(x[0][0]), static_cast<typename cast<T>::value_type>(x[0][1]), + static_cast<typename cast<T>::value_type>(x[1][0]), static_cast<typename cast<T>::value_type>(x[1][1]), + static_cast<typename cast<T>::value_type>(x[2][0]), static_cast<typename cast<T>::value_type>(x[2][1])); + } + }; + + template<typename T, qualifier Q> + struct compute_to_string<mat<3, 3, T, Q> > + { + GLM_FUNC_QUALIFIER static std::string call(mat<3, 3, T, Q> const& x) + { + char const * PrefixStr = prefix<T>::value(); + char const * LiteralStr = literal<T, std::numeric_limits<T>::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<typename cast<T>::value_type>(x[0][0]), static_cast<typename cast<T>::value_type>(x[0][1]), static_cast<typename cast<T>::value_type>(x[0][2]), + static_cast<typename cast<T>::value_type>(x[1][0]), static_cast<typename cast<T>::value_type>(x[1][1]), static_cast<typename cast<T>::value_type>(x[1][2]), + static_cast<typename cast<T>::value_type>(x[2][0]), static_cast<typename cast<T>::value_type>(x[2][1]), static_cast<typename cast<T>::value_type>(x[2][2])); + } + }; + + template<typename T, qualifier Q> + struct compute_to_string<mat<3, 4, T, Q> > + { + GLM_FUNC_QUALIFIER static std::string call(mat<3, 4, T, Q> const& x) + { + char const * PrefixStr = prefix<T>::value(); + char const * LiteralStr = literal<T, std::numeric_limits<T>::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<typename cast<T>::value_type>(x[0][0]), static_cast<typename cast<T>::value_type>(x[0][1]), static_cast<typename cast<T>::value_type>(x[0][2]), static_cast<typename cast<T>::value_type>(x[0][3]), + static_cast<typename cast<T>::value_type>(x[1][0]), static_cast<typename cast<T>::value_type>(x[1][1]), static_cast<typename cast<T>::value_type>(x[1][2]), static_cast<typename cast<T>::value_type>(x[1][3]), + static_cast<typename cast<T>::value_type>(x[2][0]), static_cast<typename cast<T>::value_type>(x[2][1]), static_cast<typename cast<T>::value_type>(x[2][2]), static_cast<typename cast<T>::value_type>(x[2][3])); + } + }; + + template<typename T, qualifier Q> + struct compute_to_string<mat<4, 2, T, Q> > + { + GLM_FUNC_QUALIFIER static std::string call(mat<4, 2, T, Q> const& x) + { + char const * PrefixStr = prefix<T>::value(); + char const * LiteralStr = literal<T, std::numeric_limits<T>::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<typename cast<T>::value_type>(x[0][0]), static_cast<typename cast<T>::value_type>(x[0][1]), + static_cast<typename cast<T>::value_type>(x[1][0]), static_cast<typename cast<T>::value_type>(x[1][1]), + static_cast<typename cast<T>::value_type>(x[2][0]), static_cast<typename cast<T>::value_type>(x[2][1]), + static_cast<typename cast<T>::value_type>(x[3][0]), static_cast<typename cast<T>::value_type>(x[3][1])); + } + }; + + template<typename T, qualifier Q> + struct compute_to_string<mat<4, 3, T, Q> > + { + GLM_FUNC_QUALIFIER static std::string call(mat<4, 3, T, Q> const& x) + { + char const * PrefixStr = prefix<T>::value(); + char const * LiteralStr = literal<T, std::numeric_limits<T>::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<typename cast<T>::value_type>(x[0][0]), static_cast<typename cast<T>::value_type>(x[0][1]), static_cast<typename cast<T>::value_type>(x[0][2]), + static_cast<typename cast<T>::value_type>(x[1][0]), static_cast<typename cast<T>::value_type>(x[1][1]), static_cast<typename cast<T>::value_type>(x[1][2]), + static_cast<typename cast<T>::value_type>(x[2][0]), static_cast<typename cast<T>::value_type>(x[2][1]), static_cast<typename cast<T>::value_type>(x[2][2]), + static_cast<typename cast<T>::value_type>(x[3][0]), static_cast<typename cast<T>::value_type>(x[3][1]), static_cast<typename cast<T>::value_type>(x[3][2])); + } + }; + + template<typename T, qualifier Q> + struct compute_to_string<mat<4, 4, T, Q> > + { + GLM_FUNC_QUALIFIER static std::string call(mat<4, 4, T, Q> const& x) + { + char const * PrefixStr = prefix<T>::value(); + char const * LiteralStr = literal<T, std::numeric_limits<T>::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<typename cast<T>::value_type>(x[0][0]), static_cast<typename cast<T>::value_type>(x[0][1]), static_cast<typename cast<T>::value_type>(x[0][2]), static_cast<typename cast<T>::value_type>(x[0][3]), + static_cast<typename cast<T>::value_type>(x[1][0]), static_cast<typename cast<T>::value_type>(x[1][1]), static_cast<typename cast<T>::value_type>(x[1][2]), static_cast<typename cast<T>::value_type>(x[1][3]), + static_cast<typename cast<T>::value_type>(x[2][0]), static_cast<typename cast<T>::value_type>(x[2][1]), static_cast<typename cast<T>::value_type>(x[2][2]), static_cast<typename cast<T>::value_type>(x[2][3]), + static_cast<typename cast<T>::value_type>(x[3][0]), static_cast<typename cast<T>::value_type>(x[3][1]), static_cast<typename cast<T>::value_type>(x[3][2]), static_cast<typename cast<T>::value_type>(x[3][3])); + } + }; + + + template<typename T, qualifier Q> + struct compute_to_string<qua<T, Q> > + { + GLM_FUNC_QUALIFIER static std::string call(qua<T, Q> const& q) + { + char const * PrefixStr = prefix<T>::value(); + char const * LiteralStr = literal<T, std::numeric_limits<T>::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<typename cast<T>::value_type>(q.w), + static_cast<typename cast<T>::value_type>(q.x), + static_cast<typename cast<T>::value_type>(q.y), + static_cast<typename cast<T>::value_type>(q.z)); + } + }; + + template<typename T, qualifier Q> + struct compute_to_string<tdualquat<T, Q> > + { + GLM_FUNC_QUALIFIER static std::string call(tdualquat<T, Q> const& x) + { + char const * PrefixStr = prefix<T>::value(); + char const * LiteralStr = literal<T, std::numeric_limits<T>::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<typename cast<T>::value_type>(x.real.w), + static_cast<typename cast<T>::value_type>(x.real.x), + static_cast<typename cast<T>::value_type>(x.real.y), + static_cast<typename cast<T>::value_type>(x.real.z), + static_cast<typename cast<T>::value_type>(x.dual.w), + static_cast<typename cast<T>::value_type>(x.dual.x), + static_cast<typename cast<T>::value_type>(x.dual.y), + static_cast<typename cast<T>::value_type>(x.dual.z)); + } + }; + +}//namespace detail + +template<class matType> +GLM_FUNC_QUALIFIER std::string to_string(matType const& x) +{ + return detail::compute_to_string<matType>::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 0000000000000000000000000000000000000000..20585e68ce11419c27f637290beaede9b56c6cf4 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/gtx/texture.hpp @@ -0,0 +1,46 @@ +/// @ref gtx_texture +/// @file glm/gtx/texture.hpp +/// +/// @see core (dependence) +/// +/// @defgroup gtx_texture GLM_GTX_texture +/// @ingroup gtx +/// +/// Include <glm/gtx/texture.hpp> 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" + +#if GLM_MESSAGES == GLM_ENABLE && !defined(GLM_EXT_INCLUDED) +# ifndef GLM_ENABLE_EXPERIMENTAL +# pragma message("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.") +# else +# pragma message("GLM: GLM_GTX_texture extension included") +# endif +#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 <length_t L, typename T, qualifier Q> + T levels(vec<L, T, Q> 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 0000000000000000000000000000000000000000..593c826141b0e0c35b513bfbac623e9a6ecb3168 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/gtx/texture.inl @@ -0,0 +1,17 @@ +/// @ref gtx_texture + +namespace glm +{ + template <length_t L, typename T, qualifier Q> + inline T levels(vec<L, T, Q> const& Extent) + { + return glm::log2(compMax(Extent)) + static_cast<T>(1); + } + + template <typename T> + 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 0000000000000000000000000000000000000000..0279fc8bd329d592288a90256ce1ff7d3c711e45 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/gtx/transform.hpp @@ -0,0 +1,60 @@ +/// @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 <glm/gtx/transform.hpp> to use the features of this extension. +/// +/// Add transformation matrices + +#pragma once + +// Dependency: +#include "../glm.hpp" +#include "../gtc/matrix_transform.hpp" + +#if GLM_MESSAGES == GLM_ENABLE && !defined(GLM_EXT_INCLUDED) +# ifndef GLM_ENABLE_EXPERIMENTAL +# pragma message("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.") +# else +# pragma message("GLM: GLM_GTX_transform extension included") +# endif +#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<typename T, qualifier Q> + 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<typename T, qualifier Q> + 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<typename T, qualifier Q> + 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 0000000000000000000000000000000000000000..48ee6801b6515266b1cfd9f389258ea5b200c5d1 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/gtx/transform.inl @@ -0,0 +1,23 @@ +/// @ref gtx_transform + +namespace glm +{ + template<typename T, qualifier Q> + GLM_FUNC_QUALIFIER mat<4, 4, T, Q> translate(vec<3, T, Q> const& v) + { + return translate(mat<4, 4, T, Q>(static_cast<T>(1)), v); + } + + template<typename T, qualifier Q> + 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<T>(1)), angle, v); + } + + template<typename T, qualifier Q> + GLM_FUNC_QUALIFIER mat<4, 4, T, Q> scale(vec<3, T, Q> const& v) + { + return scale(mat<4, 4, T, Q>(static_cast<T>(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 0000000000000000000000000000000000000000..0d8ba9d90bc51a7b094c87ca3fed3a61601c6138 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/gtx/transform2.hpp @@ -0,0 +1,89 @@ +/// @ref gtx_transform2 +/// @file glm/gtx/transform2.hpp +/// +/// @see core (dependence) +/// @see gtx_transform (dependence) +/// +/// @defgroup gtx_transform2 GLM_GTX_transform2 +/// @ingroup gtx +/// +/// Include <glm/gtx/transform2.hpp> to use the features of this extension. +/// +/// Add extra transformation matrices + +#pragma once + +// Dependency: +#include "../glm.hpp" +#include "../gtx/transform.hpp" + +#if GLM_MESSAGES == GLM_ENABLE && !defined(GLM_EXT_INCLUDED) +# ifndef GLM_ENABLE_EXPERIMENTAL +# pragma message("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.") +# else +# pragma message("GLM: GLM_GTX_transform2 extension included") +# endif +#endif + +namespace glm +{ + /// @addtogroup gtx_transform2 + /// @{ + + //! Transforms a matrix with a shearing on X axis. + //! From GLM_GTX_transform2 extension. + template<typename T, qualifier Q> + 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<typename T, qualifier Q> + 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<typename T, qualifier Q> + 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<typename T, qualifier Q> + 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<typename T, qualifier Q> + GLM_FUNC_DECL mat<4, 4, T, Q> shearZ3D(mat<4, 4, T, Q> const& m, T x, T y); + + //template<typename T> 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<typename T> 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<typename T> 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<typename T, qualifier Q> + 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<typename T, qualifier Q> + 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<typename T, qualifier Q> + GLM_FUNC_DECL mat<4, 4, T, Q> scaleBias(T scale, T bias); + + //! Build a scale bias matrix. + //! From GLM_GTX_transform2 extension. + template<typename T, qualifier Q> + 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 0000000000000000000000000000000000000000..2b53198b3302ed45c14b7ff01a7314380663283b --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/gtx/transform2.inl @@ -0,0 +1,125 @@ +/// @ref gtx_transform2 + +namespace glm +{ + template<typename T, qualifier Q> + 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<typename T, qualifier Q> + 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<typename T, qualifier Q> + 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<typename T, qualifier Q> + 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<typename T, qualifier Q> + 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<typename T, qualifier Q> + 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<T>(1)); + r[0][0] = static_cast<T>(1) - static_cast<T>(2) * normal.x * normal.x; + r[0][1] = -static_cast<T>(2) * normal.x * normal.y; + r[1][0] = -static_cast<T>(2) * normal.x * normal.y; + r[1][1] = static_cast<T>(1) - static_cast<T>(2) * normal.y * normal.y; + return m * r; + } + + template<typename T, qualifier Q> + 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<T>(1)); + r[0][0] = static_cast<T>(1) - static_cast<T>(2) * normal.x * normal.x; + r[0][1] = -static_cast<T>(2) * normal.x * normal.y; + r[0][2] = -static_cast<T>(2) * normal.x * normal.z; + + r[1][0] = -static_cast<T>(2) * normal.x * normal.y; + r[1][1] = static_cast<T>(1) - static_cast<T>(2) * normal.y * normal.y; + r[1][2] = -static_cast<T>(2) * normal.y * normal.z; + + r[2][0] = -static_cast<T>(2) * normal.x * normal.z; + r[2][1] = -static_cast<T>(2) * normal.y * normal.z; + r[2][2] = static_cast<T>(1) - static_cast<T>(2) * normal.z * normal.z; + return m * r; + } + + template<typename T, qualifier Q> + 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<T>(1)); + r[0][0] = static_cast<T>(1) - normal.x * normal.x; + r[0][1] = - normal.x * normal.y; + r[1][0] = - normal.x * normal.y; + r[1][1] = static_cast<T>(1) - normal.y * normal.y; + return m * r; + } + + template<typename T, qualifier Q> + 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<T>(1)); + r[0][0] = static_cast<T>(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<T>(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<T>(1) - normal.z * normal.z; + return m * r; + } + + template<typename T, qualifier Q> + 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<T>(1)); + result[0][0] = scale; + result[1][1] = scale; + result[2][2] = scale; + return result; + } + + template<typename T, qualifier Q> + 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 0000000000000000000000000000000000000000..2ae522c1fc7e383c8b1d2a903210acd0196c10fc --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/gtx/type_aligned.hpp @@ -0,0 +1,982 @@ +/// @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 <glm/gtx/type_aligned.hpp> to use the features of this extension. +/// +/// Defines aligned types. + +#pragma once + +// Dependency: +#include "../gtc/type_precision.hpp" +#include "../gtc/quaternion.hpp" + +#if GLM_MESSAGES == GLM_ENABLE && !defined(GLM_EXT_INCLUDED) +# 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.") +# else +# pragma message("GLM: GLM_GTX_type_aligned extension included") +# endif +#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<f32> 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<f32> 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<f32> 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<f32, defaultp> 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<f64, defaultp> 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 0000000000000000000000000000000000000000..54c1b818b64af8a03a2ce5c93853a7fce5093ea1 --- /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 0000000000000000000000000000000000000000..56685c8cb98c1861d9bbc59393b888f62c18f403 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/gtx/type_trait.hpp @@ -0,0 +1,85 @@ +/// @ref gtx_type_trait +/// @file glm/gtx/type_trait.hpp +/// +/// @see core (dependence) +/// +/// @defgroup gtx_type_trait GLM_GTX_type_trait +/// @ingroup gtx +/// +/// Include <glm/gtx/type_trait.hpp> to use the features of this extension. +/// +/// Defines traits for each type. + +#pragma once + +#if GLM_MESSAGES == GLM_ENABLE && !defined(GLM_EXT_INCLUDED) +# ifndef GLM_ENABLE_EXPERIMENTAL +# pragma message("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.") +# else +# pragma message("GLM: GLM_GTX_type_trait extension included") +# endif +#endif + +// Dependency: +#include "../detail/qualifier.hpp" +#include "../gtc/quaternion.hpp" +#include "../gtx/dual_quaternion.hpp" + +namespace glm +{ + /// @addtogroup gtx_type_trait + /// @{ + + template<typename T> + 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<length_t L, typename T, qualifier Q> + struct type<vec<L, T, Q> > + { + 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<length_t C, length_t R, typename T, qualifier Q> + struct type<mat<C, R, T, Q> > + { + 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<typename T, qualifier Q> + struct type<qua<T, Q> > + { + 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<typename T, qualifier Q> + struct type<tdualquat<T, Q> > + { + 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 0000000000000000000000000000000000000000..045de959cc21dcb60ba5e96424419e9b57824435 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/gtx/type_trait.inl @@ -0,0 +1,61 @@ +/// @ref gtx_type_trait + +namespace glm +{ + template<typename T> + bool const type<T>::is_vec; + template<typename T> + bool const type<T>::is_mat; + template<typename T> + bool const type<T>::is_quat; + template<typename T> + length_t const type<T>::components; + template<typename T> + length_t const type<T>::cols; + template<typename T> + length_t const type<T>::rows; + + // vec + template<length_t L, typename T, qualifier Q> + bool const type<vec<L, T, Q> >::is_vec; + template<length_t L, typename T, qualifier Q> + bool const type<vec<L, T, Q> >::is_mat; + template<length_t L, typename T, qualifier Q> + bool const type<vec<L, T, Q> >::is_quat; + template<length_t L, typename T, qualifier Q> + length_t const type<vec<L, T, Q> >::components; + + // mat + template<length_t C, length_t R, typename T, qualifier Q> + bool const type<mat<C, R, T, Q> >::is_vec; + template<length_t C, length_t R, typename T, qualifier Q> + bool const type<mat<C, R, T, Q> >::is_mat; + template<length_t C, length_t R, typename T, qualifier Q> + bool const type<mat<C, R, T, Q> >::is_quat; + template<length_t C, length_t R, typename T, qualifier Q> + length_t const type<mat<C, R, T, Q> >::components; + template<length_t C, length_t R, typename T, qualifier Q> + length_t const type<mat<C, R, T, Q> >::cols; + template<length_t C, length_t R, typename T, qualifier Q> + length_t const type<mat<C, R, T, Q> >::rows; + + // tquat + template<typename T, qualifier Q> + bool const type<qua<T, Q> >::is_vec; + template<typename T, qualifier Q> + bool const type<qua<T, Q> >::is_mat; + template<typename T, qualifier Q> + bool const type<qua<T, Q> >::is_quat; + template<typename T, qualifier Q> + length_t const type<qua<T, Q> >::components; + + // tdualquat + template<typename T, qualifier Q> + bool const type<tdualquat<T, Q> >::is_vec; + template<typename T, qualifier Q> + bool const type<tdualquat<T, Q> >::is_mat; + template<typename T, qualifier Q> + bool const type<tdualquat<T, Q> >::is_quat; + template<typename T, qualifier Q> + length_t const type<tdualquat<T, Q> >::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 0000000000000000000000000000000000000000..1c49abcb6ad7adcac1285d3e2c2577fb83e27e72 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/gtx/vec_swizzle.hpp @@ -0,0 +1,2782 @@ +/// @ref gtx_vec_swizzle +/// @file glm/gtx/vec_swizzle.hpp +/// +/// @see core (dependence) +/// +/// @defgroup gtx_vec_swizzle GLM_GTX_vec_swizzle +/// @ingroup gtx +/// +/// Include <glm/gtx/vec_swizzle.hpp> to use the features of this extension. +/// +/// Functions to perform swizzle operation. + +#pragma once + +#include "../glm.hpp" + +#if GLM_MESSAGES == GLM_ENABLE && !defined(GLM_EXT_INCLUDED) +# ifndef GLM_ENABLE_EXPERIMENTAL +# pragma message("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.") +# else +# pragma message("GLM: GLM_GTX_vec_swizzle extension included") +# endif +#endif + +namespace glm { + // xx + template<typename T, qualifier Q> + GLM_INLINE glm::vec<2, T, Q> xx(const glm::vec<1, T, Q> &v) { + return glm::vec<2, T, Q>(v.x, v.x); + } + + template<typename T, qualifier Q> + GLM_INLINE glm::vec<2, T, Q> xx(const glm::vec<2, T, Q> &v) { + return glm::vec<2, T, Q>(v.x, v.x); + } + + template<typename T, qualifier Q> + GLM_INLINE glm::vec<2, T, Q> xx(const glm::vec<3, T, Q> &v) { + return glm::vec<2, T, Q>(v.x, v.x); + } + + template<typename T, qualifier Q> + GLM_INLINE 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<typename T, qualifier Q> + GLM_INLINE glm::vec<2, T, Q> xy(const glm::vec<2, T, Q> &v) { + return glm::vec<2, T, Q>(v.x, v.y); + } + + template<typename T, qualifier Q> + GLM_INLINE glm::vec<2, T, Q> xy(const glm::vec<3, T, Q> &v) { + return glm::vec<2, T, Q>(v.x, v.y); + } + + template<typename T, qualifier Q> + GLM_INLINE 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<typename T, qualifier Q> + GLM_INLINE glm::vec<2, T, Q> xz(const glm::vec<3, T, Q> &v) { + return glm::vec<2, T, Q>(v.x, v.z); + } + + template<typename T, qualifier Q> + GLM_INLINE 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<typename T, qualifier Q> + GLM_INLINE 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<typename T, qualifier Q> + GLM_INLINE glm::vec<2, T, Q> yx(const glm::vec<2, T, Q> &v) { + return glm::vec<2, T, Q>(v.y, v.x); + } + + template<typename T, qualifier Q> + GLM_INLINE glm::vec<2, T, Q> yx(const glm::vec<3, T, Q> &v) { + return glm::vec<2, T, Q>(v.y, v.x); + } + + template<typename T, qualifier Q> + GLM_INLINE 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<typename T, qualifier Q> + GLM_INLINE glm::vec<2, T, Q> yy(const glm::vec<2, T, Q> &v) { + return glm::vec<2, T, Q>(v.y, v.y); + } + + template<typename T, qualifier Q> + GLM_INLINE glm::vec<2, T, Q> yy(const glm::vec<3, T, Q> &v) { + return glm::vec<2, T, Q>(v.y, v.y); + } + + template<typename T, qualifier Q> + GLM_INLINE 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<typename T, qualifier Q> + GLM_INLINE glm::vec<2, T, Q> yz(const glm::vec<3, T, Q> &v) { + return glm::vec<2, T, Q>(v.y, v.z); + } + + template<typename T, qualifier Q> + GLM_INLINE 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<typename T, qualifier Q> + GLM_INLINE 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<typename T, qualifier Q> + GLM_INLINE glm::vec<2, T, Q> zx(const glm::vec<3, T, Q> &v) { + return glm::vec<2, T, Q>(v.z, v.x); + } + + template<typename T, qualifier Q> + GLM_INLINE 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<typename T, qualifier Q> + GLM_INLINE glm::vec<2, T, Q> zy(const glm::vec<3, T, Q> &v) { + return glm::vec<2, T, Q>(v.z, v.y); + } + + template<typename T, qualifier Q> + GLM_INLINE 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<typename T, qualifier Q> + GLM_INLINE glm::vec<2, T, Q> zz(const glm::vec<3, T, Q> &v) { + return glm::vec<2, T, Q>(v.z, v.z); + } + + template<typename T, qualifier Q> + GLM_INLINE 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<typename T, qualifier Q> + GLM_INLINE 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<typename T, qualifier Q> + GLM_INLINE 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<typename T, qualifier Q> + GLM_INLINE 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<typename T, qualifier Q> + GLM_INLINE 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<typename T, qualifier Q> + GLM_INLINE 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<typename T, qualifier Q> + GLM_INLINE 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<typename T, qualifier Q> + GLM_INLINE 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<typename T, qualifier Q> + GLM_INLINE 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<typename T, qualifier Q> + GLM_INLINE 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<typename T, qualifier Q> + GLM_INLINE 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<typename T, qualifier Q> + GLM_INLINE 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<typename T, qualifier Q> + GLM_INLINE 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<typename T, qualifier Q> + GLM_INLINE 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<typename T, qualifier Q> + GLM_INLINE 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<typename T, qualifier Q> + GLM_INLINE 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<typename T, qualifier Q> + GLM_INLINE 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<typename T, qualifier Q> + GLM_INLINE 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<typename T, qualifier Q> + GLM_INLINE 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<typename T, qualifier Q> + GLM_INLINE 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<typename T, qualifier Q> + GLM_INLINE 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<typename T, qualifier Q> + GLM_INLINE 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<typename T, qualifier Q> + GLM_INLINE 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<typename T, qualifier Q> + GLM_INLINE 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<typename T, qualifier Q> + GLM_INLINE 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<typename T, qualifier Q> + GLM_INLINE 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<typename T, qualifier Q> + GLM_INLINE 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<typename T, qualifier Q> + GLM_INLINE 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<typename T, qualifier Q> + GLM_INLINE 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<typename T, qualifier Q> + GLM_INLINE 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<typename T, qualifier Q> + GLM_INLINE 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<typename T, qualifier Q> + GLM_INLINE 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<typename T, qualifier Q> + GLM_INLINE 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<typename T, qualifier Q> + GLM_INLINE 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<typename T, qualifier Q> + GLM_INLINE 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<typename T, qualifier Q> + GLM_INLINE 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<typename T, qualifier Q> + GLM_INLINE 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<typename T, qualifier Q> + GLM_INLINE 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<typename T, qualifier Q> + GLM_INLINE 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<typename T, qualifier Q> + GLM_INLINE 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<typename T, qualifier Q> + GLM_INLINE 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<typename T, qualifier Q> + GLM_INLINE 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<typename T, qualifier Q> + GLM_INLINE 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<typename T, qualifier Q> + GLM_INLINE 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<typename T, qualifier Q> + GLM_INLINE 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<typename T, qualifier Q> + GLM_INLINE 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<typename T, qualifier Q> + GLM_INLINE 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<typename T, qualifier Q> + GLM_INLINE 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<typename T, qualifier Q> + GLM_INLINE 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<typename T, qualifier Q> + GLM_INLINE 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<typename T, qualifier Q> + GLM_INLINE 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<typename T, qualifier Q> + GLM_INLINE 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<typename T, qualifier Q> + GLM_INLINE 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<typename T, qualifier Q> + GLM_INLINE 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<typename T, qualifier Q> + GLM_INLINE 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<typename T, qualifier Q> + GLM_INLINE 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<typename T, qualifier Q> + GLM_INLINE 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<typename T, qualifier Q> + GLM_INLINE 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<typename T, qualifier Q> + GLM_INLINE 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<typename T, qualifier Q> + GLM_INLINE 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<typename T, qualifier Q> + GLM_INLINE 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<typename T, qualifier Q> + GLM_INLINE 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<typename T, qualifier Q> + GLM_INLINE 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<typename T, qualifier Q> + GLM_INLINE 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<typename T, qualifier Q> + GLM_INLINE 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<typename T, qualifier Q> + GLM_INLINE 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<typename T, qualifier Q> + GLM_INLINE 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<typename T, qualifier Q> + GLM_INLINE 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<typename T, qualifier Q> + GLM_INLINE 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<typename T, qualifier Q> + GLM_INLINE 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<typename T, qualifier Q> + GLM_INLINE 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<typename T, qualifier Q> + GLM_INLINE 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<typename T, qualifier Q> + GLM_INLINE 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<typename T, qualifier Q> + GLM_INLINE 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<typename T, qualifier Q> + GLM_INLINE 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<typename T, qualifier Q> + GLM_INLINE 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<typename T, qualifier Q> + GLM_INLINE 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<typename T, qualifier Q> + GLM_INLINE 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<typename T, qualifier Q> + GLM_INLINE 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<typename T, qualifier Q> + GLM_INLINE 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<typename T, qualifier Q> + GLM_INLINE 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<typename T, qualifier Q> + GLM_INLINE 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<typename T, qualifier Q> + GLM_INLINE 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<typename T, qualifier Q> + GLM_INLINE 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<typename T, qualifier Q> + GLM_INLINE 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<typename T, qualifier Q> + GLM_INLINE 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<typename T, qualifier Q> + GLM_INLINE 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<typename T, qualifier Q> + GLM_INLINE 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<typename T, qualifier Q> + GLM_INLINE 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<typename T, qualifier Q> + GLM_INLINE 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<typename T, qualifier Q> + GLM_INLINE 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<typename T, qualifier Q> + GLM_INLINE 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<typename T, qualifier Q> + GLM_INLINE 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<typename T, qualifier Q> + GLM_INLINE 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<typename T, qualifier Q> + GLM_INLINE 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<typename T, qualifier Q> + GLM_INLINE 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<typename T, qualifier Q> + GLM_INLINE 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<typename T, qualifier Q> + GLM_INLINE 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<typename T, qualifier Q> + GLM_INLINE 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<typename T, qualifier Q> + GLM_INLINE 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<typename T, qualifier Q> + GLM_INLINE 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<typename T, qualifier Q> + GLM_INLINE 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<typename T, qualifier Q> + GLM_INLINE 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<typename T, qualifier Q> + GLM_INLINE 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<typename T, qualifier Q> + GLM_INLINE 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<typename T, qualifier Q> + GLM_INLINE 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<typename T, qualifier Q> + GLM_INLINE 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<typename T, qualifier Q> + GLM_INLINE 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<typename T, qualifier Q> + GLM_INLINE 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<typename T, qualifier Q> + GLM_INLINE 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<typename T, qualifier Q> + GLM_INLINE 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<typename T, qualifier Q> + GLM_INLINE 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<typename T, qualifier Q> + GLM_INLINE 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<typename T, qualifier Q> + GLM_INLINE 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<typename T, qualifier Q> + GLM_INLINE 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<typename T, qualifier Q> + GLM_INLINE 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<typename T, qualifier Q> + GLM_INLINE 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<typename T, qualifier Q> + GLM_INLINE 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<typename T, qualifier Q> + GLM_INLINE 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<typename T, qualifier Q> + GLM_INLINE 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<typename T, qualifier Q> + GLM_INLINE 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<typename T, qualifier Q> + GLM_INLINE 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<typename T, qualifier Q> + GLM_INLINE 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<typename T, qualifier Q> + GLM_INLINE 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<typename T, qualifier Q> + GLM_INLINE 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<typename T, qualifier Q> + GLM_INLINE 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<typename T, qualifier Q> + GLM_INLINE 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<typename T, qualifier Q> + GLM_INLINE 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<typename T, qualifier Q> + GLM_INLINE 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<typename T, qualifier Q> + GLM_INLINE 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<typename T, qualifier Q> + GLM_INLINE 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<typename T, qualifier Q> + GLM_INLINE 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<typename T, qualifier Q> + GLM_INLINE 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<typename T, qualifier Q> + GLM_INLINE 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<typename T, qualifier Q> + GLM_INLINE 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<typename T, qualifier Q> + GLM_INLINE 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<typename T, qualifier Q> + GLM_INLINE 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<typename T, qualifier Q> + GLM_INLINE 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<typename T, qualifier Q> + GLM_INLINE 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<typename T, qualifier Q> + GLM_INLINE 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<typename T, qualifier Q> + GLM_INLINE 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<typename T, qualifier Q> + GLM_INLINE 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<typename T, qualifier Q> + GLM_INLINE 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<typename T, qualifier Q> + GLM_INLINE 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<typename T, qualifier Q> + GLM_INLINE 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<typename T, qualifier Q> + GLM_INLINE 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<typename T, qualifier Q> + GLM_INLINE 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<typename T, qualifier Q> + GLM_INLINE 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<typename T, qualifier Q> + GLM_INLINE 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<typename T, qualifier Q> + GLM_INLINE 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<typename T, qualifier Q> + GLM_INLINE 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<typename T, qualifier Q> + GLM_INLINE 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<typename T, qualifier Q> + GLM_INLINE 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<typename T, qualifier Q> + GLM_INLINE 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<typename T, qualifier Q> + GLM_INLINE 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<typename T, qualifier Q> + GLM_INLINE 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<typename T, qualifier Q> + GLM_INLINE 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<typename T, qualifier Q> + GLM_INLINE 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<typename T, qualifier Q> + GLM_INLINE 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<typename T, qualifier Q> + GLM_INLINE 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<typename T, qualifier Q> + GLM_INLINE 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<typename T, qualifier Q> + GLM_INLINE 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<typename T, qualifier Q> + GLM_INLINE 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<typename T, qualifier Q> + GLM_INLINE 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<typename T, qualifier Q> + GLM_INLINE 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<typename T, qualifier Q> + GLM_INLINE 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<typename T, qualifier Q> + GLM_INLINE 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<typename T, qualifier Q> + GLM_INLINE 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<typename T, qualifier Q> + GLM_INLINE 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<typename T, qualifier Q> + GLM_INLINE 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<typename T, qualifier Q> + GLM_INLINE 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<typename T, qualifier Q> + GLM_INLINE 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<typename T, qualifier Q> + GLM_INLINE 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<typename T, qualifier Q> + GLM_INLINE 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<typename T, qualifier Q> + GLM_INLINE 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<typename T, qualifier Q> + GLM_INLINE 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<typename T, qualifier Q> + GLM_INLINE 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<typename T, qualifier Q> + GLM_INLINE 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<typename T, qualifier Q> + GLM_INLINE 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<typename T, qualifier Q> + GLM_INLINE 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<typename T, qualifier Q> + GLM_INLINE 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<typename T, qualifier Q> + GLM_INLINE 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<typename T, qualifier Q> + GLM_INLINE 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<typename T, qualifier Q> + GLM_INLINE 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<typename T, qualifier Q> + GLM_INLINE 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<typename T, qualifier Q> + GLM_INLINE 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<typename T, qualifier Q> + GLM_INLINE 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<typename T, qualifier Q> + GLM_INLINE 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<typename T, qualifier Q> + GLM_INLINE 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<typename T, qualifier Q> + GLM_INLINE 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<typename T, qualifier Q> + GLM_INLINE 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<typename T, qualifier Q> + GLM_INLINE 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<typename T, qualifier Q> + GLM_INLINE 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<typename T, qualifier Q> + GLM_INLINE 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<typename T, qualifier Q> + GLM_INLINE 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<typename T, qualifier Q> + GLM_INLINE 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<typename T, qualifier Q> + GLM_INLINE 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<typename T, qualifier Q> + GLM_INLINE 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<typename T, qualifier Q> + GLM_INLINE 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<typename T, qualifier Q> + GLM_INLINE 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<typename T, qualifier Q> + GLM_INLINE 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<typename T, qualifier Q> + GLM_INLINE 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<typename T, qualifier Q> + GLM_INLINE 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<typename T, qualifier Q> + GLM_INLINE 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<typename T, qualifier Q> + GLM_INLINE 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<typename T, qualifier Q> + GLM_INLINE 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<typename T, qualifier Q> + GLM_INLINE 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<typename T, qualifier Q> + GLM_INLINE 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<typename T, qualifier Q> + GLM_INLINE 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<typename T, qualifier Q> + GLM_INLINE 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<typename T, qualifier Q> + GLM_INLINE 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<typename T, qualifier Q> + GLM_INLINE 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<typename T, qualifier Q> + GLM_INLINE 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<typename T, qualifier Q> + GLM_INLINE 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<typename T, qualifier Q> + GLM_INLINE 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<typename T, qualifier Q> + GLM_INLINE 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<typename T, qualifier Q> + GLM_INLINE 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<typename T, qualifier Q> + GLM_INLINE 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<typename T, qualifier Q> + GLM_INLINE 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<typename T, qualifier Q> + GLM_INLINE 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<typename T, qualifier Q> + GLM_INLINE 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<typename T, qualifier Q> + GLM_INLINE 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<typename T, qualifier Q> + GLM_INLINE 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<typename T, qualifier Q> + GLM_INLINE 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<typename T, qualifier Q> + GLM_INLINE 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<typename T, qualifier Q> + GLM_INLINE 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<typename T, qualifier Q> + GLM_INLINE 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<typename T, qualifier Q> + GLM_INLINE 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<typename T, qualifier Q> + GLM_INLINE 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<typename T, qualifier Q> + GLM_INLINE 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<typename T, qualifier Q> + GLM_INLINE 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<typename T, qualifier Q> + GLM_INLINE 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<typename T, qualifier Q> + GLM_INLINE 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<typename T, qualifier Q> + GLM_INLINE 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<typename T, qualifier Q> + GLM_INLINE 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<typename T, qualifier Q> + GLM_INLINE 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<typename T, qualifier Q> + GLM_INLINE 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<typename T, qualifier Q> + GLM_INLINE 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<typename T, qualifier Q> + GLM_INLINE 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<typename T, qualifier Q> + GLM_INLINE 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<typename T, qualifier Q> + GLM_INLINE 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<typename T, qualifier Q> + GLM_INLINE 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<typename T, qualifier Q> + GLM_INLINE 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<typename T, qualifier Q> + GLM_INLINE 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<typename T, qualifier Q> + GLM_INLINE 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<typename T, qualifier Q> + GLM_INLINE 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<typename T, qualifier Q> + GLM_INLINE 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<typename T, qualifier Q> + GLM_INLINE 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<typename T, qualifier Q> + GLM_INLINE 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<typename T, qualifier Q> + GLM_INLINE 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<typename T, qualifier Q> + GLM_INLINE 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<typename T, qualifier Q> + GLM_INLINE 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<typename T, qualifier Q> + GLM_INLINE 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<typename T, qualifier Q> + GLM_INLINE 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<typename T, qualifier Q> + GLM_INLINE 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<typename T, qualifier Q> + GLM_INLINE 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<typename T, qualifier Q> + GLM_INLINE 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<typename T, qualifier Q> + GLM_INLINE 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<typename T, qualifier Q> + GLM_INLINE 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<typename T, qualifier Q> + GLM_INLINE 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<typename T, qualifier Q> + GLM_INLINE 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<typename T, qualifier Q> + GLM_INLINE 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<typename T, qualifier Q> + GLM_INLINE 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<typename T, qualifier Q> + GLM_INLINE 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<typename T, qualifier Q> + GLM_INLINE 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<typename T, qualifier Q> + GLM_INLINE 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<typename T, qualifier Q> + GLM_INLINE 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<typename T, qualifier Q> + GLM_INLINE 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<typename T, qualifier Q> + GLM_INLINE 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<typename T, qualifier Q> + GLM_INLINE 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<typename T, qualifier Q> + GLM_INLINE 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<typename T, qualifier Q> + GLM_INLINE 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<typename T, qualifier Q> + GLM_INLINE 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<typename T, qualifier Q> + GLM_INLINE 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<typename T, qualifier Q> + GLM_INLINE 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<typename T, qualifier Q> + GLM_INLINE 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<typename T, qualifier Q> + GLM_INLINE 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<typename T, qualifier Q> + GLM_INLINE 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<typename T, qualifier Q> + GLM_INLINE 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<typename T, qualifier Q> + GLM_INLINE 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<typename T, qualifier Q> + GLM_INLINE 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<typename T, qualifier Q> + GLM_INLINE 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<typename T, qualifier Q> + GLM_INLINE 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<typename T, qualifier Q> + GLM_INLINE 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<typename T, qualifier Q> + GLM_INLINE 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<typename T, qualifier Q> + GLM_INLINE 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<typename T, qualifier Q> + GLM_INLINE 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<typename T, qualifier Q> + GLM_INLINE 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<typename T, qualifier Q> + GLM_INLINE 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<typename T, qualifier Q> + GLM_INLINE 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<typename T, qualifier Q> + GLM_INLINE 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<typename T, qualifier Q> + GLM_INLINE 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<typename T, qualifier Q> + GLM_INLINE 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<typename T, qualifier Q> + GLM_INLINE 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<typename T, qualifier Q> + GLM_INLINE 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<typename T, qualifier Q> + GLM_INLINE 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<typename T, qualifier Q> + GLM_INLINE 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<typename T, qualifier Q> + GLM_INLINE 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<typename T, qualifier Q> + GLM_INLINE 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<typename T, qualifier Q> + GLM_INLINE 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<typename T, qualifier Q> + GLM_INLINE 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<typename T, qualifier Q> + GLM_INLINE 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<typename T, qualifier Q> + GLM_INLINE 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<typename T, qualifier Q> + GLM_INLINE 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<typename T, qualifier Q> + GLM_INLINE 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<typename T, qualifier Q> + GLM_INLINE 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<typename T, qualifier Q> + GLM_INLINE 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<typename T, qualifier Q> + GLM_INLINE 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<typename T, qualifier Q> + GLM_INLINE 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<typename T, qualifier Q> + GLM_INLINE 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<typename T, qualifier Q> + GLM_INLINE 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<typename T, qualifier Q> + GLM_INLINE 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<typename T, qualifier Q> + GLM_INLINE 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<typename T, qualifier Q> + GLM_INLINE 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<typename T, qualifier Q> + GLM_INLINE 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<typename T, qualifier Q> + GLM_INLINE 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<typename T, qualifier Q> + GLM_INLINE 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<typename T, qualifier Q> + GLM_INLINE 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<typename T, qualifier Q> + GLM_INLINE 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<typename T, qualifier Q> + GLM_INLINE 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<typename T, qualifier Q> + GLM_INLINE 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<typename T, qualifier Q> + GLM_INLINE 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<typename T, qualifier Q> + GLM_INLINE 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<typename T, qualifier Q> + GLM_INLINE 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<typename T, qualifier Q> + GLM_INLINE 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<typename T, qualifier Q> + GLM_INLINE 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<typename T, qualifier Q> + GLM_INLINE 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<typename T, qualifier Q> + GLM_INLINE 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<typename T, qualifier Q> + GLM_INLINE 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<typename T, qualifier Q> + GLM_INLINE 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<typename T, qualifier Q> + GLM_INLINE 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<typename T, qualifier Q> + GLM_INLINE 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<typename T, qualifier Q> + GLM_INLINE 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<typename T, qualifier Q> + GLM_INLINE 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<typename T, qualifier Q> + GLM_INLINE 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<typename T, qualifier Q> + GLM_INLINE 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<typename T, qualifier Q> + GLM_INLINE 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<typename T, qualifier Q> + GLM_INLINE 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<typename T, qualifier Q> + GLM_INLINE 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<typename T, qualifier Q> + GLM_INLINE 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<typename T, qualifier Q> + GLM_INLINE 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<typename T, qualifier Q> + GLM_INLINE 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<typename T, qualifier Q> + GLM_INLINE 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<typename T, qualifier Q> + GLM_INLINE 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<typename T, qualifier Q> + GLM_INLINE 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<typename T, qualifier Q> + GLM_INLINE 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<typename T, qualifier Q> + GLM_INLINE 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<typename T, qualifier Q> + GLM_INLINE 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<typename T, qualifier Q> + GLM_INLINE 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<typename T, qualifier Q> + GLM_INLINE 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<typename T, qualifier Q> + GLM_INLINE 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<typename T, qualifier Q> + GLM_INLINE 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<typename T, qualifier Q> + GLM_INLINE 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<typename T, qualifier Q> + GLM_INLINE 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<typename T, qualifier Q> + GLM_INLINE 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<typename T, qualifier Q> + GLM_INLINE 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<typename T, qualifier Q> + GLM_INLINE 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<typename T, qualifier Q> + GLM_INLINE 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<typename T, qualifier Q> + GLM_INLINE 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<typename T, qualifier Q> + GLM_INLINE 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<typename T, qualifier Q> + GLM_INLINE 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<typename T, qualifier Q> + GLM_INLINE 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<typename T, qualifier Q> + GLM_INLINE 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<typename T, qualifier Q> + GLM_INLINE 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<typename T, qualifier Q> + GLM_INLINE 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<typename T, qualifier Q> + GLM_INLINE 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<typename T, qualifier Q> + GLM_INLINE 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<typename T, qualifier Q> + GLM_INLINE 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<typename T, qualifier Q> + GLM_INLINE 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<typename T, qualifier Q> + GLM_INLINE 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<typename T, qualifier Q> + GLM_INLINE 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<typename T, qualifier Q> + GLM_INLINE 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<typename T, qualifier Q> + GLM_INLINE 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<typename T, qualifier Q> + GLM_INLINE 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<typename T, qualifier Q> + GLM_INLINE 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<typename T, qualifier Q> + GLM_INLINE 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<typename T, qualifier Q> + GLM_INLINE 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<typename T, qualifier Q> + GLM_INLINE 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<typename T, qualifier Q> + GLM_INLINE 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<typename T, qualifier Q> + GLM_INLINE 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<typename T, qualifier Q> + GLM_INLINE 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<typename T, qualifier Q> + GLM_INLINE 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<typename T, qualifier Q> + GLM_INLINE 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<typename T, qualifier Q> + GLM_INLINE 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<typename T, qualifier Q> + GLM_INLINE 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<typename T, qualifier Q> + GLM_INLINE 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<typename T, qualifier Q> + GLM_INLINE 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<typename T, qualifier Q> + GLM_INLINE 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<typename T, qualifier Q> + GLM_INLINE 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<typename T, qualifier Q> + GLM_INLINE 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<typename T, qualifier Q> + GLM_INLINE 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<typename T, qualifier Q> + GLM_INLINE 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<typename T, qualifier Q> + GLM_INLINE 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<typename T, qualifier Q> + GLM_INLINE 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<typename T, qualifier Q> + GLM_INLINE 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<typename T, qualifier Q> + GLM_INLINE 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<typename T, qualifier Q> + GLM_INLINE 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<typename T, qualifier Q> + GLM_INLINE 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<typename T, qualifier Q> + GLM_INLINE 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<typename T, qualifier Q> + GLM_INLINE 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<typename T, qualifier Q> + GLM_INLINE 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<typename T, qualifier Q> + GLM_INLINE 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<typename T, qualifier Q> + GLM_INLINE 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<typename T, qualifier Q> + GLM_INLINE 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<typename T, qualifier Q> + GLM_INLINE 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<typename T, qualifier Q> + GLM_INLINE 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<typename T, qualifier Q> + GLM_INLINE 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<typename T, qualifier Q> + GLM_INLINE 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<typename T, qualifier Q> + GLM_INLINE 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<typename T, qualifier Q> + GLM_INLINE 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<typename T, qualifier Q> + GLM_INLINE 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<typename T, qualifier Q> + GLM_INLINE 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<typename T, qualifier Q> + GLM_INLINE 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<typename T, qualifier Q> + GLM_INLINE 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<typename T, qualifier Q> + GLM_INLINE 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<typename T, qualifier Q> + GLM_INLINE 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<typename T, qualifier Q> + GLM_INLINE 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<typename T, qualifier Q> + GLM_INLINE 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<typename T, qualifier Q> + GLM_INLINE 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<typename T, qualifier Q> + GLM_INLINE 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<typename T, qualifier Q> + GLM_INLINE 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<typename T, qualifier Q> + GLM_INLINE 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<typename T, qualifier Q> + GLM_INLINE 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<typename T, qualifier Q> + GLM_INLINE 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<typename T, qualifier Q> + GLM_INLINE 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<typename T, qualifier Q> + GLM_INLINE 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<typename T, qualifier Q> + GLM_INLINE 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<typename T, qualifier Q> + GLM_INLINE 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<typename T, qualifier Q> + GLM_INLINE 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<typename T, qualifier Q> + GLM_INLINE 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<typename T, qualifier Q> + GLM_INLINE 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<typename T, qualifier Q> + GLM_INLINE 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<typename T, qualifier Q> + GLM_INLINE 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<typename T, qualifier Q> + GLM_INLINE 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<typename T, qualifier Q> + GLM_INLINE 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<typename T, qualifier Q> + GLM_INLINE 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<typename T, qualifier Q> + GLM_INLINE 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<typename T, qualifier Q> + GLM_INLINE 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<typename T, qualifier Q> + GLM_INLINE 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<typename T, qualifier Q> + GLM_INLINE 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<typename T, qualifier Q> + GLM_INLINE 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<typename T, qualifier Q> + GLM_INLINE 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<typename T, qualifier Q> + GLM_INLINE 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<typename T, qualifier Q> + GLM_INLINE 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<typename T, qualifier Q> + GLM_INLINE 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<typename T, qualifier Q> + GLM_INLINE 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<typename T, qualifier Q> + GLM_INLINE 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<typename T, qualifier Q> + GLM_INLINE 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<typename T, qualifier Q> + GLM_INLINE 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<typename T, qualifier Q> + GLM_INLINE 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<typename T, qualifier Q> + GLM_INLINE 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<typename T, qualifier Q> + GLM_INLINE 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<typename T, qualifier Q> + GLM_INLINE 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<typename T, qualifier Q> + GLM_INLINE 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<typename T, qualifier Q> + GLM_INLINE 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<typename T, qualifier Q> + GLM_INLINE 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<typename T, qualifier Q> + GLM_INLINE 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<typename T, qualifier Q> + GLM_INLINE 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<typename T, qualifier Q> + GLM_INLINE 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<typename T, qualifier Q> + GLM_INLINE 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); + } + +} 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 0000000000000000000000000000000000000000..9ae437126b195e637c846f45549adfd8eb7e9965 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/gtx/vector_angle.hpp @@ -0,0 +1,57 @@ +/// @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 <glm/gtx/vector_angle.hpp> 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" + +#if GLM_MESSAGES == GLM_ENABLE && !defined(GLM_EXT_INCLUDED) +# ifndef GLM_ENABLE_EXPERIMENTAL +# pragma message("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.") +# else +# pragma message("GLM: GLM_GTX_vector_angle extension included") +# endif +#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<length_t L, typename T, qualifier Q> + GLM_FUNC_DECL T angle(vec<L, T, Q> const& x, vec<L, T, Q> const& y); + + //! Returns the oriented angle between two 2d vectors. + //! Parameters need to be normalized. + /// @see gtx_vector_angle extension. + template<typename T, qualifier Q> + 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<typename T, qualifier Q> + 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 0000000000000000000000000000000000000000..a1f957a594fdea0904d32a2cf76f7169a4dcf239 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/gtx/vector_angle.inl @@ -0,0 +1,44 @@ +/// @ref gtx_vector_angle + +namespace glm +{ + template<typename genType> + GLM_FUNC_QUALIFIER genType angle + ( + genType const& x, + genType const& y + ) + { + GLM_STATIC_ASSERT(std::numeric_limits<genType>::is_iec559, "'angle' only accept floating-point inputs"); + return acos(clamp(dot(x, y), genType(-1), genType(1))); + } + + template<length_t L, typename T, qualifier Q> + GLM_FUNC_QUALIFIER T angle(vec<L, T, Q> const& x, vec<L, T, Q> const& y) + { + GLM_STATIC_ASSERT(std::numeric_limits<T>::is_iec559, "'angle' only accept floating-point inputs"); + return acos(clamp(dot(x, y), T(-1), T(1))); + } + + //! \todo epsilon is hard coded to 0.01 + template<typename T, qualifier Q> + GLM_FUNC_QUALIFIER T orientedAngle(vec<2, T, Q> const& x, vec<2, T, Q> const& y) + { + GLM_STATIC_ASSERT(std::numeric_limits<T>::is_iec559, "'orientedAngle' only accept floating-point inputs"); + T const Angle(acos(clamp(dot(x, y), T(-1), T(1)))); + + if(all(epsilonEqual(y, glm::rotate(x, Angle), T(0.0001)))) + return Angle; + else + return -Angle; + } + + template<typename T, qualifier Q> + 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<T>::is_iec559, "'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 0000000000000000000000000000000000000000..77c7b974be5159111151191608ec28f80de09c2e --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/gtx/vector_query.hpp @@ -0,0 +1,66 @@ +/// @ref gtx_vector_query +/// @file glm/gtx/vector_query.hpp +/// +/// @see core (dependence) +/// +/// @defgroup gtx_vector_query GLM_GTX_vector_query +/// @ingroup gtx +/// +/// Include <glm/gtx/vector_query.hpp> to use the features of this extension. +/// +/// Query informations of vector types + +#pragma once + +// Dependency: +#include "../glm.hpp" +#include <cfloat> +#include <limits> + +#if GLM_MESSAGES == GLM_ENABLE && !defined(GLM_EXT_INCLUDED) +# ifndef GLM_ENABLE_EXPERIMENTAL +# pragma message("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.") +# else +# pragma message("GLM: GLM_GTX_vector_query extension included") +# endif +#endif + +namespace glm +{ + /// @addtogroup gtx_vector_query + /// @{ + + //! Check whether two vectors are collinears. + /// @see gtx_vector_query extensions. + template<length_t L, typename T, qualifier Q> + GLM_FUNC_DECL bool areCollinear(vec<L, T, Q> const& v0, vec<L, T, Q> const& v1, T const& epsilon); + + //! Check whether two vectors are orthogonals. + /// @see gtx_vector_query extensions. + template<length_t L, typename T, qualifier Q> + GLM_FUNC_DECL bool areOrthogonal(vec<L, T, Q> const& v0, vec<L, T, Q> const& v1, T const& epsilon); + + //! Check whether a vector is normalized. + /// @see gtx_vector_query extensions. + template<length_t L, typename T, qualifier Q> + GLM_FUNC_DECL bool isNormalized(vec<L, T, Q> const& v, T const& epsilon); + + //! Check whether a vector is null. + /// @see gtx_vector_query extensions. + template<length_t L, typename T, qualifier Q> + GLM_FUNC_DECL bool isNull(vec<L, T, Q> const& v, T const& epsilon); + + //! Check whether a each component of a vector is null. + /// @see gtx_vector_query extensions. + template<length_t L, typename T, qualifier Q> + GLM_FUNC_DECL vec<L, bool, Q> isCompNull(vec<L, T, Q> const& v, T const& epsilon); + + //! Check whether two vectors are orthonormal. + /// @see gtx_vector_query extensions. + template<length_t L, typename T, qualifier Q> + GLM_FUNC_DECL bool areOrthonormal(vec<L, T, Q> const& v0, vec<L, T, Q> 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 0000000000000000000000000000000000000000..d1a5c9be46b1574a80c076d303822261e84e940a --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/gtx/vector_query.inl @@ -0,0 +1,154 @@ +/// @ref gtx_vector_query + +#include <cassert> + +namespace glm{ +namespace detail +{ + template<length_t L, typename T, qualifier Q> + struct compute_areCollinear{}; + + template<typename T, qualifier Q> + 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<T>(0)), vec<3, T, Q>(v1, static_cast<T>(0)))) < epsilon; + } + }; + + template<typename T, qualifier Q> + 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<typename T, qualifier Q> + 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<length_t L, typename T, qualifier Q> + struct compute_isCompNull{}; + + template<typename T, qualifier Q> + 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<typename T, qualifier Q> + 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<typename T, qualifier Q> + 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<length_t L, typename T, qualifier Q> + GLM_FUNC_QUALIFIER bool areCollinear(vec<L, T, Q> const& v0, vec<L, T, Q> const& v1, T const& epsilon) + { + GLM_STATIC_ASSERT(std::numeric_limits<T>::is_iec559, "'areCollinear' only accept floating-point inputs"); + + return detail::compute_areCollinear<L, T, Q>::call(v0, v1, epsilon); + } + + template<length_t L, typename T, qualifier Q> + GLM_FUNC_QUALIFIER bool areOrthogonal(vec<L, T, Q> const& v0, vec<L, T, Q> const& v1, T const& epsilon) + { + GLM_STATIC_ASSERT(std::numeric_limits<T>::is_iec559, "'areOrthogonal' only accept floating-point inputs"); + + return abs(dot(v0, v1)) <= max( + static_cast<T>(1), + length(v0)) * max(static_cast<T>(1), length(v1)) * epsilon; + } + + template<length_t L, typename T, qualifier Q> + GLM_FUNC_QUALIFIER bool isNormalized(vec<L, T, Q> const& v, T const& epsilon) + { + GLM_STATIC_ASSERT(std::numeric_limits<T>::is_iec559, "'isNormalized' only accept floating-point inputs"); + + return abs(length(v) - static_cast<T>(1)) <= static_cast<T>(2) * epsilon; + } + + template<length_t L, typename T, qualifier Q> + GLM_FUNC_QUALIFIER bool isNull(vec<L, T, Q> const& v, T const& epsilon) + { + GLM_STATIC_ASSERT(std::numeric_limits<T>::is_iec559, "'isNull' only accept floating-point inputs"); + + return length(v) <= epsilon; + } + + template<length_t L, typename T, qualifier Q> + GLM_FUNC_QUALIFIER vec<L, bool, Q> isCompNull(vec<L, T, Q> const& v, T const& epsilon) + { + GLM_STATIC_ASSERT(std::numeric_limits<T>::is_iec559, "'isCompNull' only accept floating-point inputs"); + + return detail::compute_isCompNull<L, T, Q>::call(v, epsilon); + } + + template<typename T, qualifier Q> + 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<typename T, qualifier Q> + 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<typename T, qualifier Q> + 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<length_t L, typename T, qualifier Q> + GLM_FUNC_QUALIFIER bool areOrthonormal(vec<L, T, Q> const& v0, vec<L, T, Q> 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 0000000000000000000000000000000000000000..ad4eb3fca740217bf04761eda2e315da1d0125a6 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/gtx/wrap.hpp @@ -0,0 +1,37 @@ +/// @ref gtx_wrap +/// @file glm/gtx/wrap.hpp +/// +/// @see core (dependence) +/// +/// @defgroup gtx_wrap GLM_GTX_wrap +/// @ingroup gtx +/// +/// Include <glm/gtx/wrap.hpp> 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" + +#if GLM_MESSAGES == GLM_ENABLE && !defined(GLM_EXT_INCLUDED) +# ifndef GLM_ENABLE_EXPERIMENTAL +# pragma message("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.") +# else +# pragma message("GLM: GLM_GTX_wrap extension included") +# endif +#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 0000000000000000000000000000000000000000..4be3b4c38aeeaba444655b2d0ac991806e6da48e --- /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 0000000000000000000000000000000000000000..8817db3f0a224f6b36a7a0ad75ffc3d895e75aaa --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/integer.hpp @@ -0,0 +1,212 @@ +/// @ref core +/// @file glm/integer.hpp +/// +/// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 8.8 Integer Functions</a> +/// +/// @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 <glm/integer.hpp> 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 <a href="http://www.opengl.org/sdk/docs/manglsl/xhtml/uaddCarry.xml">GLSL uaddCarry man page</a> + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 8.8 Integer Functions</a> + template<length_t L, qualifier Q> + GLM_FUNC_DECL vec<L, uint, Q> uaddCarry( + vec<L, uint, Q> const& x, + vec<L, uint, Q> const& y, + vec<L, uint, Q> & 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 <a href="http://www.opengl.org/sdk/docs/manglsl/xhtml/usubBorrow.xml">GLSL usubBorrow man page</a> + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 8.8 Integer Functions</a> + template<length_t L, qualifier Q> + GLM_FUNC_DECL vec<L, uint, Q> usubBorrow( + vec<L, uint, Q> const& x, + vec<L, uint, Q> const& y, + vec<L, uint, Q> & 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 <a href="http://www.opengl.org/sdk/docs/manglsl/xhtml/umulExtended.xml">GLSL umulExtended man page</a> + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 8.8 Integer Functions</a> + template<length_t L, qualifier Q> + GLM_FUNC_DECL void umulExtended( + vec<L, uint, Q> const& x, + vec<L, uint, Q> const& y, + vec<L, uint, Q> & msb, + vec<L, uint, Q> & 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 <a href="http://www.opengl.org/sdk/docs/manglsl/xhtml/imulExtended.xml">GLSL imulExtended man page</a> + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 8.8 Integer Functions</a> + template<length_t L, qualifier Q> + GLM_FUNC_DECL void imulExtended( + vec<L, int, Q> const& x, + vec<L, int, Q> const& y, + vec<L, int, Q> & msb, + vec<L, int, Q> & 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 <a href="http://www.opengl.org/sdk/docs/manglsl/xhtml/bitfieldExtract.xml">GLSL bitfieldExtract man page</a> + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 8.8 Integer Functions</a> + template<length_t L, typename T, qualifier Q> + GLM_FUNC_DECL vec<L, T, Q> bitfieldExtract( + vec<L, T, Q> 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 <a href="http://www.opengl.org/sdk/docs/manglsl/xhtml/bitfieldInsert.xml">GLSL bitfieldInsert man page</a> + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 8.8 Integer Functions</a> + template<length_t L, typename T, qualifier Q> + GLM_FUNC_DECL vec<L, T, Q> bitfieldInsert( + vec<L, T, Q> const& Base, + vec<L, T, Q> 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 <a href="http://www.opengl.org/sdk/docs/manglsl/xhtml/bitfieldReverse.xml">GLSL bitfieldReverse man page</a> + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 8.8 Integer Functions</a> + template<length_t L, typename T, qualifier Q> + GLM_FUNC_DECL vec<L, T, Q> bitfieldReverse(vec<L, T, Q> 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 <a href="http://www.opengl.org/sdk/docs/manglsl/xhtml/bitCount.xml">GLSL bitCount man page</a> + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 8.8 Integer Functions</a> + template<typename genType> + 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 <a href="http://www.opengl.org/sdk/docs/manglsl/xhtml/bitCount.xml">GLSL bitCount man page</a> + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 8.8 Integer Functions</a> + template<length_t L, typename T, qualifier Q> + GLM_FUNC_DECL vec<L, int, Q> bitCount(vec<L, T, Q> 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 <a href="http://www.opengl.org/sdk/docs/manglsl/xhtml/findLSB.xml">GLSL findLSB man page</a> + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 8.8 Integer Functions</a> + template<typename genIUType> + 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 <a href="http://www.opengl.org/sdk/docs/manglsl/xhtml/findLSB.xml">GLSL findLSB man page</a> + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 8.8 Integer Functions</a> + template<length_t L, typename T, qualifier Q> + GLM_FUNC_DECL vec<L, int, Q> findLSB(vec<L, T, Q> 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 <a href="http://www.opengl.org/sdk/docs/manglsl/xhtml/findMSB.xml">GLSL findMSB man page</a> + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 8.8 Integer Functions</a> + template<typename genIUType> + 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 <a href="http://www.opengl.org/sdk/docs/manglsl/xhtml/findMSB.xml">GLSL findMSB man page</a> + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 8.8 Integer Functions</a> + template<length_t L, typename T, qualifier Q> + GLM_FUNC_DECL vec<L, int, Q> findMSB(vec<L, T, Q> 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 0000000000000000000000000000000000000000..96bec96b9a63846e577ebbd0e2dd21f65ae8f353 --- /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 0000000000000000000000000000000000000000..d68dc25eda943a72429732f0cdda9080a38b4829 --- /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 0000000000000000000000000000000000000000..b04b7387b1a31826ce22ac25d7926586b7b6f14a --- /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 0000000000000000000000000000000000000000..c85315372dc02dd2d409a8e214ea587101241a43 --- /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 0000000000000000000000000000000000000000..fd4fa31cdee018ed6eaf4a0d5386396010f89c7f --- /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 0000000000000000000000000000000000000000..6342bf5b992dc97c57b532e25c18b8262d2a2f08 --- /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 0000000000000000000000000000000000000000..e013e46b9c20c136332dd71ecc4f65abf7b51cfb --- /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 0000000000000000000000000000000000000000..205725abd25aa6094e140d80f3158b6a7659ea60 --- /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 0000000000000000000000000000000000000000..3515f7f370bf105587316498db2459294cd52537 --- /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 0000000000000000000000000000000000000000..6badf5385048cf47124a1050092bd341e3d21bc4 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/matrix.hpp @@ -0,0 +1,161 @@ +/// @ref core +/// @file glm/matrix.hpp +/// +/// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 8.6 Matrix Functions</a> +/// +/// @defgroup core_func_matrix Matrix functions +/// @ingroup core +/// +/// Provides GLSL matrix functions. +/// +/// Include <glm/matrix.hpp> 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<length_t C, length_t R, typename T, qualifier Q> + struct outerProduct_trait{}; + + template<typename T, qualifier Q> + struct outerProduct_trait<2, 2, T, Q> + { + typedef mat<2, 2, T, Q> type; + }; + + template<typename T, qualifier Q> + struct outerProduct_trait<2, 3, T, Q> + { + typedef mat<3, 2, T, Q> type; + }; + + template<typename T, qualifier Q> + struct outerProduct_trait<2, 4, T, Q> + { + typedef mat<4, 2, T, Q> type; + }; + + template<typename T, qualifier Q> + struct outerProduct_trait<3, 2, T, Q> + { + typedef mat<2, 3, T, Q> type; + }; + + template<typename T, qualifier Q> + struct outerProduct_trait<3, 3, T, Q> + { + typedef mat<3, 3, T, Q> type; + }; + + template<typename T, qualifier Q> + struct outerProduct_trait<3, 4, T, Q> + { + typedef mat<4, 3, T, Q> type; + }; + + template<typename T, qualifier Q> + struct outerProduct_trait<4, 2, T, Q> + { + typedef mat<2, 4, T, Q> type; + }; + + template<typename T, qualifier Q> + struct outerProduct_trait<4, 3, T, Q> + { + typedef mat<3, 4, T, Q> type; + }; + + template<typename T, qualifier Q> + 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 or signed integer scalar types + /// @tparam Q Value from qualifier enum + /// + /// @see <a href="http://www.opengl.org/sdk/docs/manglsl/xhtml/matrixCompMult.xml">GLSL matrixCompMult man page</a> + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 8.6 Matrix Functions</a> + template<length_t C, length_t R, typename T, qualifier Q> + GLM_FUNC_DECL mat<C, R, T, Q> matrixCompMult(mat<C, R, T, Q> const& x, mat<C, R, T, Q> 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 <a href="http://www.opengl.org/sdk/docs/manglsl/xhtml/outerProduct.xml">GLSL outerProduct man page</a> + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 8.6 Matrix Functions</a> + template<length_t C, length_t R, typename T, qualifier Q> + GLM_FUNC_DECL typename detail::outerProduct_trait<C, R, T, Q>::type outerProduct(vec<C, T, Q> const& c, vec<R, T, Q> 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 <a href="http://www.opengl.org/sdk/docs/manglsl/xhtml/transpose.xml">GLSL transpose man page</a> + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 8.6 Matrix Functions</a> + template<length_t C, length_t R, typename T, qualifier Q> + GLM_FUNC_DECL typename mat<C, R, T, Q>::transpose_type transpose(mat<C, R, T, Q> 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 <a href="http://www.opengl.org/sdk/docs/manglsl/xhtml/determinant.xml">GLSL determinant man page</a> + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 8.6 Matrix Functions</a> + template<length_t C, length_t R, typename T, qualifier Q> + GLM_FUNC_DECL T determinant(mat<C, R, T, Q> 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 or signed integer scalar types + /// @tparam Q Value from qualifier enum + /// + /// @see <a href="http://www.opengl.org/sdk/docs/manglsl/xhtml/inverse.xml">GLSL inverse man page</a> + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 8.6 Matrix Functions</a> + template<length_t C, length_t R, typename T, qualifier Q> + GLM_FUNC_DECL mat<C, R, T, Q> inverse(mat<C, R, T, Q> 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 0000000000000000000000000000000000000000..ca83ac1dec960d3ddef0127a43f9504d64772fb3 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/packing.hpp @@ -0,0 +1,173 @@ +/// @ref core +/// @file glm/packing.hpp +/// +/// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 8.4 Floating-Point Pack and Unpack Functions</a> +/// @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 <glm/packing.hpp> 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 <a href="http://www.opengl.org/sdk/docs/manglsl/xhtml/packUnorm2x16.xml">GLSL packUnorm2x16 man page</a> + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 8.4 Floating-Point Pack and Unpack Functions</a> + 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 <a href="http://www.opengl.org/sdk/docs/manglsl/xhtml/packSnorm2x16.xml">GLSL packSnorm2x16 man page</a> + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 8.4 Floating-Point Pack and Unpack Functions</a> + 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 <a href="http://www.opengl.org/sdk/docs/manglsl/xhtml/packUnorm4x8.xml">GLSL packUnorm4x8 man page</a> + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 8.4 Floating-Point Pack and Unpack Functions</a> + 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 <a href="http://www.opengl.org/sdk/docs/manglsl/xhtml/packSnorm4x8.xml">GLSL packSnorm4x8 man page</a> + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 8.4 Floating-Point Pack and Unpack Functions</a> + 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 <a href="http://www.opengl.org/sdk/docs/manglsl/xhtml/unpackUnorm2x16.xml">GLSL unpackUnorm2x16 man page</a> + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 8.4 Floating-Point Pack and Unpack Functions</a> + 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 <a href="http://www.opengl.org/sdk/docs/manglsl/xhtml/unpackSnorm2x16.xml">GLSL unpackSnorm2x16 man page</a> + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 8.4 Floating-Point Pack and Unpack Functions</a> + 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 <a href="http://www.opengl.org/sdk/docs/manglsl/xhtml/unpackUnorm4x8.xml">GLSL unpackUnorm4x8 man page</a> + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 8.4 Floating-Point Pack and Unpack Functions</a> + 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 <a href="http://www.opengl.org/sdk/docs/manglsl/xhtml/unpackSnorm4x8.xml">GLSL unpackSnorm4x8 man page</a> + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 8.4 Floating-Point Pack and Unpack Functions</a> + 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 <a href="http://www.opengl.org/sdk/docs/manglsl/xhtml/packDouble2x32.xml">GLSL packDouble2x32 man page</a> + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 8.4 Floating-Point Pack and Unpack Functions</a> + 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 <a href="http://www.opengl.org/sdk/docs/manglsl/xhtml/unpackDouble2x32.xml">GLSL unpackDouble2x32 man page</a> + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 8.4 Floating-Point Pack and Unpack Functions</a> + 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 <a href="http://www.opengl.org/sdk/docs/manglsl/xhtml/packHalf2x16.xml">GLSL packHalf2x16 man page</a> + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 8.4 Floating-Point Pack and Unpack Functions</a> + 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 <a href="http://www.opengl.org/sdk/docs/manglsl/xhtml/unpackHalf2x16.xml">GLSL unpackHalf2x16 man page</a> + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 8.4 Floating-Point Pack and Unpack Functions</a> + 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 0000000000000000000000000000000000000000..9b017cb4256e0fc3249c6fdbf6b3cad6c5be5f5a --- /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_sub(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 0000000000000000000000000000000000000000..bc351d0119b9a8a2513a23eb02a0dee5f9c03d2d --- /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 0000000000000000000000000000000000000000..07d7cbcc425f2910e2dc50bcb35fe0cd7a0d9609 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/simd/geometric.h @@ -0,0 +1,124 @@ +/// @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) +{ + glm_vec4 const dot0 = glm_vec4_dot(N, I); + glm_vec4 const mul0 = _mm_mul_ps(eta, eta); + glm_vec4 const mul1 = _mm_mul_ps(dot0, dot0); + glm_vec4 const sub0 = _mm_sub_ps(_mm_set1_ps(1.0f), mul0); + glm_vec4 const sub1 = _mm_sub_ps(_mm_set1_ps(1.0f), mul1); + glm_vec4 const mul2 = _mm_mul_ps(sub0, sub1); + + if(_mm_movemask_ps(_mm_cmplt_ss(mul2, _mm_set1_ps(0.0f))) == 0) + return _mm_set1_ps(0.0f); + + glm_vec4 const sqt0 = _mm_sqrt_ps(mul2); + 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 0000000000000000000000000000000000000000..93814183fe027ab62e3532062de1abbb0ffe8c9e --- /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 0000000000000000000000000000000000000000..b6c42ea4c17cff134a492d057309a131489ef51a --- /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 0000000000000000000000000000000000000000..6c38b06c93738c3d5e8e4e59b9726bc83ee95965 --- /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 <arm_neon.h> + +namespace glm { + namespace neon { + static 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 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 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 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 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 0000000000000000000000000000000000000000..609163eb0d77aaccd0f165fab215a703d70f91c8 --- /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 0000000000000000000000000000000000000000..ad25cc15a26141ca2a921c59eef9e9eabfabf2a0 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/simd/platform.h @@ -0,0 +1,398 @@ +#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 + +// Visual C++ defines +#define GLM_COMPILER_VC 0x01000000 +#define GLM_COMPILER_VC12 0x01000001 +#define GLM_COMPILER_VC14 0x01000002 +#define GLM_COMPILER_VC15 0x01000003 +#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 + +// 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_GCC7 0x02000400 +#define GLM_COMPILER_GCC8 0x02000500 + +// CUDA +#define GLM_COMPILER_CUDA 0x10000000 +#define GLM_COMPILER_CUDA75 0x10000001 +#define GLM_COMPILER_CUDA80 0x10000002 +#define GLM_COMPILER_CUDA90 0x10000004 + +// SYCL +#define GLM_COMPILER_SYCL 0x00300000 + +// 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_CLANG40 0x200000B0 +#define GLM_COMPILER_CLANG41 0x200000C0 +#define GLM_COMPILER_CLANG42 0x200000D0 + +// 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 >= 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 <cuda.h> // make sure version is defined since nvcc does not define it itself! +# endif +# if 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 + +// SYCL +#elif defined(__SYCL_DEVICE_ONLY__) +# define GLM_COMPILER GLM_COMPILER_SYCL + +// 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_CLANG40 +# elif __clang_major__ == 4 && __clang_minor__ == 1 +# define GLM_COMPILER GLM_COMPILER_CLANG41 +# elif __clang_major__ == 4 && __clang_minor__ >= 2 +# define GLM_COMPILER GLM_COMPILER_CLANG42 +# elif __clang_major__ >= 4 +# define GLM_COMPILER GLM_COMPILER_CLANG42 +# endif +# endif + +// Visual C++ +#elif defined(_MSC_VER) +# if _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__ >= 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 <immintrin.h> +#elif GLM_ARCH & GLM_ARCH_AVX_BIT +# include <immintrin.h> +#elif GLM_ARCH & GLM_ARCH_SSE42_BIT +# if GLM_COMPILER & GLM_COMPILER_CLANG +# include <popcntintrin.h> +# endif +# include <nmmintrin.h> +#elif GLM_ARCH & GLM_ARCH_SSE41_BIT +# include <smmintrin.h> +#elif GLM_ARCH & GLM_ARCH_SSSE3_BIT +# include <tmmintrin.h> +#elif GLM_ARCH & GLM_ARCH_SSE3_BIT +# include <pmmintrin.h> +#elif GLM_ARCH & GLM_ARCH_SSE2_BIT +# include <emmintrin.h> +#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 0000000000000000000000000000000000000000..739b796e7e45c86f07dbe5d508ed46dd9a9c6fd4 --- /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 0000000000000000000000000000000000000000..f7385e9747363cf64be22d5b0b5e061983a36a12 --- /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 0000000000000000000000000000000000000000..fcf07f899f8df646da5bafe825404e191524fe15 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/trigonometric.hpp @@ -0,0 +1,210 @@ +/// @ref core +/// @file glm/trigonometric.hpp +/// +/// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 8.1 Angle and Trigonometry Functions</a> +/// +/// @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 <glm/trigonometric.hpp> 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 <a href="http://www.opengl.org/sdk/docs/manglsl/xhtml/radians.xml">GLSL radians man page</a> + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 8.1 Angle and Trigonometry Functions</a> + template<length_t L, typename T, qualifier Q> + GLM_FUNC_DECL GLM_CONSTEXPR vec<L, T, Q> radians(vec<L, T, Q> 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 <a href="http://www.opengl.org/sdk/docs/manglsl/xhtml/degrees.xml">GLSL degrees man page</a> + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 8.1 Angle and Trigonometry Functions</a> + template<length_t L, typename T, qualifier Q> + GLM_FUNC_DECL GLM_CONSTEXPR vec<L, T, Q> degrees(vec<L, T, Q> 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 <a href="http://www.opengl.org/sdk/docs/manglsl/xhtml/sin.xml">GLSL sin man page</a> + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 8.1 Angle and Trigonometry Functions</a> + template<length_t L, typename T, qualifier Q> + GLM_FUNC_DECL vec<L, T, Q> sin(vec<L, T, Q> 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 <a href="http://www.opengl.org/sdk/docs/manglsl/xhtml/cos.xml">GLSL cos man page</a> + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 8.1 Angle and Trigonometry Functions</a> + template<length_t L, typename T, qualifier Q> + GLM_FUNC_DECL vec<L, T, Q> cos(vec<L, T, Q> 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 <a href="http://www.opengl.org/sdk/docs/manglsl/xhtml/tan.xml">GLSL tan man page</a> + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 8.1 Angle and Trigonometry Functions</a> + template<length_t L, typename T, qualifier Q> + GLM_FUNC_DECL vec<L, T, Q> tan(vec<L, T, Q> 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 <a href="http://www.opengl.org/sdk/docs/manglsl/xhtml/asin.xml">GLSL asin man page</a> + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 8.1 Angle and Trigonometry Functions</a> + template<length_t L, typename T, qualifier Q> + GLM_FUNC_DECL vec<L, T, Q> asin(vec<L, T, Q> const& x); + + /// Arc cosine. Returns an angle whose sine 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 <a href="http://www.opengl.org/sdk/docs/manglsl/xhtml/acos.xml">GLSL acos man page</a> + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 8.1 Angle and Trigonometry Functions</a> + template<length_t L, typename T, qualifier Q> + GLM_FUNC_DECL vec<L, T, Q> acos(vec<L, T, Q> 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 <a href="http://www.opengl.org/sdk/docs/manglsl/xhtml/atan.xml">GLSL atan man page</a> + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 8.1 Angle and Trigonometry Functions</a> + template<length_t L, typename T, qualifier Q> + GLM_FUNC_DECL vec<L, T, Q> atan(vec<L, T, Q> const& y, vec<L, T, Q> 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 <a href="http://www.opengl.org/sdk/docs/manglsl/xhtml/atan.xml">GLSL atan man page</a> + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 8.1 Angle and Trigonometry Functions</a> + template<length_t L, typename T, qualifier Q> + GLM_FUNC_DECL vec<L, T, Q> atan(vec<L, T, Q> 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 <a href="http://www.opengl.org/sdk/docs/manglsl/xhtml/sinh.xml">GLSL sinh man page</a> + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 8.1 Angle and Trigonometry Functions</a> + template<length_t L, typename T, qualifier Q> + GLM_FUNC_DECL vec<L, T, Q> sinh(vec<L, T, Q> 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 <a href="http://www.opengl.org/sdk/docs/manglsl/xhtml/cosh.xml">GLSL cosh man page</a> + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 8.1 Angle and Trigonometry Functions</a> + template<length_t L, typename T, qualifier Q> + GLM_FUNC_DECL vec<L, T, Q> cosh(vec<L, T, Q> 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 <a href="http://www.opengl.org/sdk/docs/manglsl/xhtml/tanh.xml">GLSL tanh man page</a> + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 8.1 Angle and Trigonometry Functions</a> + template<length_t L, typename T, qualifier Q> + GLM_FUNC_DECL vec<L, T, Q> tanh(vec<L, T, Q> 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 <a href="http://www.opengl.org/sdk/docs/manglsl/xhtml/asinh.xml">GLSL asinh man page</a> + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 8.1 Angle and Trigonometry Functions</a> + template<length_t L, typename T, qualifier Q> + GLM_FUNC_DECL vec<L, T, Q> asinh(vec<L, T, Q> 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 <a href="http://www.opengl.org/sdk/docs/manglsl/xhtml/acosh.xml">GLSL acosh man page</a> + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 8.1 Angle and Trigonometry Functions</a> + template<length_t L, typename T, qualifier Q> + GLM_FUNC_DECL vec<L, T, Q> acosh(vec<L, T, Q> 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 <a href="http://www.opengl.org/sdk/docs/manglsl/xhtml/atanh.xml">GLSL atanh man page</a> + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 8.1 Angle and Trigonometry Functions</a> + template<length_t L, typename T, qualifier Q> + GLM_FUNC_DECL vec<L, T, Q> atanh(vec<L, T, Q> 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 0000000000000000000000000000000000000000..cd4e0708e109cfa2c35bff6ea146dbdd2167104b --- /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 0000000000000000000000000000000000000000..f5a927dbe4c577736c88b86638454c095e1eb9bb --- /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 0000000000000000000000000000000000000000..c6ea9f1ff4c51cd9cfaee865e7413f928e354b71 --- /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 0000000000000000000000000000000000000000..a0fe17eb707a4e5ba3590fe16d2704cecc3bd8ef --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/glm/vector_relational.hpp @@ -0,0 +1,121 @@ +/// @ref core +/// @file glm/vector_relational.hpp +/// +/// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 8.7 Vector Relational Functions</a> +/// +/// @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 <glm/vector_relational.hpp> 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 <a href="http://www.opengl.org/sdk/docs/manglsl/xhtml/lessThan.xml">GLSL lessThan man page</a> + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 8.7 Vector Relational Functions</a> + template<length_t L, typename T, qualifier Q> + GLM_FUNC_DECL GLM_CONSTEXPR vec<L, bool, Q> lessThan(vec<L, T, Q> const& x, vec<L, T, Q> 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 <a href="http://www.opengl.org/sdk/docs/manglsl/xhtml/lessThanEqual.xml">GLSL lessThanEqual man page</a> + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 8.7 Vector Relational Functions</a> + template<length_t L, typename T, qualifier Q> + GLM_FUNC_DECL GLM_CONSTEXPR vec<L, bool, Q> lessThanEqual(vec<L, T, Q> const& x, vec<L, T, Q> 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 <a href="http://www.opengl.org/sdk/docs/manglsl/xhtml/greaterThan.xml">GLSL greaterThan man page</a> + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 8.7 Vector Relational Functions</a> + template<length_t L, typename T, qualifier Q> + GLM_FUNC_DECL GLM_CONSTEXPR vec<L, bool, Q> greaterThan(vec<L, T, Q> const& x, vec<L, T, Q> 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 <a href="http://www.opengl.org/sdk/docs/manglsl/xhtml/greaterThanEqual.xml">GLSL greaterThanEqual man page</a> + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 8.7 Vector Relational Functions</a> + template<length_t L, typename T, qualifier Q> + GLM_FUNC_DECL GLM_CONSTEXPR vec<L, bool, Q> greaterThanEqual(vec<L, T, Q> const& x, vec<L, T, Q> 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 <a href="http://www.opengl.org/sdk/docs/manglsl/xhtml/equal.xml">GLSL equal man page</a> + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 8.7 Vector Relational Functions</a> + template<length_t L, typename T, qualifier Q> + GLM_FUNC_DECL GLM_CONSTEXPR vec<L, bool, Q> equal(vec<L, T, Q> const& x, vec<L, T, Q> 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 <a href="http://www.opengl.org/sdk/docs/manglsl/xhtml/notEqual.xml">GLSL notEqual man page</a> + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 8.7 Vector Relational Functions</a> + template<length_t L, typename T, qualifier Q> + GLM_FUNC_DECL GLM_CONSTEXPR vec<L, bool, Q> notEqual(vec<L, T, Q> const& x, vec<L, T, Q> 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 <a href="http://www.opengl.org/sdk/docs/manglsl/xhtml/any.xml">GLSL any man page</a> + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 8.7 Vector Relational Functions</a> + template<length_t L, qualifier Q> + GLM_FUNC_DECL GLM_CONSTEXPR bool any(vec<L, bool, Q> 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 <a href="http://www.opengl.org/sdk/docs/manglsl/xhtml/all.xml">GLSL all man page</a> + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 8.7 Vector Relational Functions</a> + template<length_t L, qualifier Q> + GLM_FUNC_DECL GLM_CONSTEXPR bool all(vec<L, bool, Q> 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 <a href="http://www.opengl.org/sdk/docs/manglsl/xhtml/not.xml">GLSL not man page</a> + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 8.7 Vector Relational Functions</a> + template<length_t L, qualifier Q> + GLM_FUNC_DECL GLM_CONSTEXPR vec<L, bool, Q> not_(vec<L, bool, Q> const& v); + + /// @} +}//namespace glm + +#include "detail/func_vector_relational.inl" diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/gsl/algorithm b/Plugins/CesiumForUnreal/Source/ThirdParty/include/gsl/algorithm new file mode 100644 index 0000000000000000000000000000000000000000..b27475de54b87a1c9692eca6adf853650e727361 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/gsl/algorithm @@ -0,0 +1,63 @@ +/////////////////////////////////////////////////////////////////////////////// +// +// Copyright (c) 2015 Microsoft Corporation. All rights reserved. +// +// This code is licensed under the MIT License (MIT). +// +// 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 GSL_ALGORITHM_H +#define GSL_ALGORITHM_H + +#include <gsl/assert> // for Expects +#include <gsl/span> // for dynamic_extent, span + +#include <algorithm> // for copy_n +#include <cstddef> // for ptrdiff_t +#include <type_traits> // for is_assignable + +#ifdef _MSC_VER +#pragma warning(push) + +// turn off some warnings that are noisy about our Expects statements +#pragma warning(disable : 4127) // conditional expression is constant +#pragma warning(disable : 4996) // unsafe use of std::copy_n + +#endif // _MSC_VER + +namespace gsl +{ +// Note: this will generate faster code than std::copy using span iterator in older msvc+stl +// not necessary for msvc since VS2017 15.8 (_MSC_VER >= 1915) +template <class SrcElementType, std::size_t SrcExtent, class DestElementType, + std::size_t DestExtent> +void copy(span<SrcElementType, SrcExtent> src, span<DestElementType, DestExtent> dest) +{ + static_assert(std::is_assignable<decltype(*dest.data()), decltype(*src.data())>::value, + "Elements of source span can not be assigned to elements of destination span"); + static_assert(SrcExtent == dynamic_extent || DestExtent == dynamic_extent || + (SrcExtent <= DestExtent), + "Source range is longer than target range"); + + Expects(dest.size() >= src.size()); + // clang-format off + GSL_SUPPRESS(stl.1) // NO-FORMAT: attribute + // clang-format on + std::copy_n(src.data(), src.size(), dest.data()); +} + +} // namespace gsl + +#ifdef _MSC_VER +#pragma warning(pop) +#endif // _MSC_VER + +#endif // GSL_ALGORITHM_H diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/gsl/assert b/Plugins/CesiumForUnreal/Source/ThirdParty/include/gsl/assert new file mode 100644 index 0000000000000000000000000000000000000000..0cc54f66b5b21b1251964a1de161da953ae216bf --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/gsl/assert @@ -0,0 +1,135 @@ +/////////////////////////////////////////////////////////////////////////////// +// +// Copyright (c) 2015 Microsoft Corporation. All rights reserved. +// +// This code is licensed under the MIT License (MIT). +// +// 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 GSL_CONTRACTS_H +#define GSL_CONTRACTS_H + +// +// Temporary until MSVC STL supports no-exceptions mode. +// Currently terminate is a no-op in this mode, so we add termination behavior back +// +#if defined(_MSC_VER) && (defined(_KERNEL_MODE) || (defined(_HAS_EXCEPTIONS) && !_HAS_EXCEPTIONS)) + +#define GSL_MSVC_USE_STL_NOEXCEPTION_WORKAROUND +#include <intrin.h> +#define RANGE_CHECKS_FAILURE 0 + +#if defined(__clang__) +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Winvalid-noreturn" +#endif // defined(__clang__) + +#else // defined(_MSC_VER) && (defined(_KERNEL_MODE) || (defined(_HAS_EXCEPTIONS) && + // !_HAS_EXCEPTIONS)) + +#include <exception> + +#endif // defined(_MSC_VER) && (defined(_KERNEL_MODE) || (defined(_HAS_EXCEPTIONS) && + // !_HAS_EXCEPTIONS)) + +// +// make suppress attributes parse for some compilers +// Hopefully temporary until suppression standardization occurs +// +#if defined(__clang__) +#define GSL_SUPPRESS(x) [[gsl::suppress("x")]] +#else +#if defined(_MSC_VER) && !defined(__INTEL_COMPILER) +#define GSL_SUPPRESS(x) [[gsl::suppress(x)]] +#else +#define GSL_SUPPRESS(x) +#endif // _MSC_VER +#endif // __clang__ + +#define GSL_STRINGIFY_DETAIL(x) #x +#define GSL_STRINGIFY(x) GSL_STRINGIFY_DETAIL(x) + +#if defined(__clang__) || defined(__GNUC__) +#define GSL_LIKELY(x) __builtin_expect(!!(x), 1) +#define GSL_UNLIKELY(x) __builtin_expect(!!(x), 0) + +#else + +#define GSL_LIKELY(x) (!!(x)) +#define GSL_UNLIKELY(x) (!!(x)) +#endif // defined(__clang__) || defined(__GNUC__) + +// +// GSL_ASSUME(cond) +// +// Tell the optimizer that the predicate cond must hold. It is unspecified +// whether or not cond is actually evaluated. +// +#ifdef _MSC_VER +#define GSL_ASSUME(cond) __assume(cond) +#elif defined(__GNUC__) +#define GSL_ASSUME(cond) ((cond) ? static_cast<void>(0) : __builtin_unreachable()) +#else +#define GSL_ASSUME(cond) static_cast<void>((cond) ? 0 : 0) +#endif + +// +// GSL.assert: assertions +// + +namespace gsl +{ + +namespace details +{ +#if defined(GSL_MSVC_USE_STL_NOEXCEPTION_WORKAROUND) + + typedef void(__cdecl* terminate_handler)(); + + // clang-format off + GSL_SUPPRESS(f.6) // NO-FORMAT: attribute + // clang-format on + [[noreturn]] inline void __cdecl default_terminate_handler() + { + __fastfail(RANGE_CHECKS_FAILURE); + } + + inline gsl::details::terminate_handler& get_terminate_handler() noexcept + { + static terminate_handler handler = &default_terminate_handler; + return handler; + } + +#endif // defined(GSL_MSVC_USE_STL_NOEXCEPTION_WORKAROUND) + + [[noreturn]] inline void terminate() noexcept + { +#if defined(GSL_MSVC_USE_STL_NOEXCEPTION_WORKAROUND) + (*gsl::details::get_terminate_handler())(); +#else + std::terminate(); +#endif // defined(GSL_MSVC_USE_STL_NOEXCEPTION_WORKAROUND) + } + +} // namespace details +} // namespace gsl + +#define GSL_CONTRACT_CHECK(type, cond) \ + (GSL_LIKELY(cond) ? static_cast<void>(0) : gsl::details::terminate()) + +#define Expects(cond) GSL_CONTRACT_CHECK("Precondition", cond) +#define Ensures(cond) GSL_CONTRACT_CHECK("Postcondition", cond) + +#if defined(GSL_MSVC_USE_STL_NOEXCEPTION_WORKAROUND) && defined(__clang__) +#pragma clang diagnostic pop +#endif + +#endif // GSL_CONTRACTS_H diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/gsl/byte b/Plugins/CesiumForUnreal/Source/ThirdParty/include/gsl/byte new file mode 100644 index 0000000000000000000000000000000000000000..9231340b56839e06794c6a6f25e8bf651457e2e9 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/gsl/byte @@ -0,0 +1,213 @@ +/////////////////////////////////////////////////////////////////////////////// +// +// Copyright (c) 2015 Microsoft Corporation. All rights reserved. +// +// This code is licensed under the MIT License (MIT). +// +// 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 GSL_BYTE_H +#define GSL_BYTE_H + +// +// make suppress attributes work for some compilers +// Hopefully temporary until suppression standardization occurs +// +#if defined(__clang__) +#define GSL_SUPPRESS(x) [[gsl::suppress("x")]] +#else +#if defined(_MSC_VER) && !defined(__INTEL_COMPILER) +#define GSL_SUPPRESS(x) [[gsl::suppress(x)]] +#else +#define GSL_SUPPRESS(x) +#endif // _MSC_VER +#endif // __clang__ + +#include <type_traits> + +// VS2017 15.8 added support for the __cpp_lib_byte definition +// To do: drop _HAS_STD_BYTE when support for pre 15.8 expires +#ifdef _MSC_VER + +#pragma warning(push) + +// Turn MSVC /analyze rules that generate too much noise. TODO: fix in the tool. +#pragma warning(disable : 26493) // don't use c-style casts // TODO: MSVC suppression in templates + // does not always work + +#ifndef GSL_USE_STD_BYTE +// this tests if we are under MSVC and the standard lib has std::byte and it is enabled +#if (defined(_HAS_STD_BYTE) && _HAS_STD_BYTE) || \ + (defined(__cpp_lib_byte) && __cpp_lib_byte >= 201603) + +#define GSL_USE_STD_BYTE 1 + +#else // (defined(_HAS_STD_BYTE) && _HAS_STD_BYTE) || (defined(__cpp_lib_byte) && __cpp_lib_byte >= + // 201603) + +#define GSL_USE_STD_BYTE 0 + +#endif // (defined(_HAS_STD_BYTE) && _HAS_STD_BYTE) || (defined(__cpp_lib_byte) && __cpp_lib_byte >= + // 201603) +#endif // GSL_USE_STD_BYTE + +#else // _MSC_VER + +#ifndef GSL_USE_STD_BYTE +#include <cstddef> /* __cpp_lib_byte */ +// this tests if we are under GCC or Clang with enough -std=c++1z power to get us std::byte +// also check if libc++ version is sufficient (> 5.0) or libstdc++ actually contains std::byte +#if defined(__cplusplus) && (__cplusplus >= 201703L) && \ + (defined(__cpp_lib_byte) && (__cpp_lib_byte >= 201603) || \ + defined(_LIBCPP_VERSION) && (_LIBCPP_VERSION >= 5000)) + +#define GSL_USE_STD_BYTE 1 + +#else // defined(__cplusplus) && (__cplusplus >= 201703L) && + // (defined(__cpp_lib_byte) && (__cpp_lib_byte >= 201603) || + // defined(_LIBCPP_VERSION) && (_LIBCPP_VERSION >= 5000)) + +#define GSL_USE_STD_BYTE 0 + +#endif // defined(__cplusplus) && (__cplusplus >= 201703L) && + // (defined(__cpp_lib_byte) && (__cpp_lib_byte >= 201603) || + // defined(_LIBCPP_VERSION) && (_LIBCPP_VERSION >= 5000)) +#endif // GSL_USE_STD_BYTE + +#endif // _MSC_VER + +// Use __may_alias__ attribute on gcc and clang +#if defined __clang__ || (defined(__GNUC__) && __GNUC__ > 5) +#define byte_may_alias __attribute__((__may_alias__)) +#else // defined __clang__ || defined __GNUC__ +#define byte_may_alias +#endif // defined __clang__ || defined __GNUC__ + +#if GSL_USE_STD_BYTE +#include <cstddef> +#endif + +namespace gsl +{ +#if GSL_USE_STD_BYTE + +using std::byte; +using std::to_integer; + +#else // GSL_USE_STD_BYTE + +// This is a simple definition for now that allows +// use of byte within span<> to be standards-compliant +enum class byte_may_alias byte : unsigned char +{ +}; + +template <class IntegerType, class = std::enable_if_t<std::is_integral<IntegerType>::value>> +constexpr byte& operator<<=(byte& b, IntegerType shift) noexcept +{ + return b = byte(static_cast<unsigned char>(b) << shift); +} + +template <class IntegerType, class = std::enable_if_t<std::is_integral<IntegerType>::value>> +constexpr byte operator<<(byte b, IntegerType shift) noexcept +{ + return byte(static_cast<unsigned char>(b) << shift); +} + +template <class IntegerType, class = std::enable_if_t<std::is_integral<IntegerType>::value>> +constexpr byte& operator>>=(byte& b, IntegerType shift) noexcept +{ + return b = byte(static_cast<unsigned char>(b) >> shift); +} + +template <class IntegerType, class = std::enable_if_t<std::is_integral<IntegerType>::value>> +constexpr byte operator>>(byte b, IntegerType shift) noexcept +{ + return byte(static_cast<unsigned char>(b) >> shift); +} + +constexpr byte& operator|=(byte& l, byte r) noexcept +{ + return l = byte(static_cast<unsigned char>(l) | static_cast<unsigned char>(r)); +} + +constexpr byte operator|(byte l, byte r) noexcept +{ + return byte(static_cast<unsigned char>(l) | static_cast<unsigned char>(r)); +} + +constexpr byte& operator&=(byte& l, byte r) noexcept +{ + return l = byte(static_cast<unsigned char>(l) & static_cast<unsigned char>(r)); +} + +constexpr byte operator&(byte l, byte r) noexcept +{ + return byte(static_cast<unsigned char>(l) & static_cast<unsigned char>(r)); +} + +constexpr byte& operator^=(byte& l, byte r) noexcept +{ + return l = byte(static_cast<unsigned char>(l) ^ static_cast<unsigned char>(r)); +} + +constexpr byte operator^(byte l, byte r) noexcept +{ + return byte(static_cast<unsigned char>(l) ^ static_cast<unsigned char>(r)); +} + +constexpr byte operator~(byte b) noexcept { return byte(~static_cast<unsigned char>(b)); } + +template <class IntegerType, class = std::enable_if_t<std::is_integral<IntegerType>::value>> +constexpr IntegerType to_integer(byte b) noexcept +{ + return static_cast<IntegerType>(b); +} + +#endif // GSL_USE_STD_BYTE + +template <bool E, typename T> +constexpr byte to_byte_impl(T t) noexcept +{ + static_assert( + E, "gsl::to_byte(t) must be provided an unsigned char, otherwise data loss may occur. " + "If you are calling to_byte with an integer contant use: gsl::to_byte<t>() version."); + return static_cast<byte>(t); +} +template <> +// NOTE: need suppression since c++14 does not allow "return {t}" +// GSL_SUPPRESS(type.4) // NO-FORMAT: attribute // TODO: suppression does not work +constexpr byte to_byte_impl<true, unsigned char>(unsigned char t) noexcept +{ + return byte(t); +} + +template <typename T> +constexpr byte to_byte(T t) noexcept +{ + return to_byte_impl<std::is_same<T, unsigned char>::value, T>(t); +} + +template <int I> +constexpr byte to_byte() noexcept +{ + static_assert(I >= 0 && I <= 255, + "gsl::byte only has 8 bits of storage, values must be in range 0-255"); + return static_cast<byte>(I); +} + +} // namespace gsl + +#ifdef _MSC_VER +#pragma warning(pop) +#endif // _MSC_VER + +#endif // GSL_BYTE_H diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/gsl/gsl b/Plugins/CesiumForUnreal/Source/ThirdParty/include/gsl/gsl new file mode 100644 index 0000000000000000000000000000000000000000..adadc40fe695f5c293c50734c30bf0b7d601425f --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/gsl/gsl @@ -0,0 +1,32 @@ +/////////////////////////////////////////////////////////////////////////////// +// +// Copyright (c) 2015 Microsoft Corporation. All rights reserved. +// +// This code is licensed under the MIT License (MIT). +// +// 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 GSL_GSL_H +#define GSL_GSL_H + +#include <gsl/algorithm> // copy +#include <gsl/assert> // Ensures/Expects +#include <gsl/byte> // byte +#include <gsl/pointers> // owner, not_null +#include <gsl/span> // span +#include <gsl/string_span> // zstring, string_span, zstring_builder... +#include <gsl/util> // finally()/narrow_cast()... + +#ifdef __cpp_exceptions +#include <gsl/narrow> // narrow() +#endif + +#endif // GSL_GSL_H diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/gsl/gsl_algorithm b/Plugins/CesiumForUnreal/Source/ThirdParty/include/gsl/gsl_algorithm new file mode 100644 index 0000000000000000000000000000000000000000..6e43e13dce410cb61b507ce7dc4b440deaeb6dc7 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/gsl/gsl_algorithm @@ -0,0 +1,3 @@ +#pragma once +#pragma message("This header will soon be removed. Use <gsl/algorithm> instead of <gsl/gsl_algorithm>") +#include <gsl/algorithm> diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/gsl/gsl_assert b/Plugins/CesiumForUnreal/Source/ThirdParty/include/gsl/gsl_assert new file mode 100644 index 0000000000000000000000000000000000000000..1dd24b1b3858f5efa6b39a8e5352ac5a1de73726 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/gsl/gsl_assert @@ -0,0 +1,3 @@ +#pragma once +#pragma message("This header will soon be removed. Use <gsl/assert> instead of <gsl/gsl_assert>") +#include <gsl/assert> diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/gsl/gsl_byte b/Plugins/CesiumForUnreal/Source/ThirdParty/include/gsl/gsl_byte new file mode 100644 index 0000000000000000000000000000000000000000..b41f2d9a4d5a08636fe5c616b876d74b3c0c38b6 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/gsl/gsl_byte @@ -0,0 +1,3 @@ +#pragma once +#pragma message("This header will soon be removed. Use <gsl/byte> instead of <gsl/gsl_byte>") +#include <gsl/byte> diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/gsl/gsl_narrow b/Plugins/CesiumForUnreal/Source/ThirdParty/include/gsl/gsl_narrow new file mode 100644 index 0000000000000000000000000000000000000000..d30d42128ca0d68febdbdf22220d436ec6fbbc80 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/gsl/gsl_narrow @@ -0,0 +1,3 @@ +#pragma once +#pragma message("This header will soon be removed. Use <gsl/narrow> instead of <gsl/gsl_narrow>") +#include <gsl/narrow> diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/gsl/gsl_util b/Plugins/CesiumForUnreal/Source/ThirdParty/include/gsl/gsl_util new file mode 100644 index 0000000000000000000000000000000000000000..feb19902cd643558b71fa31be8f08ec66208508c --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/gsl/gsl_util @@ -0,0 +1,3 @@ +#pragma once +#pragma message("This header will soon be removed. Use <gsl/util> instead of <gsl/gsl_util>") +#include <gsl/util> diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/gsl/narrow b/Plugins/CesiumForUnreal/Source/ThirdParty/include/gsl/narrow new file mode 100644 index 0000000000000000000000000000000000000000..a8010450b1ce7e4e9f9c00aa9f7947c70b82097a --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/gsl/narrow @@ -0,0 +1,49 @@ +/////////////////////////////////////////////////////////////////////////////// +// +// Copyright (c) 2015 Microsoft Corporation. All rights reserved. +// +// This code is licensed under the MIT License (MIT). +// +// 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 GSL_NARROW_H +#define GSL_NARROW_H +#include <gsl/assert> // for Expects +#include <gsl/util> // for narrow_cast +namespace gsl +{ +struct narrowing_error : public std::exception +{ + const char* what() const noexcept override { return "narrowing_error"; } +}; + +// narrow() : a checked version of narrow_cast() that throws if the cast changed the value +template <class T, class U> +// clang-format off +GSL_SUPPRESS(type.1) // NO-FORMAT: attribute +GSL_SUPPRESS(f.6) // NO-FORMAT: attribute // TODO: MSVC /analyze does not recognise noexcept(false) +// clang-format on + constexpr T narrow(U u) noexcept(false) +{ + constexpr const bool is_different_signedness = + (std::is_signed<T>::value != std::is_signed<U>::value); + + const T t = narrow_cast<T>(u); + + if (static_cast<U>(t) != u || (is_different_signedness && ((t < T{}) != (u < U{})))) + { + throw narrowing_error{}; + } + + return t; +} +} // namespace gsl +#endif // GSL_NARROW_H diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/gsl/pointers b/Plugins/CesiumForUnreal/Source/ThirdParty/include/gsl/pointers new file mode 100644 index 0000000000000000000000000000000000000000..2f1b15f24830e60333618e270c39274c9fbdff0b --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/gsl/pointers @@ -0,0 +1,316 @@ +/////////////////////////////////////////////////////////////////////////////// +// +// Copyright (c) 2015 Microsoft Corporation. All rights reserved. +// +// This code is licensed under the MIT License (MIT). +// +// 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 GSL_POINTERS_H +#define GSL_POINTERS_H + +#include <gsl/assert> // for Ensures, Expects + +#include <algorithm> // for forward +#include <cstddef> // for ptrdiff_t, nullptr_t, size_t +#include <memory> // for shared_ptr, unique_ptr +#include <system_error> // for hash +#include <type_traits> // for enable_if_t, is_convertible, is_assignable + +#if !defined(GSL_NO_IOSTREAMS) +#include <iosfwd> // for ostream +#endif // !defined(GSL_NO_IOSTREAMS) + +namespace gsl +{ + +namespace details +{ +template<typename T, typename = void> +struct is_comparable_to_nullptr : std::false_type {}; + +template <typename T> +struct is_comparable_to_nullptr<T, std::enable_if_t<std::is_convertible<decltype(std::declval<T>() != nullptr), bool>::value>> : std::true_type {}; +} // namespace details + +// +// GSL.owner: ownership pointers +// +using std::shared_ptr; +using std::unique_ptr; + +// +// owner +// +// owner<T> is designed as a bridge for code that must deal directly with owning pointers for some +// reason +// +// T must be a pointer type +// - disallow construction from any type other than pointer type +// +template <class T, class = std::enable_if_t<std::is_pointer<T>::value>> +using owner = T; + +// +// not_null +// +// Restricts a pointer or smart pointer to only hold non-null values. +// +// Has zero size overhead over T. +// +// If T is a pointer (i.e. T == U*) then +// - allow construction from U* +// - disallow construction from nullptr_t +// - disallow default construction +// - ensure construction from null U* fails +// - allow implicit conversion to U* +// +template <class T> +class not_null +{ +public: + static_assert(details::is_comparable_to_nullptr<T>::value, "T cannot be compared to nullptr."); + + template <typename U, typename = std::enable_if_t<std::is_convertible<U, T>::value>> + constexpr not_null(U&& u) : ptr_(std::forward<U>(u)) + { + Expects(ptr_ != nullptr); + } + + template <typename = std::enable_if_t<!std::is_same<std::nullptr_t, T>::value>> + constexpr not_null(T u) : ptr_(std::move(u)) + { + Expects(ptr_ != nullptr); + } + + template <typename U, typename = std::enable_if_t<std::is_convertible<U, T>::value>> + constexpr not_null(const not_null<U>& other) : not_null(other.get()) + {} + + not_null(const not_null& other) = default; + not_null& operator=(const not_null& other) = default; + constexpr std::conditional_t<std::is_copy_constructible<T>::value, T, const T&> get() const + { + Ensures(ptr_ != nullptr); + return ptr_; + } + + constexpr operator T() const { return get(); } + constexpr decltype(auto) operator->() const { return get(); } + constexpr decltype(auto) operator*() const { return *get(); } + + // prevents compilation when someone attempts to assign a null pointer constant + not_null(std::nullptr_t) = delete; + not_null& operator=(std::nullptr_t) = delete; + + // unwanted operators...pointers only point to single objects! + not_null& operator++() = delete; + not_null& operator--() = delete; + not_null operator++(int) = delete; + not_null operator--(int) = delete; + not_null& operator+=(std::ptrdiff_t) = delete; + not_null& operator-=(std::ptrdiff_t) = delete; + void operator[](std::ptrdiff_t) const = delete; + +private: + T ptr_; +}; + +template <class T> +auto make_not_null(T&& t) noexcept +{ + return not_null<std::remove_cv_t<std::remove_reference_t<T>>>{std::forward<T>(t)}; +} + +#if !defined(GSL_NO_IOSTREAMS) +template <class T> +std::ostream& operator<<(std::ostream& os, const not_null<T>& val) +{ + os << val.get(); + return os; +} +#endif // !defined(GSL_NO_IOSTREAMS) + +template <class T, class U> +auto operator==(const not_null<T>& lhs, + const not_null<U>& rhs) noexcept(noexcept(lhs.get() == rhs.get())) + -> decltype(lhs.get() == rhs.get()) +{ + return lhs.get() == rhs.get(); +} + +template <class T, class U> +auto operator!=(const not_null<T>& lhs, + const not_null<U>& rhs) noexcept(noexcept(lhs.get() != rhs.get())) + -> decltype(lhs.get() != rhs.get()) +{ + return lhs.get() != rhs.get(); +} + +template <class T, class U> +auto operator<(const not_null<T>& lhs, + const not_null<U>& rhs) noexcept(noexcept(lhs.get() < rhs.get())) + -> decltype(lhs.get() < rhs.get()) +{ + return lhs.get() < rhs.get(); +} + +template <class T, class U> +auto operator<=(const not_null<T>& lhs, + const not_null<U>& rhs) noexcept(noexcept(lhs.get() <= rhs.get())) + -> decltype(lhs.get() <= rhs.get()) +{ + return lhs.get() <= rhs.get(); +} + +template <class T, class U> +auto operator>(const not_null<T>& lhs, + const not_null<U>& rhs) noexcept(noexcept(lhs.get() > rhs.get())) + -> decltype(lhs.get() > rhs.get()) +{ + return lhs.get() > rhs.get(); +} + +template <class T, class U> +auto operator>=(const not_null<T>& lhs, + const not_null<U>& rhs) noexcept(noexcept(lhs.get() >= rhs.get())) + -> decltype(lhs.get() >= rhs.get()) +{ + return lhs.get() >= rhs.get(); +} + +// more unwanted operators +template <class T, class U> +std::ptrdiff_t operator-(const not_null<T>&, const not_null<U>&) = delete; +template <class T> +not_null<T> operator-(const not_null<T>&, std::ptrdiff_t) = delete; +template <class T> +not_null<T> operator+(const not_null<T>&, std::ptrdiff_t) = delete; +template <class T> +not_null<T> operator+(std::ptrdiff_t, const not_null<T>&) = delete; + +} // namespace gsl + +namespace std +{ +template <class T> +struct hash<gsl::not_null<T>> +{ + std::size_t operator()(const gsl::not_null<T>& value) const { return hash<T>{}(value.get()); } +}; + +} // namespace std + +namespace gsl +{ + +// +// strict_not_null +// +// Restricts a pointer or smart pointer to only hold non-null values, +// +// - provides a strict (i.e. explicit constructor from T) wrapper of not_null +// - to be used for new code that wishes the design to be cleaner and make not_null +// checks intentional, or in old code that would like to make the transition. +// +// To make the transition from not_null, incrementally replace not_null +// by strict_not_null and fix compilation errors +// +// Expect to +// - remove all unneeded conversions from raw pointer to not_null and back +// - make API clear by specifying not_null in parameters where needed +// - remove unnecessary asserts +// +template <class T> +class strict_not_null : public not_null<T> +{ +public: + template <typename U, typename = std::enable_if_t<std::is_convertible<U, T>::value>> + constexpr explicit strict_not_null(U&& u) : not_null<T>(std::forward<U>(u)) + {} + + template <typename = std::enable_if_t<!std::is_same<std::nullptr_t, T>::value>> + constexpr explicit strict_not_null(T u) : not_null<T>(u) + {} + + template <typename U, typename = std::enable_if_t<std::is_convertible<U, T>::value>> + constexpr strict_not_null(const not_null<U>& other) : not_null<T>(other) + {} + + template <typename U, typename = std::enable_if_t<std::is_convertible<U, T>::value>> + constexpr strict_not_null(const strict_not_null<U>& other) : not_null<T>(other) + {} + + strict_not_null(strict_not_null&& other) = default; + strict_not_null(const strict_not_null& other) = default; + strict_not_null& operator=(const strict_not_null& other) = default; + strict_not_null& operator=(const not_null<T>& other) + { + not_null<T>::operator=(other); + return *this; + } + + // prevents compilation when someone attempts to assign a null pointer constant + strict_not_null(std::nullptr_t) = delete; + strict_not_null& operator=(std::nullptr_t) = delete; + + // unwanted operators...pointers only point to single objects! + strict_not_null& operator++() = delete; + strict_not_null& operator--() = delete; + strict_not_null operator++(int) = delete; + strict_not_null operator--(int) = delete; + strict_not_null& operator+=(std::ptrdiff_t) = delete; + strict_not_null& operator-=(std::ptrdiff_t) = delete; + void operator[](std::ptrdiff_t) const = delete; +}; + +// more unwanted operators +template <class T, class U> +std::ptrdiff_t operator-(const strict_not_null<T>&, const strict_not_null<U>&) = delete; +template <class T> +strict_not_null<T> operator-(const strict_not_null<T>&, std::ptrdiff_t) = delete; +template <class T> +strict_not_null<T> operator+(const strict_not_null<T>&, std::ptrdiff_t) = delete; +template <class T> +strict_not_null<T> operator+(std::ptrdiff_t, const strict_not_null<T>&) = delete; + +template <class T> +auto make_strict_not_null(T&& t) noexcept +{ + return strict_not_null<std::remove_cv_t<std::remove_reference_t<T>>>{std::forward<T>(t)}; +} + +#if (defined(__cpp_deduction_guides) && (__cpp_deduction_guides >= 201611L)) + +// deduction guides to prevent the ctad-maybe-unsupported warning +template <class T> +not_null(T) -> not_null<T>; +template <class T> +strict_not_null(T) -> strict_not_null<T>; + +#endif // ( defined(__cpp_deduction_guides) && (__cpp_deduction_guides >= 201611L) ) + +} // namespace gsl + +namespace std +{ +template <class T> +struct hash<gsl::strict_not_null<T>> +{ + std::size_t operator()(const gsl::strict_not_null<T>& value) const + { + return hash<T>{}(value.get()); + } +}; + +} // namespace std + +#endif // GSL_POINTERS_H diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/gsl/span b/Plugins/CesiumForUnreal/Source/ThirdParty/include/gsl/span new file mode 100644 index 0000000000000000000000000000000000000000..506eb4cbc2f501a708842211e678a909e2b9986a --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/gsl/span @@ -0,0 +1,826 @@ +/////////////////////////////////////////////////////////////////////////////// +// +// Copyright (c) 2015 Microsoft Corporation. All rights reserved. +// +// This code is licensed under the MIT License (MIT). +// +// 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 GSL_SPAN_H +#define GSL_SPAN_H + +#include <gsl/assert> // for Expects +#include <gsl/byte> // for byte +#include <gsl/util> // for narrow_cast + +#include <array> // for array +#include <cstddef> // for ptrdiff_t, size_t, nullptr_t +#include <iterator> // for reverse_iterator, distance, random_access_... +#include <type_traits> // for enable_if_t, declval, is_convertible, inte... + +#if defined(_MSC_VER) && !defined(__clang__) +#pragma warning(push) + +// turn off some warnings that are noisy about our Expects statements +#pragma warning(disable : 4127) // conditional expression is constant +#pragma warning( \ + disable : 4146) // unary minus operator applied to unsigned type, result still unsigned +#pragma warning(disable : 4702) // unreachable code + +// Turn MSVC /analyze rules that generate too much noise. TODO: fix in the tool. +#pragma warning(disable : 26495) // uninitalized member when constructor calls constructor +#pragma warning(disable : 26446) // parser bug does not allow attributes on some templates + +#endif // _MSC_VER + +// See if we have enough C++17 power to use a static constexpr data member +// without needing an out-of-line definition +#if !(defined(__cplusplus) && (__cplusplus >= 201703L)) +#define GSL_USE_STATIC_CONSTEXPR_WORKAROUND +#endif // !(defined(__cplusplus) && (__cplusplus >= 201703L)) + +// GCC 7 does not like the signed unsigned missmatch (size_t ptrdiff_t) +// While there is a conversion from signed to unsigned, it happens at +// compiletime, so the compiler wouldn't have to warn indiscriminately, but +// could check if the source value actually doesn't fit into the target type +// and only warn in those cases. +#if defined(__GNUC__) && __GNUC__ > 6 +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wsign-conversion" +#endif + +namespace gsl +{ + +// [views.constants], constants +constexpr const std::size_t dynamic_extent = narrow_cast<std::size_t>(-1); + +template <class ElementType, std::size_t Extent = dynamic_extent> +class span; + +// implementation details +namespace details +{ + template <class T> + struct is_span_oracle : std::false_type + { + }; + + template <class ElementType, std::size_t Extent> + struct is_span_oracle<gsl::span<ElementType, Extent>> : std::true_type + { + }; + + template <class T> + struct is_span : public is_span_oracle<std::remove_cv_t<T>> + { + }; + + template <class T> + struct is_std_array_oracle : std::false_type + { + }; + + template <class ElementType, std::size_t Extent> + struct is_std_array_oracle<std::array<ElementType, Extent>> : std::true_type + { + }; + + template <class T> + struct is_std_array : is_std_array_oracle<std::remove_cv_t<T>> + { + }; + + template <std::size_t From, std::size_t To> + struct is_allowed_extent_conversion + : std::integral_constant<bool, From == To || To == dynamic_extent> + { + }; + + template <class From, class To> + struct is_allowed_element_type_conversion + : std::integral_constant<bool, std::is_convertible<From (*)[], To (*)[]>::value> + { + }; + + template <class Type> + class span_iterator + { + public: + using iterator_category = std::random_access_iterator_tag; + using value_type = std::remove_cv_t<Type>; + using difference_type = std::ptrdiff_t; + using pointer = Type*; + using reference = Type&; + +#ifdef _MSC_VER + using _Unchecked_type = pointer; +#endif // _MSC_VER + constexpr span_iterator() = default; + + constexpr span_iterator(pointer begin, pointer end, pointer current) + : begin_(begin), end_(end), current_(current) + {} + + constexpr operator span_iterator<const Type>() const noexcept + { + return {begin_, end_, current_}; + } + + constexpr reference operator*() const noexcept + { + Expects(begin_ && end_); + Expects(begin_ <= current_ && current_ < end_); + return *current_; + } + + constexpr pointer operator->() const noexcept + { + Expects(begin_ && end_); + Expects(begin_ <= current_ && current_ < end_); + return current_; + } + constexpr span_iterator& operator++() noexcept + { + Expects(begin_ && current_ && end_); + Expects(current_ < end_); + // clang-format off + GSL_SUPPRESS(bounds.1) // NO-FORMAT: attribute + // clang-format on + ++current_; + return *this; + } + + constexpr span_iterator operator++(int) noexcept + { + span_iterator ret = *this; + ++*this; + return ret; + } + + constexpr span_iterator& operator--() noexcept + { + Expects(begin_ && end_); + Expects(begin_ < current_); + --current_; + return *this; + } + + constexpr span_iterator operator--(int) noexcept + { + span_iterator ret = *this; + --*this; + return ret; + } + + constexpr span_iterator& operator+=(const difference_type n) noexcept + { + if (n != 0) Expects(begin_ && current_ && end_); + if (n > 0) Expects(end_ - current_ >= n); + if (n < 0) Expects(current_ - begin_ >= -n); + // clang-format off + GSL_SUPPRESS(bounds.1) // NO-FORMAT: attribute + // clang-format on + current_ += n; + return *this; + } + + constexpr span_iterator operator+(const difference_type n) const noexcept + { + span_iterator ret = *this; + ret += n; + return ret; + } + + friend constexpr span_iterator operator+(const difference_type n, + const span_iterator& rhs) noexcept + { + return rhs + n; + } + + constexpr span_iterator& operator-=(const difference_type n) noexcept + { + if (n != 0) Expects(begin_ && current_ && end_); + if (n > 0) Expects(current_ - begin_ >= n); + if (n < 0) Expects(end_ - current_ >= -n); + current_ -= n; + return *this; + } + + constexpr span_iterator operator-(const difference_type n) const noexcept + { + span_iterator ret = *this; + ret -= n; + return ret; + } + + template < + class Type2, + std::enable_if_t<std::is_same<std::remove_cv_t<Type2>, value_type>::value, int> = 0> + constexpr difference_type operator-(const span_iterator<Type2>& rhs) const noexcept + { + Expects(begin_ == rhs.begin_ && end_ == rhs.end_); + return current_ - rhs.current_; + } + + constexpr reference operator[](const difference_type n) const noexcept + { + return *(*this + n); + } + + template < + class Type2, + std::enable_if_t<std::is_same<std::remove_cv_t<Type2>, value_type>::value, int> = 0> + constexpr bool operator==(const span_iterator<Type2>& rhs) const noexcept + { + Expects(begin_ == rhs.begin_ && end_ == rhs.end_); + return current_ == rhs.current_; + } + + template < + class Type2, + std::enable_if_t<std::is_same<std::remove_cv_t<Type2>, value_type>::value, int> = 0> + constexpr bool operator!=(const span_iterator<Type2>& rhs) const noexcept + { + return !(*this == rhs); + } + + template < + class Type2, + std::enable_if_t<std::is_same<std::remove_cv_t<Type2>, value_type>::value, int> = 0> + constexpr bool operator<(const span_iterator<Type2>& rhs) const noexcept + { + Expects(begin_ == rhs.begin_ && end_ == rhs.end_); + return current_ < rhs.current_; + } + + template < + class Type2, + std::enable_if_t<std::is_same<std::remove_cv_t<Type2>, value_type>::value, int> = 0> + constexpr bool operator>(const span_iterator<Type2>& rhs) const noexcept + { + return rhs < *this; + } + + template < + class Type2, + std::enable_if_t<std::is_same<std::remove_cv_t<Type2>, value_type>::value, int> = 0> + constexpr bool operator<=(const span_iterator<Type2>& rhs) const noexcept + { + return !(rhs < *this); + } + + template < + class Type2, + std::enable_if_t<std::is_same<std::remove_cv_t<Type2>, value_type>::value, int> = 0> + constexpr bool operator>=(const span_iterator<Type2>& rhs) const noexcept + { + return !(*this < rhs); + } + +#ifdef _MSC_VER + // MSVC++ iterator debugging support; allows STL algorithms in 15.8+ + // to unwrap span_iterator to a pointer type after a range check in STL + // algorithm calls + friend constexpr void _Verify_range(span_iterator lhs, span_iterator rhs) noexcept + { // test that [lhs, rhs) forms a valid range inside an STL algorithm + Expects(lhs.begin_ == rhs.begin_ // range spans have to match + && lhs.end_ == rhs.end_ && + lhs.current_ <= rhs.current_); // range must not be transposed + } + + constexpr void _Verify_offset(const difference_type n) const noexcept + { // test that *this + n is within the range of this call + if (n != 0) Expects(begin_ && current_ && end_); + if (n > 0) Expects(end_ - current_ >= n); + if (n < 0) Expects(current_ - begin_ >= -n); + } + + // clang-format off + GSL_SUPPRESS(bounds.1) // NO-FORMAT: attribute + // clang-format on + constexpr pointer _Unwrapped() const noexcept + { // after seeking *this to a high water mark, or using one of the + // _Verify_xxx functions above, unwrap this span_iterator to a raw + // pointer + return current_; + } + + // Tell the STL that span_iterator should not be unwrapped if it can't + // validate in advance, even in release / optimized builds: +#if defined(GSL_USE_STATIC_CONSTEXPR_WORKAROUND) + static constexpr const bool _Unwrap_when_unverified = false; +#else + static constexpr bool _Unwrap_when_unverified = false; +#endif + // clang-format off + GSL_SUPPRESS(con.3) // NO-FORMAT: attribute // TODO: false positive + // clang-format on + constexpr void _Seek_to(const pointer p) noexcept + { // adjust the position of *this to previously verified location p + // after _Unwrapped + current_ = p; + } +#endif + + pointer begin_ = nullptr; + pointer end_ = nullptr; + pointer current_ = nullptr; + }; + + template <std::size_t Ext> + class extent_type + { + public: + using size_type = std::size_t; + + constexpr extent_type() noexcept = default; + + constexpr explicit extent_type(extent_type<dynamic_extent>); + + constexpr explicit extent_type(size_type size) { Expects(size == Ext); } + + constexpr size_type size() const noexcept { return Ext; } + + private: +#if defined(GSL_USE_STATIC_CONSTEXPR_WORKAROUND) + static constexpr const size_type size_ = Ext; // static size equal to Ext +#else + static constexpr size_type size_ = Ext; // static size equal to Ext +#endif + }; + + template <> + class extent_type<dynamic_extent> + { + public: + using size_type = std::size_t; + + template <size_type Other> + constexpr explicit extent_type(extent_type<Other> ext) : size_(ext.size()) + {} + + constexpr explicit extent_type(size_type size) : size_(size) + { + Expects(size != dynamic_extent); + } + + constexpr size_type size() const noexcept { return size_; } + + private: + size_type size_; + }; + + template <std::size_t Ext> + constexpr extent_type<Ext>::extent_type(extent_type<dynamic_extent> ext) + { + Expects(ext.size() == Ext); + } + + template <class ElementType, std::size_t Extent, std::size_t Offset, std::size_t Count> + struct calculate_subspan_type + { + using type = span<ElementType, Count != dynamic_extent + ? Count + : (Extent != dynamic_extent ? Extent - Offset : Extent)>; + }; +} // namespace details + +// [span], class template span +template <class ElementType, std::size_t Extent> +class span +{ +public: + // constants and types + using element_type = ElementType; + using value_type = std::remove_cv_t<ElementType>; + using size_type = std::size_t; + using pointer = element_type*; + using const_pointer = const element_type*; + using reference = element_type&; + using const_reference = const element_type&; + using difference_type = std::ptrdiff_t; + + using iterator = details::span_iterator<ElementType>; + using reverse_iterator = std::reverse_iterator<iterator>; + +#if defined(GSL_USE_STATIC_CONSTEXPR_WORKAROUND) + static constexpr const size_type extent{Extent}; +#else + static constexpr size_type extent{Extent}; +#endif + + // [span.cons], span constructors, copy, assignment, and destructor + template <bool Dependent = false, + // "Dependent" is needed to make "std::enable_if_t<Dependent || Extent == 0 || Extent + // == dynamic_extent>" SFINAE, since "std::enable_if_t<Extent == 0 || Extent == + // dynamic_extent>" is ill-formed when Extent is greater than 0. + class = std::enable_if_t<(Dependent || + details::is_allowed_extent_conversion<0, Extent>::value)>> + constexpr span() noexcept : storage_(nullptr, details::extent_type<0>()) + {} + + template <std::size_t MyExtent = Extent, std::enable_if_t<MyExtent != dynamic_extent, int> = 0> + constexpr explicit span(pointer ptr, size_type count) noexcept : storage_(ptr, count) + { + Expects(count == Extent); + } + + template <std::size_t MyExtent = Extent, std::enable_if_t<MyExtent == dynamic_extent, int> = 0> + constexpr span(pointer ptr, size_type count) noexcept : storage_(ptr, count) + {} + + template <std::size_t MyExtent = Extent, std::enable_if_t<MyExtent != dynamic_extent, int> = 0> + constexpr explicit span(pointer firstElem, pointer lastElem) noexcept + : storage_(firstElem, narrow_cast<std::size_t>(lastElem - firstElem)) + { + Expects(lastElem - firstElem == static_cast<difference_type>(Extent)); + } + + template <std::size_t MyExtent = Extent, std::enable_if_t<MyExtent == dynamic_extent, int> = 0> + constexpr span(pointer firstElem, pointer lastElem) noexcept + : storage_(firstElem, narrow_cast<std::size_t>(lastElem - firstElem)) + {} + + template <std::size_t N, + std::enable_if_t<details::is_allowed_extent_conversion<N, Extent>::value, int> = 0> + constexpr span(element_type (&arr)[N]) noexcept + : storage_(KnownNotNull{arr}, details::extent_type<N>()) + {} + + template < + class T, std::size_t N, + std::enable_if_t<(details::is_allowed_extent_conversion<N, Extent>::value && + details::is_allowed_element_type_conversion<T, element_type>::value), + int> = 0> + constexpr span(std::array<T, N>& arr) noexcept + : storage_(KnownNotNull{arr.data()}, details::extent_type<N>()) + {} + + template <class T, std::size_t N, + std::enable_if_t< + (details::is_allowed_extent_conversion<N, Extent>::value && + details::is_allowed_element_type_conversion<const T, element_type>::value), + int> = 0> + constexpr span(const std::array<T, N>& arr) noexcept + : storage_(KnownNotNull{arr.data()}, details::extent_type<N>()) + {} + + // NB: the SFINAE on these constructors uses .data() as an incomplete/imperfect proxy for the + // requirement on Container to be a contiguous sequence container. + template <std::size_t MyExtent = Extent, class Container, + std::enable_if_t< + MyExtent != dynamic_extent && !details::is_span<Container>::value && + !details::is_std_array<Container>::value && + std::is_pointer<decltype(std::declval<Container&>().data())>::value && + std::is_convertible< + std::remove_pointer_t<decltype(std::declval<Container&>().data())> (*)[], + element_type (*)[]>::value, + int> = 0> + constexpr explicit span(Container& cont) noexcept : span(cont.data(), cont.size()) + {} + + template <std::size_t MyExtent = Extent, class Container, + std::enable_if_t< + MyExtent == dynamic_extent && !details::is_span<Container>::value && + !details::is_std_array<Container>::value && + std::is_pointer<decltype(std::declval<Container&>().data())>::value && + std::is_convertible< + std::remove_pointer_t<decltype(std::declval<Container&>().data())> (*)[], + element_type (*)[]>::value, + int> = 0> + constexpr span(Container& cont) noexcept : span(cont.data(), cont.size()) + {} + + template < + std::size_t MyExtent = Extent, class Container, + std::enable_if_t< + MyExtent != dynamic_extent && std::is_const<element_type>::value && + !details::is_span<Container>::value && !details::is_std_array<Container>::value && + std::is_pointer<decltype(std::declval<const Container&>().data())>::value && + std::is_convertible< + std::remove_pointer_t<decltype(std::declval<const Container&>().data())> (*)[], + element_type (*)[]>::value, + int> = 0> + constexpr explicit span(const Container& cont) noexcept : span(cont.data(), cont.size()) + {} + + template < + std::size_t MyExtent = Extent, class Container, + std::enable_if_t< + MyExtent == dynamic_extent && std::is_const<element_type>::value && + !details::is_span<Container>::value && !details::is_std_array<Container>::value && + std::is_pointer<decltype(std::declval<const Container&>().data())>::value && + std::is_convertible< + std::remove_pointer_t<decltype(std::declval<const Container&>().data())> (*)[], + element_type (*)[]>::value, + int> = 0> + constexpr span(const Container& cont) noexcept : span(cont.data(), cont.size()) + {} + + constexpr span(const span& other) noexcept = default; + + template <class OtherElementType, std::size_t OtherExtent, std::size_t MyExtent = Extent, + std::enable_if_t<(MyExtent == dynamic_extent || MyExtent == OtherExtent) && + details::is_allowed_element_type_conversion<OtherElementType, + element_type>::value, + int> = 0> + constexpr span(const span<OtherElementType, OtherExtent>& other) noexcept + : storage_(other.data(), details::extent_type<OtherExtent>(other.size())) + {} + + template <class OtherElementType, std::size_t OtherExtent, std::size_t MyExtent = Extent, + std::enable_if_t<MyExtent != dynamic_extent && OtherExtent == dynamic_extent && + details::is_allowed_element_type_conversion<OtherElementType, + element_type>::value, + int> = 0> + constexpr explicit span(const span<OtherElementType, OtherExtent>& other) noexcept + : storage_(other.data(), details::extent_type<OtherExtent>(other.size())) + {} + + ~span() noexcept = default; + constexpr span& operator=(const span& other) noexcept = default; + + // [span.sub], span subviews + template <std::size_t Count> + constexpr span<element_type, Count> first() const noexcept + { + Expects(Count <= size()); + return span<element_type, Count>{data(), Count}; + } + + template <std::size_t Count> + // clang-format off + GSL_SUPPRESS(bounds.1) // NO-FORMAT: attribute + // clang-format on + constexpr span<element_type, Count> last() const noexcept + { + Expects(Count <= size()); + return span<element_type, Count>{data() + (size() - Count), Count}; + } + + template <std::size_t Offset, std::size_t Count = dynamic_extent> + // clang-format off + GSL_SUPPRESS(bounds.1) // NO-FORMAT: attribute + // clang-format on + constexpr auto subspan() const noexcept -> + typename details::calculate_subspan_type<ElementType, Extent, Offset, Count>::type + { + Expects((size() >= Offset) && (Count == dynamic_extent || (Count <= size() - Offset))); + using type = + typename details::calculate_subspan_type<ElementType, Extent, Offset, Count>::type; + return type{data() + Offset, Count == dynamic_extent ? size() - Offset : Count}; + } + + constexpr span<element_type, dynamic_extent> first(size_type count) const noexcept + { + Expects(count <= size()); + return {data(), count}; + } + + constexpr span<element_type, dynamic_extent> last(size_type count) const noexcept + { + Expects(count <= size()); + return make_subspan(size() - count, dynamic_extent, subspan_selector<Extent>{}); + } + + constexpr span<element_type, dynamic_extent> + subspan(size_type offset, size_type count = dynamic_extent) const noexcept + { + return make_subspan(offset, count, subspan_selector<Extent>{}); + } + + // [span.obs], span observers + constexpr size_type size() const noexcept { return storage_.size(); } + + constexpr size_type size_bytes() const noexcept + { + Expects(size() < dynamic_extent / sizeof(element_type)); + return size() * sizeof(element_type); + } + + constexpr bool empty() const noexcept { return size() == 0; } + + // [span.elem], span element access + // clang-format off + GSL_SUPPRESS(bounds.1) // NO-FORMAT: attribute + // clang-format on + constexpr reference operator[](size_type idx) const noexcept + { + Expects(idx < size()); + return data()[idx]; + } + + constexpr reference front() const noexcept + { + Expects(size() > 0); + return data()[0]; + } + + constexpr reference back() const noexcept + { + Expects(size() > 0); + return data()[size() - 1]; + } + + constexpr pointer data() const noexcept { return storage_.data(); } + + // [span.iter], span iterator support + constexpr iterator begin() const noexcept + { + const auto data = storage_.data(); + // clang-format off + GSL_SUPPRESS(bounds.1) // NO-FORMAT: attribute + // clang-format on + return {data, data + size(), data}; + } + + constexpr iterator end() const noexcept + { + const auto data = storage_.data(); + // clang-format off + GSL_SUPPRESS(bounds.1) // NO-FORMAT: attribute + // clang-format on + const auto endData = data + storage_.size(); + return {data, endData, endData}; + } + + constexpr reverse_iterator rbegin() const noexcept { return reverse_iterator{end()}; } + constexpr reverse_iterator rend() const noexcept { return reverse_iterator{begin()}; } + +#ifdef _MSC_VER + // Tell MSVC how to unwrap spans in range-based-for + constexpr pointer _Unchecked_begin() const noexcept { return data(); } + constexpr pointer _Unchecked_end() const noexcept + { + // clang-format off + GSL_SUPPRESS(bounds.1) // NO-FORMAT: attribute + // clang-format on + return data() + size(); + } +#endif // _MSC_VER + +private: + // Needed to remove unnecessary null check in subspans + struct KnownNotNull + { + pointer p; + }; + + // this implementation detail class lets us take advantage of the + // empty base class optimization to pay for only storage of a single + // pointer in the case of fixed-size spans + template <class ExtentType> + class storage_type : public ExtentType + { + public: + // KnownNotNull parameter is needed to remove unnecessary null check + // in subspans and constructors from arrays + template <class OtherExtentType> + constexpr storage_type(KnownNotNull data, OtherExtentType ext) + : ExtentType(ext), data_(data.p) + { + Expects(ExtentType::size() != dynamic_extent); + } + + template <class OtherExtentType> + constexpr storage_type(pointer data, OtherExtentType ext) : ExtentType(ext), data_(data) + { + Expects(ExtentType::size() != dynamic_extent); + Expects(data || ExtentType::size() == 0); + } + + constexpr pointer data() const noexcept { return data_; } + + private: + pointer data_; + }; + + storage_type<details::extent_type<Extent>> storage_; + + // The rest is needed to remove unnecessary null check + // in subspans and constructors from arrays + constexpr span(KnownNotNull ptr, size_type count) noexcept : storage_(ptr, count) {} + + template <std::size_t CallerExtent> + class subspan_selector + { + }; + + template <std::size_t CallerExtent> + constexpr span<element_type, dynamic_extent> + make_subspan(size_type offset, size_type count, subspan_selector<CallerExtent>) const noexcept + { + const span<element_type, dynamic_extent> tmp(*this); + return tmp.subspan(offset, count); + } + + // clang-format off + GSL_SUPPRESS(bounds.1) // NO-FORMAT: attribute + // clang-format on + constexpr span<element_type, dynamic_extent> + make_subspan(size_type offset, size_type count, subspan_selector<dynamic_extent>) const noexcept + { + Expects(size() >= offset); + + if (count == dynamic_extent) { return {KnownNotNull{data() + offset}, size() - offset}; } + + Expects(size() - offset >= count); + return {KnownNotNull{data() + offset}, count}; + } +}; + +#if (defined(__cpp_deduction_guides) && (__cpp_deduction_guides >= 201611L)) + +// Deduction Guides +template <class Type, std::size_t Extent> +span(Type (&)[Extent]) -> span<Type, Extent>; + +template <class Type, std::size_t Size> +span(std::array<Type, Size>&) -> span<Type, Size>; + +template <class Type, std::size_t Size> +span(const std::array<Type, Size>&) -> span<const Type, Size>; + +template <class Container, + class Element = std::remove_pointer_t<decltype(std::declval<Container&>().data())>> +span(Container&) -> span<Element>; + +template <class Container, + class Element = std::remove_pointer_t<decltype(std::declval<const Container&>().data())>> +span(const Container&) -> span<Element>; + +#endif // ( defined(__cpp_deduction_guides) && (__cpp_deduction_guides >= 201611L) ) + +#if defined(GSL_USE_STATIC_CONSTEXPR_WORKAROUND) +template <class ElementType, std::size_t Extent> +constexpr const typename span<ElementType, Extent>::size_type span<ElementType, Extent>::extent; +#endif + +namespace details +{ + // if we only supported compilers with good constexpr support then + // this pair of classes could collapse down to a constexpr function + + // we should use a narrow_cast<> to go to std::size_t, but older compilers may not see it as + // constexpr + // and so will fail compilation of the template + template <class ElementType, std::size_t Extent> + struct calculate_byte_size : std::integral_constant<std::size_t, sizeof(ElementType) * Extent> + { + static_assert(Extent < dynamic_extent / sizeof(ElementType), "Size is too big."); + }; + + template <class ElementType> + struct calculate_byte_size<ElementType, dynamic_extent> + : std::integral_constant<std::size_t, dynamic_extent> + { + }; +} // namespace details + +// [span.objectrep], views of object representation +template <class ElementType, std::size_t Extent> +span<const byte, details::calculate_byte_size<ElementType, Extent>::value> +as_bytes(span<ElementType, Extent> s) noexcept +{ + using type = span<const byte, details::calculate_byte_size<ElementType, Extent>::value>; + + // clang-format off + GSL_SUPPRESS(type.1) // NO-FORMAT: attribute + // clang-format on + return type{reinterpret_cast<const byte*>(s.data()), s.size_bytes()}; +} + +template <class ElementType, std::size_t Extent, + std::enable_if_t<!std::is_const<ElementType>::value, int> = 0> +span<byte, details::calculate_byte_size<ElementType, Extent>::value> +as_writable_bytes(span<ElementType, Extent> s) noexcept +{ + using type = span<byte, details::calculate_byte_size<ElementType, Extent>::value>; + + // clang-format off + GSL_SUPPRESS(type.1) // NO-FORMAT: attribute + // clang-format on + return type{reinterpret_cast<byte*>(s.data()), s.size_bytes()}; +} + +} // namespace gsl + +#if defined(_MSC_VER) && !defined(__clang__) + +#pragma warning(pop) +#endif // _MSC_VER + +#if defined(__GNUC__) && __GNUC__ > 6 +#pragma GCC diagnostic pop +#endif // __GNUC__ > 6 + +#endif // GSL_SPAN_H diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/gsl/span_ext b/Plugins/CesiumForUnreal/Source/ThirdParty/include/gsl/span_ext new file mode 100644 index 0000000000000000000000000000000000000000..13b171df7e3f95829100d7fc256f2fadcaa054bc --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/gsl/span_ext @@ -0,0 +1,197 @@ +/////////////////////////////////////////////////////////////////////////////// +// +// Copyright (c) 2015 Microsoft Corporation. All rights reserved. +// +// This code is licensed under the MIT License (MIT). +// +// 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 GSL_SPAN_EXT_H +#define GSL_SPAN_EXT_H + +/////////////////////////////////////////////////////////////////////////////// +// +// File: span_ext +// Purpose: continue offering features that have been cut from the official +// implementation of span. +// While modernizing gsl::span a number of features needed to be removed to +// be compliant with the design of std::span +// +/////////////////////////////////////////////////////////////////////////////// + +#include <gsl/span> // for span +#include <gsl/util> // for narrow_cast, narrow + +#include <algorithm> // for lexicographical_compare +#include <cstddef> // for ptrdiff_t, size_t +#include <utility> + +namespace gsl +{ + +// [span.comparison], span comparison operators +template <class ElementType, std::size_t FirstExtent, std::size_t SecondExtent> +constexpr bool operator==(span<ElementType, FirstExtent> l, span<ElementType, SecondExtent> r) +{ + return std::equal(l.begin(), l.end(), r.begin(), r.end()); +} + +template <class ElementType, std::size_t Extent> +constexpr bool operator!=(span<ElementType, Extent> l, span<ElementType, Extent> r) +{ + return !(l == r); +} + +template <class ElementType, std::size_t Extent> +constexpr bool operator<(span<ElementType, Extent> l, span<ElementType, Extent> r) +{ + return std::lexicographical_compare(l.begin(), l.end(), r.begin(), r.end()); +} + +template <class ElementType, std::size_t Extent> +constexpr bool operator<=(span<ElementType, Extent> l, span<ElementType, Extent> r) +{ + return !(l > r); +} + +template <class ElementType, std::size_t Extent> +constexpr bool operator>(span<ElementType, Extent> l, span<ElementType, Extent> r) +{ + return r < l; +} + +template <class ElementType, std::size_t Extent> +constexpr bool operator>=(span<ElementType, Extent> l, span<ElementType, Extent> r) +{ + return !(l < r); +} + +// +// make_span() - Utility functions for creating spans +// +template <class ElementType> +constexpr span<ElementType> make_span(ElementType* ptr, typename span<ElementType>::size_type count) +{ + return span<ElementType>(ptr, count); +} + +template <class ElementType> +constexpr span<ElementType> make_span(ElementType* firstElem, ElementType* lastElem) +{ + return span<ElementType>(firstElem, lastElem); +} + +template <class ElementType, std::size_t N> +constexpr span<ElementType, N> make_span(ElementType (&arr)[N]) noexcept +{ + return span<ElementType, N>(arr); +} + +template <class Container> +constexpr span<typename Container::value_type> make_span(Container& cont) +{ + return span<typename Container::value_type>(cont); +} + +template <class Container> +constexpr span<const typename Container::value_type> make_span(const Container& cont) +{ + return span<const typename Container::value_type>(cont); +} + +template <class Ptr> +constexpr span<typename Ptr::element_type> make_span(Ptr& cont, std::size_t count) +{ + return span<typename Ptr::element_type>(cont, count); +} + +template <class Ptr> +constexpr span<typename Ptr::element_type> make_span(Ptr& cont) +{ + return span<typename Ptr::element_type>(cont); +} + +// Specialization of gsl::at for span +template <class ElementType, std::size_t Extent> +constexpr ElementType& at(span<ElementType, Extent> s, index i) +{ + // No bounds checking here because it is done in span::operator[] called below + Ensures(i >= 0); + return s[narrow_cast<std::size_t>(i)]; +} + +// [span.obs] Free observer functions +template <class ElementType, std::size_t Extent> +constexpr std::ptrdiff_t ssize(const span<ElementType, Extent>& s) noexcept +{ + return static_cast<std::ptrdiff_t>(s.size()); +} + +// [span.iter] Free functions for begin/end functions +template <class ElementType, std::size_t Extent> +constexpr typename span<ElementType, Extent>::iterator +begin(const span<ElementType, Extent>& s) noexcept +{ + return s.begin(); +} + +template <class ElementType, std::size_t Extent = dynamic_extent> +constexpr typename span<ElementType, Extent>::iterator +end(const span<ElementType, Extent>& s) noexcept +{ + return s.end(); +} + +template <class ElementType, std::size_t Extent> +constexpr typename span<ElementType, Extent>::reverse_iterator +rbegin(const span<ElementType, Extent>& s) noexcept +{ + return s.rbegin(); +} + +template <class ElementType, std::size_t Extent> +constexpr typename span<ElementType, Extent>::reverse_iterator +rend(const span<ElementType, Extent>& s) noexcept +{ + return s.rend(); +} + +template <class ElementType, std::size_t Extent> +constexpr typename span<ElementType, Extent>::iterator +cbegin(const span<ElementType, Extent>& s) noexcept +{ + return s.begin(); +} + +template <class ElementType, std::size_t Extent = dynamic_extent> +constexpr typename span<ElementType, Extent>::iterator +cend(const span<ElementType, Extent>& s) noexcept +{ + return s.end(); +} + +template <class ElementType, std::size_t Extent> +constexpr typename span<ElementType, Extent>::reverse_iterator +crbegin(const span<ElementType, Extent>& s) noexcept +{ + return s.rbegin(); +} + +template <class ElementType, std::size_t Extent> +constexpr typename span<ElementType, Extent>::reverse_iterator +crend(const span<ElementType, Extent>& s) noexcept +{ + return s.rend(); +} + +} // namespace gsl + +#endif // GSL_SPAN_EXT_H diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/gsl/string_span b/Plugins/CesiumForUnreal/Source/ThirdParty/include/gsl/string_span new file mode 100644 index 0000000000000000000000000000000000000000..d74f82d667ce53f1ee0164781f3bbff5f4cb6dc0 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/gsl/string_span @@ -0,0 +1,767 @@ +/////////////////////////////////////////////////////////////////////////////// +// +// Copyright (c) 2015 Microsoft Corporation. All rights reserved. +// +// This code is licensed under the MIT License (MIT). +// +// 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 GSL_STRING_SPAN_H +#define GSL_STRING_SPAN_H + +#include <gsl/assert> // for Ensures, Expects +#include <gsl/span_ext> // for operator!=, operator==, dynamic_extent +#include <gsl/util> // for narrow_cast + +#include <algorithm> // for equal, lexicographical_compare +#include <array> // for array +#include <cstddef> // for size_t, nullptr_t +#include <cstdint> // for PTRDIFF_MAX +#include <cstring> +#include <string> // for basic_string, allocator, char_traits +#include <type_traits> // for declval, is_convertible, enable_if_t, add_... + +#if defined(_MSC_VER) && !defined(__clang__) +#pragma warning(push) + +// Turn MSVC /analyze rules that generate too much noise. TODO: fix in the tool. +#pragma warning(disable : 26446) // TODO: bug in parser - attributes and templates +#pragma warning(disable : 26481) // TODO: suppress does not work inside templates sometimes +#pragma warning(disable : 4996) // use of functions & classes marked [[deprecated]] +#endif // _MSC_VER + +#if defined(__GNUC__) || defined(__clang__) +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wdeprecated-declarations" +#endif + +namespace gsl +{ +// +// czstring and wzstring +// +// These are "tag" typedefs for C-style strings (i.e. null-terminated character arrays) +// that allow static analysis to help find bugs. +// +// There are no additional features/semantics that we can find a way to add inside the +// type system for these types that will not either incur significant runtime costs or +// (sometimes needlessly) break existing programs when introduced. +// + +template <typename CharT, std::size_t Extent = dynamic_extent> +using basic_zstring = CharT*; + +template <std::size_t Extent = dynamic_extent> +using czstring = basic_zstring<const char, Extent>; + +template <std::size_t Extent = dynamic_extent> +using cwzstring = basic_zstring<const wchar_t, Extent>; + +template <std::size_t Extent = dynamic_extent> +using cu16zstring = basic_zstring<const char16_t, Extent>; + +template <std::size_t Extent = dynamic_extent> +using cu32zstring = basic_zstring<const char32_t, Extent>; + +template <std::size_t Extent = dynamic_extent> +using zstring = basic_zstring<char, Extent>; + +template <std::size_t Extent = dynamic_extent> +using wzstring = basic_zstring<wchar_t, Extent>; + +template <std::size_t Extent = dynamic_extent> +using u16zstring = basic_zstring<char16_t, Extent>; + +template <std::size_t Extent = dynamic_extent> +using u32zstring = basic_zstring<char32_t, Extent>; + +namespace details +{ + template <class CharT> + [[deprecated("string_span was removed from the C++ Core Guidelines. For more information, see " + "isocpp/CppCoreGuidelines PR#1680")]] constexpr std::size_t + string_length(const CharT* str, std::size_t n) + { + if (str == nullptr || n == dynamic_extent) return 0; + + const span<const CharT> str_span{str, n}; + + std::size_t len = 0; + while (len < n && str_span[len]) len++; + + return len; + } +} // namespace details + +// +// ensure_sentinel() +// +// Provides a way to obtain an span from a contiguous sequence +// that ends with a (non-inclusive) sentinel value. +// +// Will fail-fast if sentinel cannot be found before max elements are examined. +// +template <typename T, const T Sentinel> +[[deprecated("string_span was removed from the C++ Core Guidelines. For more information, see " + "isocpp/CppCoreGuidelines PR#1680")]] constexpr span<T, dynamic_extent> +ensure_sentinel(T* seq, std::size_t max = static_cast<std::size_t>(-1)) +{ + Ensures(seq != nullptr); + + // clang-format off + GSL_SUPPRESS(f.23) // TODO: false positive // TODO: suppress does not work + // clang-format on + auto cur = seq; + Ensures(cur != nullptr); // workaround for removing the warning + + // clang-format off + GSL_SUPPRESS(bounds.1) // TODO: suppress does not work + // clang-format on + while (static_cast<std::size_t>(cur - seq) < max && *cur != Sentinel) ++cur; + Ensures(*cur == Sentinel); + return {seq, static_cast<std::size_t>(cur - seq)}; +} + +// +// ensure_z - creates a span for a zero terminated strings. The span will not contain the zero +// termination. Will fail fast if a null-terminator cannot be found before the limit of size_type. +// +template <typename CharT> +[[deprecated("string_span was removed from the C++ Core Guidelines. For more information, see " + "isocpp/CppCoreGuidelines PR#1680")]] constexpr span<CharT, dynamic_extent> +ensure_z(CharT* const& sz, std::size_t max = static_cast<std::size_t>(-1)) +{ + return ensure_sentinel<CharT, CharT(0)>(sz, max); +} + +template <typename CharT, std::size_t N> +constexpr span<CharT, dynamic_extent> ensure_z(CharT (&sz)[N]) +{ + return ensure_z(&sz[0], N); +} + +template <class Cont> +[[deprecated( + "string_span was removed from the C++ Core Guidelines. For more information, see " + "isocpp/CppCoreGuidelines PR#1680")]] constexpr span<typename std:: + remove_pointer< + typename Cont::pointer>::type, + dynamic_extent> +ensure_z(Cont& cont) +{ + return ensure_z(cont.data(), cont.size()); +} + +template <typename CharT, std::size_t> +class [[deprecated("string_span was removed from the C++ Core Guidelines. For more information, " + "see isocpp/CppCoreGuidelines PR#1680")]] basic_string_span; + +namespace details +{ + template <typename T> + struct [[deprecated( + "string_span was removed from the C++ Core Guidelines. For more information, " + "see isocpp/CppCoreGuidelines PR#1680")]] is_basic_string_span_oracle : std::false_type{}; + + template <typename CharT, std::size_t Extent> + struct [[deprecated( + "string_span was removed from the C++ Core Guidelines. For more information, see " + "isocpp/CppCoreGuidelines PR#1680")]] is_basic_string_span_oracle<basic_string_span<CharT, + Extent>> + : std::true_type{}; + + template <typename T> + struct [[deprecated("string_span was removed from the C++ Core Guidelines. For more " + "information, see isocpp/CppCoreGuidelines PR#1680")]] is_basic_string_span + : is_basic_string_span_oracle<std::remove_cv_t<T>>{}; +} // namespace details + +// +// string_span and relatives +// +template <typename CharT, std::size_t Extent = dynamic_extent> +class [[deprecated("string_span was removed from the C++ Core Guidelines. For more information, " + "see isocpp/CppCoreGuidelines PR#1680")]] basic_string_span +{ +public: + using element_type = CharT; + using value_type = std::remove_cv_t<element_type>; + using pointer = std::add_pointer_t<element_type>; + using reference = std::add_lvalue_reference_t<element_type>; + using const_reference = std::add_lvalue_reference_t<std::add_const_t<element_type>>; + using impl_type = span<element_type, Extent>; + + using size_type = typename impl_type::size_type; + using iterator = typename impl_type::iterator; + using reverse_iterator = typename impl_type::reverse_iterator; + + // default (empty) + constexpr basic_string_span() noexcept = default; + + // copy + constexpr basic_string_span(const basic_string_span& other) noexcept = default; + + // assign + constexpr basic_string_span& operator=(const basic_string_span& other) noexcept = default; + + constexpr basic_string_span(pointer ptr, size_type length) : span_(ptr, length) {} + constexpr basic_string_span(pointer firstElem, pointer lastElem) : span_(firstElem, lastElem) {} + + // From static arrays - if 0-terminated, remove 0 from the view + // All other containers allow 0s within the length, so we do not remove them + template <std::size_t N> + constexpr basic_string_span(element_type(&arr)[N]) : span_(remove_z(arr)) + {} + + template <std::size_t N, class ArrayElementType = std::remove_const_t<element_type>> + constexpr basic_string_span(std::array<ArrayElementType, N> & arr) noexcept : span_(arr) + {} + + template <std::size_t N, class ArrayElementType = std::remove_const_t<element_type>> + constexpr basic_string_span(const std::array<ArrayElementType, N>& arr) noexcept : span_(arr) + {} + + // Container signature should work for basic_string after C++17 version exists + template <class Traits, class Allocator> + // GSL_SUPPRESS(bounds.4) // TODO: parser bug + constexpr basic_string_span(std::basic_string<element_type, Traits, Allocator> & str) + : span_(&str[0], str.length()) + {} + + template <class Traits, class Allocator> + constexpr basic_string_span(const std::basic_string<element_type, Traits, Allocator>& str) + : span_(&str[0], str.length()) + {} + + // from containers. Containers must have a pointer type and data() function signatures + template <class Container, + class = std::enable_if_t< + !details::is_basic_string_span<Container>::value && + std::is_convertible<typename Container::pointer, pointer>::value && + std::is_convertible<typename Container::pointer, + decltype(std::declval<Container>().data())>::value>> + constexpr basic_string_span(Container & cont) : span_(cont) + {} + + template <class Container, + class = std::enable_if_t< + !details::is_basic_string_span<Container>::value && + std::is_convertible<typename Container::pointer, pointer>::value && + std::is_convertible<typename Container::pointer, + decltype(std::declval<Container>().data())>::value>> + constexpr basic_string_span(const Container& cont) : span_(cont) + {} + + // from string_span + template < + class OtherValueType, std::size_t OtherExtent, + class = std::enable_if_t<std::is_convertible< + typename basic_string_span<OtherValueType, OtherExtent>::impl_type, impl_type>::value>> + constexpr basic_string_span(basic_string_span<OtherValueType, OtherExtent> other) + : span_(other.data(), other.length()) + {} + + template <size_type Count> + constexpr basic_string_span<element_type, Count> first() const + { + return {span_.template first<Count>()}; + } + + constexpr basic_string_span<element_type, dynamic_extent> first(size_type count) const + { + return {span_.first(count)}; + } + + template <size_type Count> + constexpr basic_string_span<element_type, Count> last() const + { + return {span_.template last<Count>()}; + } + + constexpr basic_string_span<element_type, dynamic_extent> last(size_type count) const + { + return {span_.last(count)}; + } + + template <size_type Offset, size_type Count> + constexpr basic_string_span<element_type, Count> subspan() const + { + return {span_.template subspan<Offset, Count>()}; + } + + constexpr basic_string_span<element_type, dynamic_extent> subspan( + size_type offset, size_type count = dynamic_extent) const + { + return {span_.subspan(offset, count)}; + } + + constexpr reference operator[](size_type idx) const { return span_[idx]; } + constexpr reference operator()(size_type idx) const { return span_[idx]; } + + constexpr pointer data() const { return span_.data(); } + + constexpr size_type length() const noexcept { return span_.size(); } + constexpr size_type size() const noexcept { return span_.size(); } + constexpr size_type size_bytes() const noexcept { return span_.size_bytes(); } + constexpr size_type length_bytes() const noexcept { return span_.length_bytes(); } + constexpr bool empty() const noexcept { return size() == 0; } + + constexpr iterator begin() const noexcept { return span_.begin(); } + constexpr iterator end() const noexcept { return span_.end(); } + + constexpr reverse_iterator rbegin() const noexcept { return span_.rbegin(); } + constexpr reverse_iterator rend() const noexcept { return span_.rend(); } + +private: + static constexpr impl_type remove_z(pointer const& sz, std::size_t max) + { + return impl_type(sz, details::string_length(sz, max)); + } + + template <std::size_t N> + static constexpr impl_type remove_z(element_type(&sz)[N]) + { + return remove_z(&sz[0], N); + } + + impl_type span_; +}; + +template <std::size_t Extent = dynamic_extent> +using string_span [[deprecated("string_span was removed from the C++ Core Guidelines. For more " + "information, see isocpp/CppCoreGuidelines PR#1680")]] = + basic_string_span<char, Extent>; + +template <std::size_t Extent = dynamic_extent> +using cstring_span [[deprecated("string_span was removed from the C++ Core Guidelines. For more " + "information, see isocpp/CppCoreGuidelines PR#1680")]] = + basic_string_span<const char, Extent>; + +template <std::size_t Extent = dynamic_extent> +using wstring_span [[deprecated("string_span was removed from the C++ Core Guidelines. For more " + "information, see isocpp/CppCoreGuidelines PR#1680")]] = + basic_string_span<wchar_t, Extent>; + +template <std::size_t Extent = dynamic_extent> +using cwstring_span [[deprecated("string_span was removed from the C++ Core Guidelines. For more " + "information, see isocpp/CppCoreGuidelines PR#1680")]] = + basic_string_span<const wchar_t, Extent>; + +template <std::size_t Extent = dynamic_extent> +using u16string_span [[deprecated("string_span was removed from the C++ Core Guidelines. For more " + "information, see isocpp/CppCoreGuidelines PR#1680")]] = + basic_string_span<char16_t, Extent>; + +template <std::size_t Extent = dynamic_extent> +using cu16string_span [[deprecated("string_span was removed from the C++ Core Guidelines. For more " + "information, see isocpp/CppCoreGuidelines PR#1680")]] = + basic_string_span<const char16_t, Extent>; + +template <std::size_t Extent = dynamic_extent> +using u32string_span [[deprecated("string_span was removed from the C++ Core Guidelines. For more " + "information, see isocpp/CppCoreGuidelines PR#1680")]] = + basic_string_span<char32_t, Extent>; + +template <std::size_t Extent = dynamic_extent> +using cu32string_span [[deprecated("string_span was removed from the C++ Core Guidelines. For more " + "information, see isocpp/CppCoreGuidelines PR#1680")]] = + basic_string_span<const char32_t, Extent>; + +// +// to_string() allow (explicit) conversions from string_span to string +// + +template <typename CharT, std::size_t Extent> +constexpr std::basic_string<typename std::remove_const<CharT>::type> +to_string(basic_string_span<CharT, Extent> view) +{ + return {view.data(), narrow_cast<std::size_t>(view.length())}; +} + +template <typename CharT, typename Traits = typename std::char_traits<CharT>, + typename Allocator = std::allocator<CharT>, typename gCharT, std::size_t Extent> +constexpr std::basic_string<CharT, Traits, Allocator> +to_basic_string(basic_string_span<gCharT, Extent> view) +{ + return {view.data(), narrow_cast<std::size_t>(view.length())}; +} + +template <class ElementType, std::size_t Extent> +constexpr basic_string_span<const byte, details::calculate_byte_size<ElementType, Extent>::value> +as_bytes(basic_string_span<ElementType, Extent> s) noexcept +{ + // clang-format off + GSL_SUPPRESS(type.1) + // clang-format on + return {reinterpret_cast<const byte*>(s.data()), s.size_bytes()}; +} + +template <class ElementType, std::size_t Extent, + class = std::enable_if_t<!std::is_const<ElementType>::value>> +constexpr basic_string_span<byte, details::calculate_byte_size<ElementType, Extent>::value> +as_writable_bytes(basic_string_span<ElementType, Extent> s) noexcept +{ + // clang-format off + GSL_SUPPRESS(type.1) + // clang-format on + return {reinterpret_cast<byte*>(s.data()), s.size_bytes()}; +} + +// zero-terminated string span, used to convert +// zero-terminated spans to legacy strings +template <typename CharT, std::size_t Extent = dynamic_extent> +class [[deprecated("string_span was removed from the C++ Core Guidelines. For more information, " + "see isocpp/CppCoreGuidelines PR#1680")]] basic_zstring_span +{ +public: + using value_type = CharT; + using const_value_type = std::add_const_t<CharT>; + + using pointer = std::add_pointer_t<value_type>; + using const_pointer = std::add_pointer_t<const_value_type>; + + using zstring_type = basic_zstring<value_type, Extent>; + using const_zstring_type = basic_zstring<const_value_type, Extent>; + + using impl_type = span<value_type, Extent>; + using string_span_type = basic_string_span<value_type, Extent>; + + constexpr basic_zstring_span(impl_type s) : span_(s) + { + // expects a zero-terminated span + Expects(s.size() > 0); + Expects(s[s.size() - 1] == value_type{}); + } + + // copy + constexpr basic_zstring_span(const basic_zstring_span& other) = default; + + // move + constexpr basic_zstring_span(basic_zstring_span && other) = default; + + // assign + constexpr basic_zstring_span& operator=(const basic_zstring_span& other) = default; + + // move assign + constexpr basic_zstring_span& operator=(basic_zstring_span&& other) = default; + + constexpr bool empty() const noexcept { return false; } + + constexpr string_span_type as_string_span() const noexcept + { + return {span_.data(), span_.size() - 1}; + } + constexpr string_span_type ensure_z() const { return gsl::ensure_z(span_); } + + constexpr const_zstring_type assume_z() const noexcept { return span_.data(); } + +private: + impl_type span_; +}; + +template <std::size_t Max = dynamic_extent> +using zstring_span [[deprecated("string_span was removed from the C++ Core Guidelines. For more " + "information, see isocpp/CppCoreGuidelines PR#1680")]] = + basic_zstring_span<char, Max>; + +template <std::size_t Max = dynamic_extent> +using wzstring_span [[deprecated("string_span was removed from the C++ Core Guidelines. For more " + "information, see isocpp/CppCoreGuidelines PR#1680")]] = + basic_zstring_span<wchar_t, Max>; + +template <std::size_t Max = dynamic_extent> +using u16zstring_span [[deprecated("string_span was removed from the C++ Core Guidelines. For more " + "information, see isocpp/CppCoreGuidelines PR#1680")]] = + basic_zstring_span<char16_t, Max>; + +template <std::size_t Max = dynamic_extent> +using u32zstring_span [[deprecated("string_span was removed from the C++ Core Guidelines. For more " + "information, see isocpp/CppCoreGuidelines PR#1680")]] = + basic_zstring_span<char32_t, Max>; + +template <std::size_t Max = dynamic_extent> +using czstring_span [[deprecated("string_span was removed from the C++ Core Guidelines. For more " + "information, see isocpp/CppCoreGuidelines PR#1680")]] = + basic_zstring_span<const char, Max>; + +template <std::size_t Max = dynamic_extent> +using cwzstring_span [[deprecated("string_span was removed from the C++ Core Guidelines. For more " + "information, see isocpp/CppCoreGuidelines PR#1680")]] = + basic_zstring_span<const wchar_t, Max>; + +template <std::size_t Max = dynamic_extent> +using cu16zstring_span [[deprecated("string_span was removed from the C++ Core Guidelines. For " + "more information, see isocpp/CppCoreGuidelines PR#1680")]] = + basic_zstring_span<const char16_t, Max>; + +template <std::size_t Max = dynamic_extent> +using cu32zstring_span [[deprecated("string_span was removed from the C++ Core Guidelines. For " + "more information, see isocpp/CppCoreGuidelines PR#1680")]] = + basic_zstring_span<const char32_t, Max>; + +// operator == +template <class CharT, std::size_t Extent, class T, + class = std::enable_if_t< + details::is_basic_string_span<T>::value || + std::is_convertible<T, gsl::basic_string_span<std::add_const_t<CharT>>>::value>> +bool operator==(const gsl::basic_string_span<CharT, Extent>& one, const T& other) +{ + const gsl::basic_string_span<std::add_const_t<CharT>> tmp(other); + return std::equal(one.begin(), one.end(), tmp.begin(), tmp.end()); +} + +template <class CharT, std::size_t Extent, class T, + class = std::enable_if_t< + !details::is_basic_string_span<T>::value && + std::is_convertible<T, gsl::basic_string_span<std::add_const_t<CharT>>>::value>> +bool operator==(const T& one, const gsl::basic_string_span<CharT, Extent>& other) +{ + const gsl::basic_string_span<std::add_const_t<CharT>> tmp(one); + return std::equal(tmp.begin(), tmp.end(), other.begin(), other.end()); +} + +// operator != +template <typename CharT, std::size_t Extent = dynamic_extent, typename T, + typename = std::enable_if_t<std::is_convertible< + T, gsl::basic_string_span<std::add_const_t<CharT>, Extent>>::value>> +bool operator!=(gsl::basic_string_span<CharT, Extent> one, const T& other) +{ + return !(one == other); +} + +template < + typename CharT, std::size_t Extent = dynamic_extent, typename T, + typename = std::enable_if_t< + std::is_convertible<T, gsl::basic_string_span<std::add_const_t<CharT>, Extent>>::value && + !gsl::details::is_basic_string_span<T>::value>> +bool operator!=(const T& one, gsl::basic_string_span<CharT, Extent> other) +{ + return !(one == other); +} + +// operator< +template <typename CharT, std::size_t Extent = dynamic_extent, typename T, + typename = std::enable_if_t<std::is_convertible< + T, gsl::basic_string_span<std::add_const_t<CharT>, Extent>>::value>> +bool operator<(gsl::basic_string_span<CharT, Extent> one, const T& other) +{ + const gsl::basic_string_span<std::add_const_t<CharT>, Extent> tmp(other); + return std::lexicographical_compare(one.begin(), one.end(), tmp.begin(), tmp.end()); +} + +template < + typename CharT, std::size_t Extent = dynamic_extent, typename T, + typename = std::enable_if_t< + std::is_convertible<T, gsl::basic_string_span<std::add_const_t<CharT>, Extent>>::value && + !gsl::details::is_basic_string_span<T>::value>> +bool operator<(const T& one, gsl::basic_string_span<CharT, Extent> other) +{ + gsl::basic_string_span<std::add_const_t<CharT>, Extent> tmp(one); + return std::lexicographical_compare(tmp.begin(), tmp.end(), other.begin(), other.end()); +} + +#ifndef _MSC_VER + +// VS treats temp and const containers as convertible to basic_string_span, +// so the cases below are already covered by the previous operators + +template < + typename CharT, std::size_t Extent = dynamic_extent, typename T, + typename DataType = typename T::value_type, + typename = std::enable_if_t< + !gsl::details::is_span<T>::value && !gsl::details::is_basic_string_span<T>::value && + std::is_convertible<DataType*, CharT*>::value && + std::is_same<std::decay_t<decltype(std::declval<T>().size(), *std::declval<T>().data())>, + DataType>::value>> +bool operator<(gsl::basic_string_span<CharT, Extent> one, const T& other) +{ + gsl::basic_string_span<std::add_const_t<CharT>, Extent> tmp(other); + return std::lexicographical_compare(one.begin(), one.end(), tmp.begin(), tmp.end()); +} + +template < + typename CharT, std::size_t Extent = dynamic_extent, typename T, + typename DataType = typename T::value_type, + typename = std::enable_if_t< + !gsl::details::is_span<T>::value && !gsl::details::is_basic_string_span<T>::value && + std::is_convertible<DataType*, CharT*>::value && + std::is_same<std::decay_t<decltype(std::declval<T>().size(), *std::declval<T>().data())>, + DataType>::value>> +bool operator<(const T& one, gsl::basic_string_span<CharT, Extent> other) +{ + gsl::basic_string_span<std::add_const_t<CharT>, Extent> tmp(one); + return std::lexicographical_compare(tmp.begin(), tmp.end(), other.begin(), other.end()); +} +#endif + +// operator <= +template <typename CharT, std::size_t Extent = dynamic_extent, typename T, + typename = std::enable_if_t<std::is_convertible< + T, gsl::basic_string_span<std::add_const_t<CharT>, Extent>>::value>> +bool operator<=(gsl::basic_string_span<CharT, Extent> one, const T& other) +{ + return !(other < one); +} + +template < + typename CharT, std::size_t Extent = dynamic_extent, typename T, + typename = std::enable_if_t< + std::is_convertible<T, gsl::basic_string_span<std::add_const_t<CharT>, Extent>>::value && + !gsl::details::is_basic_string_span<T>::value>> +bool operator<=(const T& one, gsl::basic_string_span<CharT, Extent> other) +{ + return !(other < one); +} + +#ifndef _MSC_VER + +// VS treats temp and const containers as convertible to basic_string_span, +// so the cases below are already covered by the previous operators + +template < + typename CharT, std::size_t Extent = dynamic_extent, typename T, + typename DataType = typename T::value_type, + typename = std::enable_if_t< + !gsl::details::is_span<T>::value && !gsl::details::is_basic_string_span<T>::value && + std::is_convertible<DataType*, CharT*>::value && + std::is_same<std::decay_t<decltype(std::declval<T>().size(), *std::declval<T>().data())>, + DataType>::value>> +bool operator<=(gsl::basic_string_span<CharT, Extent> one, const T& other) +{ + return !(other < one); +} + +template < + typename CharT, std::size_t Extent = dynamic_extent, typename T, + typename DataType = typename T::value_type, + typename = std::enable_if_t< + !gsl::details::is_span<T>::value && !gsl::details::is_basic_string_span<T>::value && + std::is_convertible<DataType*, CharT*>::value && + std::is_same<std::decay_t<decltype(std::declval<T>().size(), *std::declval<T>().data())>, + DataType>::value>> +bool operator<=(const T& one, gsl::basic_string_span<CharT, Extent> other) +{ + return !(other < one); +} +#endif + +// operator> +template <typename CharT, std::size_t Extent = dynamic_extent, typename T, + typename = std::enable_if_t<std::is_convertible< + T, gsl::basic_string_span<std::add_const_t<CharT>, Extent>>::value>> +bool operator>(gsl::basic_string_span<CharT, Extent> one, const T& other) +{ + return other < one; +} + +template < + typename CharT, std::size_t Extent = dynamic_extent, typename T, + typename = std::enable_if_t< + std::is_convertible<T, gsl::basic_string_span<std::add_const_t<CharT>, Extent>>::value && + !gsl::details::is_basic_string_span<T>::value>> +bool operator>(const T& one, gsl::basic_string_span<CharT, Extent> other) +{ + return other < one; +} + +#ifndef _MSC_VER + +// VS treats temp and const containers as convertible to basic_string_span, +// so the cases below are already covered by the previous operators + +template < + typename CharT, std::size_t Extent = dynamic_extent, typename T, + typename DataType = typename T::value_type, + typename = std::enable_if_t< + !gsl::details::is_span<T>::value && !gsl::details::is_basic_string_span<T>::value && + std::is_convertible<DataType*, CharT*>::value && + std::is_same<std::decay_t<decltype(std::declval<T>().size(), *std::declval<T>().data())>, + DataType>::value>> +bool operator>(gsl::basic_string_span<CharT, Extent> one, const T& other) +{ + return other < one; +} + +template < + typename CharT, std::size_t Extent = dynamic_extent, typename T, + typename DataType = typename T::value_type, + typename = std::enable_if_t< + !gsl::details::is_span<T>::value && !gsl::details::is_basic_string_span<T>::value && + std::is_convertible<DataType*, CharT*>::value && + std::is_same<std::decay_t<decltype(std::declval<T>().size(), *std::declval<T>().data())>, + DataType>::value>> +bool operator>(const T& one, gsl::basic_string_span<CharT, Extent> other) +{ + return other < one; +} +#endif + +// operator >= +template <typename CharT, std::size_t Extent = dynamic_extent, typename T, + typename = std::enable_if_t<std::is_convertible< + T, gsl::basic_string_span<std::add_const_t<CharT>, Extent>>::value>> +bool operator>=(gsl::basic_string_span<CharT, Extent> one, const T& other) +{ + return !(one < other); +} + +template < + typename CharT, std::size_t Extent = dynamic_extent, typename T, + typename = std::enable_if_t< + std::is_convertible<T, gsl::basic_string_span<std::add_const_t<CharT>, Extent>>::value && + !gsl::details::is_basic_string_span<T>::value>> +bool operator>=(const T& one, gsl::basic_string_span<CharT, Extent> other) +{ + return !(one < other); +} + +#ifndef _MSC_VER + +// VS treats temp and const containers as convertible to basic_string_span, +// so the cases below are already covered by the previous operators + +template < + typename CharT, std::size_t Extent = dynamic_extent, typename T, + typename DataType = typename T::value_type, + typename = std::enable_if_t< + !gsl::details::is_span<T>::value && !gsl::details::is_basic_string_span<T>::value && + std::is_convertible<DataType*, CharT*>::value && + std::is_same<std::decay_t<decltype(std::declval<T>().size(), *std::declval<T>().data())>, + DataType>::value>> +bool operator>=(gsl::basic_string_span<CharT, Extent> one, const T& other) +{ + return !(one < other); +} + +template < + typename CharT, std::size_t Extent = dynamic_extent, typename T, + typename DataType = typename T::value_type, + typename = std::enable_if_t< + !gsl::details::is_span<T>::value && !gsl::details::is_basic_string_span<T>::value && + std::is_convertible<DataType*, CharT*>::value && + std::is_same<std::decay_t<decltype(std::declval<T>().size(), *std::declval<T>().data())>, + DataType>::value>> +bool operator>=(const T& one, gsl::basic_string_span<CharT, Extent> other) +{ + return !(one < other); +} +#endif +} // namespace gsl + +#if defined(_MSC_VER) && !defined(__clang__) +#pragma warning(pop) + +#endif // _MSC_VER + +#if defined(__GNUC__) || defined(__clang__) +#pragma GCC diagnostic pop +#endif +#endif // GSL_STRING_SPAN_H diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/gsl/util b/Plugins/CesiumForUnreal/Source/ThirdParty/include/gsl/util new file mode 100644 index 0000000000000000000000000000000000000000..2d67b7f996e6073ef3910007d9e4faea7b6268ec --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/gsl/util @@ -0,0 +1,145 @@ +/////////////////////////////////////////////////////////////////////////////// +// +// Copyright (c) 2015 Microsoft Corporation. All rights reserved. +// +// This code is licensed under the MIT License (MIT). +// +// 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 GSL_UTIL_H +#define GSL_UTIL_H + +#include <gsl/assert> // for Expects + +#include <array> +#include <cstddef> // for ptrdiff_t, size_t +#include <initializer_list> // for initializer_list +#include <type_traits> // for is_signed, integral_constant +#include <utility> // for exchange, forward + +#if defined(_MSC_VER) && !defined(__clang__) + +#pragma warning(push) +#pragma warning(disable : 4127) // conditional expression is constant + +#endif // _MSC_VER + +#if defined(__cplusplus) && (__cplusplus >= 201703L) +#define GSL_NODISCARD [[nodiscard]] +#else +#define GSL_NODISCARD +#endif // defined(__cplusplus) && (__cplusplus >= 201703L) + +namespace gsl +{ +// +// GSL.util: utilities +// + +// index type for all container indexes/subscripts/sizes +using index = std::ptrdiff_t; + +// final_action allows you to ensure something gets run at the end of a scope +template <class F> +class final_action +{ +public: + static_assert(!std::is_reference<F>::value && !std::is_const<F>::value && + !std::is_volatile<F>::value, + "Final_action should store its callable by value"); + + explicit final_action(F f) noexcept : f_(std::move(f)) {} + + final_action(final_action&& other) noexcept + : f_(std::move(other.f_)), invoke_(std::exchange(other.invoke_, false)) + {} + + final_action(const final_action&) = delete; + final_action& operator=(const final_action&) = delete; + final_action& operator=(final_action&&) = delete; + + // clang-format off + GSL_SUPPRESS(f.6) // NO-FORMAT: attribute // terminate if throws + // clang-format on + ~final_action() noexcept + { + if (invoke_) f_(); + } + +private: + F f_; + bool invoke_{true}; +}; + +// finally() - convenience function to generate a final_action +template <class F> +GSL_NODISCARD final_action<typename std::remove_cv<typename std::remove_reference<F>::type>::type> +finally(F&& f) noexcept +{ + return final_action<typename std::remove_cv<typename std::remove_reference<F>::type>::type>( + std::forward<F>(f)); +} + +// narrow_cast(): a searchable way to do narrowing casts of values +template <class T, class U> +// clang-format off +GSL_SUPPRESS(type.1) // NO-FORMAT: attribute +// clang-format on +constexpr T narrow_cast(U&& u) noexcept +{ + return static_cast<T>(std::forward<U>(u)); +} + +// +// at() - Bounds-checked way of accessing builtin arrays, std::array, std::vector +// +template <class T, std::size_t N> +// clang-format off +GSL_SUPPRESS(bounds.4) // NO-FORMAT: attribute +GSL_SUPPRESS(bounds.2) // NO-FORMAT: attribute +// clang-format on + constexpr T& at(T (&arr)[N], const index i) +{ + Expects(i >= 0 && i < narrow_cast<index>(N)); + return arr[narrow_cast<std::size_t>(i)]; +} + +template <class Cont> +// clang-format off +GSL_SUPPRESS(bounds.4) // NO-FORMAT: attribute +GSL_SUPPRESS(bounds.2) // NO-FORMAT: attribute +// clang-format on + constexpr auto at(Cont& cont, const index i) -> decltype(cont[cont.size()]) +{ + Expects(i >= 0 && i < narrow_cast<index>(cont.size())); + using size_type = decltype(cont.size()); + return cont[narrow_cast<size_type>(i)]; +} + +template <class T> +// clang-format off +GSL_SUPPRESS(bounds.1) // NO-FORMAT: attribute +// clang-format on +constexpr T at(const std::initializer_list<T> cont, const index i) +{ + Expects(i >= 0 && i < narrow_cast<index>(cont.size())); + return *(cont.begin() + i); +} + +} // namespace gsl + +#if defined(_MSC_VER) && !defined(__clang__) + +#pragma warning(pop) + +#endif // _MSC_VER + +#endif // GSL_UTIL_H 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 0000000000000000000000000000000000000000..52c44a713c60ebff71133a41e0711bbf7199fc5e --- /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 0000000000000000000000000000000000000000..f2b7f94021c9ed618eae89be804cbe5a26f654e4 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/nonstd/expected.hpp @@ -0,0 +1,2520 @@ +// 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 6 +#define expected_lite_PATCH 2 + +#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(<nonstd/expected.tweak.hpp>) +# include <nonstd/expected.tweak.hpp> +# 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 + +// Control presence of C++ exception handling (try and auto discover): + +#ifndef nsel_CONFIG_NO_EXCEPTIONS +# if defined(_MSC_VER) +# include <cstddef> // 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( <expected> ) +# 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 <utility>: + +#if nsel_CPP17_OR_GREATER + +#include <utility> + +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<T> +#define nonstd_lite_in_place_index_t(K) std::in_place_index_t<K> + +#define nonstd_lite_in_place( T) std::in_place_t{} +#define nonstd_lite_in_place_type( T) std::in_place_type_t<T>{} +#define nonstd_lite_in_place_index(K) std::in_place_index_t<K>{} + +} // namespace nonstd + +#else // nsel_CPP17_OR_GREATER + +#include <cstddef> + +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<T> = detail::in_place_type_tag<T>() ) +{ + return in_place_t(); +} + +template< std::size_t K > +inline in_place_t in_place( detail::in_place_index_tag<K> = detail::in_place_index_tag<K>() ) +{ + return in_place_t(); +} + +template< class T > +inline in_place_t in_place_type( detail::in_place_type_tag<T> = detail::in_place_type_tag<T>() ) +{ + return in_place_t(); +} + +template< std::size_t K > +inline in_place_t in_place_index( detail::in_place_index_tag<K> = detail::in_place_index_tag<K>() ) +{ + return in_place_t(); +} + +// mimic templated typedef: + +#define nonstd_lite_in_place_t( T) nonstd::in_place_t(&)( nonstd::detail::in_place_type_tag<T> ) +#define nonstd_lite_in_place_type_t( T) nonstd::in_place_t(&)( nonstd::detail::in_place_type_tag<T> ) +#define nonstd_lite_in_place_index_t(K) nonstd::in_place_t(&)( nonstd::detail::in_place_index_tag<K> ) + +#define nonstd_lite_in_place( T) nonstd::in_place_type<T> +#define nonstd_lite_in_place_type( T) nonstd::in_place_type<T> +#define nonstd_lite_in_place_index(K) nonstd::in_place_index<K> + +} // namespace nonstd + +#endif // nsel_CPP17_OR_GREATER +#endif // nonstd_lite_HAVE_IN_PLACE_TYPES + +// +// Using std::expected: +// + +#if nsel_USES_STD_EXPECTED + +#include <expected> + +namespace nonstd { + + using std::expected; +// ... +} + +#else // nsel_USES_STD_EXPECTED + +#include <cassert> +#include <exception> +#include <functional> +#include <initializer_list> +#include <memory> +#include <new> +#include <system_error> +#include <type_traits> +#include <utility> + +// additional includes: + +#if nsel_CONFIG_NO_EXCEPTIONS +# if nsel_CONFIG_NO_EXCEPTIONS_SEH +# include <windows.h> // for ExceptionCodes +# else +// already included: <cassert> +# endif +#else +# include <stdexcept> +#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<B, int>::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 + +// Presence of language and library features: + +#ifdef _HAS_CPP0X +# define nsel_HAS_CPP0X _HAS_CPP0X +#else +# define nsel_HAS_CPP0X 0 +#endif + +//#define nsel_CPP11_140 (nsel_CPP11_OR_GREATER || nsel_COMPILER_MSVC_VER >= 1900) + +// 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 +# pragma warning( push ) +# define nsel_DISABLE_MSVC_WARNINGS(codes) __pragma( warning(disable: codes) ) +#else +# define nsel_DISABLE_MSVC_WARNINGS(codes) +#endif + +#ifdef __clang__ +# define nsel_RESTORE_WARNINGS() _Pragma("clang diagnostic pop") +#elif defined __GNUC__ +# define nsel_RESTORE_WARNINGS() _Pragma("GCC diagnostic pop") +#elif nsel_COMPILER_MSVC_VERSION >= 140 +# define nsel_RESTORE_WARNINGS() __pragma( warning( pop ) ) +#else +# define nsel_RESTORE_WARNINGS() +#endif + +// Suppress the following MSVC (GSL) warnings: +// - C26409: Avoid calling new and delete explicitly, use std::make_unique<T> instead (r.11) + +nsel_DISABLE_MSVC_WARNINGS( 26409 ) + +// +// 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<T&>(), std::declval<T&>() ) ) > + 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<T&>(), std::declval<T&>() ) ); + } + + template< typename T > + static auto test( int ) -> std::integral_constant<bool, satisfies<T>()>{} + + template< typename > + static auto test(...) -> std::false_type; +}; +} // namespace detail + +// is [nothow] swappable: + +template< typename T > +struct is_swappable : decltype( detail::is_swappable::test<T>(0) ){}; + +template< typename T > +struct is_nothrow_swappable : decltype( detail::is_nothrow_swappable::test<T>(0) ){}; + +// conjunction: + +template< typename... > struct conjunction : std::true_type{}; +template< typename B1 > struct conjunction<B1> : B1{}; + +template< typename B1, typename... Bn > +struct conjunction<B1, Bn...> : std::conditional<bool(B1::value), conjunction<Bn...>, 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<T>::type >::type type; +}; + +#endif + +} // namespace std20 + +// forward declaration: + +template< typename T, typename E > +class expected; + +namespace detail { + +/// discriminated union to hold value or 'error'. + +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( 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>(args)...); + } + + template< class U, class... Args > + void emplace_value( std::initializer_list<U> il, Args&&... args ) + { + new( &m_value ) value_type( il, std::forward<Args>(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>(args)...); + } + + template< class U, class... Args > + void emplace_error( std::initializer_list<U> il, Args&&... args ) + { + new( &m_error ) error_type( il, std::forward<Args>(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<void, E> +{ + 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>(args)...); + } + + template< class U, class... Args > + void emplace_error( std::initializer_list<U> il, Args&&... args ) + { + new( &m_error ) error_type( il, std::forward<Args>(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: + storage_t() = default; + ~storage_t() = default; + + explicit storage_t( bool has_value ) + : storage_t_impl<T, E>( has_value ) + {} + + storage_t( storage_t const & other ) = delete; + storage_t( storage_t && other ) = delete; +}; + +template< typename T, typename E > +class storage_t<T, E, true, true> : public storage_t_impl<T, E> +{ +public: + storage_t() = default; + ~storage_t() = default; + + explicit storage_t( bool has_value ) + : storage_t_impl<T, E>( has_value ) + {} + + storage_t( storage_t const & other ) + : storage_t_impl<T, E>( 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<T, E>( 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<void, E, true, true> : public storage_t_impl<void, E> +{ +public: + storage_t() = default; + ~storage_t() = default; + + explicit storage_t( bool has_value ) + : storage_t_impl<void, E>( has_value ) + {} + + storage_t( storage_t const & other ) + : storage_t_impl<void, E>( other.has_value() ) + { + if ( this->has_value() ) ; + else this->construct_error( other.error() ); + } + + storage_t(storage_t && other ) + : storage_t_impl<void, E>( other.has_value() ) + { + if ( this->has_value() ) ; + else this->construct_error( std::move( other.error() ) ); + } +}; + +template< typename T, typename E > +class storage_t<T, E, true, false> : public storage_t_impl<T, E> +{ +public: + storage_t() = default; + ~storage_t() = default; + + explicit storage_t( bool has_value ) + : storage_t_impl<T, E>( has_value ) + {} + + storage_t( storage_t const & other ) + : storage_t_impl<T, E>(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<void, E, true, false> : public storage_t_impl<void, E> +{ +public: + storage_t() = default; + ~storage_t() = default; + + explicit storage_t( bool has_value ) + : storage_t_impl<void, E>( has_value ) + {} + + storage_t( storage_t const & other ) + : storage_t_impl<void, E>(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<T, E, false, true> : public storage_t_impl<T, E> +{ +public: + storage_t() = default; + ~storage_t() = default; + + explicit storage_t( bool has_value ) + : storage_t_impl<T, E>( has_value ) + {} + + storage_t( storage_t const & other ) = delete; + + storage_t( storage_t && other ) + : storage_t_impl<T, E>( 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<void, E, false, true> : public storage_t_impl<void, E> +{ +public: + storage_t() = default; + ~storage_t() = default; + + explicit storage_t( bool has_value ) + : storage_t_impl<void, E>( has_value ) + {} + + storage_t( storage_t const & other ) = delete; + + storage_t( storage_t && other ) + : storage_t_impl<void, E>( other.has_value() ) + { + if ( this->has_value() ) ; + else this->construct_error( std::move( other.error() ) ); + } +}; + +} // 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<E, Args&&...>::value + ) + > + constexpr explicit unexpected_type( nonstd_lite_in_place_t(E), Args &&... args ) + : m_error( std::forward<Args>( args )...) + {} + + template< typename U, typename... Args + nsel_REQUIRES_T( + std::is_constructible<E, std::initializer_list<U>, Args&&...>::value + ) + > + constexpr explicit unexpected_type( nonstd_lite_in_place_t(E), std::initializer_list<U> il, Args &&... args ) + : m_error( il, std::forward<Args>( args )...) + {} + + template< typename E2 + nsel_REQUIRES_T( + std::is_constructible<E,E2>::value + && !std::is_same< typename std20::remove_cvref<E2>::type, nonstd_lite_in_place_t(E2) >::value + && !std::is_same< typename std20::remove_cvref<E2>::type, unexpected_type >::value + ) + > + constexpr explicit unexpected_type( E2 && error ) + : m_error( std::forward<E2>( error ) ) + {} + + template< typename E2 + nsel_REQUIRES_T( + std::is_constructible< E, E2>::value + && !std::is_constructible<E, unexpected_type<E2> & >::value + && !std::is_constructible<E, unexpected_type<E2> >::value + && !std::is_constructible<E, unexpected_type<E2> const & >::value + && !std::is_constructible<E, unexpected_type<E2> const >::value + && !std::is_convertible< unexpected_type<E2> &, E>::value + && !std::is_convertible< unexpected_type<E2> , E>::value + && !std::is_convertible< unexpected_type<E2> const &, E>::value + && !std::is_convertible< unexpected_type<E2> const , E>::value + && !std::is_convertible< E2 const &, E>::value /*=> explicit */ + ) + > + constexpr explicit unexpected_type( unexpected_type<E2> const & error ) + : m_error( E{ error.value() } ) + {} + + template< typename E2 + nsel_REQUIRES_T( + std::is_constructible< E, E2>::value + && !std::is_constructible<E, unexpected_type<E2> & >::value + && !std::is_constructible<E, unexpected_type<E2> >::value + && !std::is_constructible<E, unexpected_type<E2> const & >::value + && !std::is_constructible<E, unexpected_type<E2> const >::value + && !std::is_convertible< unexpected_type<E2> &, E>::value + && !std::is_convertible< unexpected_type<E2> , E>::value + && !std::is_convertible< unexpected_type<E2> const &, E>::value + && !std::is_convertible< unexpected_type<E2> const , E>::value + && std::is_convertible< E2 const &, E>::value /*=> explicit */ + ) + > + constexpr /*non-explicit*/ unexpected_type( unexpected_type<E2> const & error ) + : m_error( error.value() ) + {} + + template< typename E2 + nsel_REQUIRES_T( + std::is_constructible< E, E2>::value + && !std::is_constructible<E, unexpected_type<E2> & >::value + && !std::is_constructible<E, unexpected_type<E2> >::value + && !std::is_constructible<E, unexpected_type<E2> const & >::value + && !std::is_constructible<E, unexpected_type<E2> const >::value + && !std::is_convertible< unexpected_type<E2> &, E>::value + && !std::is_convertible< unexpected_type<E2> , E>::value + && !std::is_convertible< unexpected_type<E2> const &, E>::value + && !std::is_convertible< unexpected_type<E2> const , E>::value + && !std::is_convertible< E2 const &, E>::value /*=> explicit */ + ) + > + constexpr explicit unexpected_type( unexpected_type<E2> && error ) + : m_error( E{ std::move( error.value() ) } ) + {} + + template< typename E2 + nsel_REQUIRES_T( + std::is_constructible< E, E2>::value + && !std::is_constructible<E, unexpected_type<E2> & >::value + && !std::is_constructible<E, unexpected_type<E2> >::value + && !std::is_constructible<E, unexpected_type<E2> const & >::value + && !std::is_constructible<E, unexpected_type<E2> const >::value + && !std::is_convertible< unexpected_type<E2> &, E>::value + && !std::is_convertible< unexpected_type<E2> , E>::value + && !std::is_convertible< unexpected_type<E2> const &, E>::value + && !std::is_convertible< unexpected_type<E2> const , E>::value + && std::is_convertible< E2 const &, E>::value /*=> non-explicit */ + ) + > + constexpr /*non-explicit*/ unexpected_type( unexpected_type<E2> && error ) + : m_error( std::move( error.value() ) ) + {} + + // 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<E2> const & other ) + { + unexpected_type{ other.value() }.swap( *this ); + return *this; + } + + template< typename E2 = E > + nsel_constexpr14 unexpected_type & operator=( unexpected_type<E2> && other ) + { + unexpected_type{ std::move( other.value() ) }.swap( *this ); + return *this; + } + + // x.x.5.2.3 Observers + + nsel_constexpr14 E & value() & noexcept + { + return m_error; + } + + constexpr E const & value() const & noexcept + { + return m_error; + } + +#if !nsel_COMPILER_GNUC_VERSION || nsel_COMPILER_GNUC_VERSION >= 490 + + nsel_constexpr14 E && value() && noexcept + { + return std::move( m_error ); + } + + constexpr E const && value() const && noexcept + { + return std::move( m_error ); + } + +#endif + + // x.x.5.2.4 Swap + + nsel_REQUIRES_R( void, + std17::is_swappable<E>::value + ) + swap( unexpected_type & other ) noexcept ( + std17::is_nothrow_swappable<E>::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<E1> const & x, unexpected_type<E2> const & y ) +{ + return x.value() == y.value(); +} + +template< typename E1, typename E2 > +constexpr bool operator!=( unexpected_type<E1> const & x, unexpected_type<E2> const & y ) +{ + return ! ( x == y ); +} + +#if nsel_P0323R <= 2 + +template< typename E > +constexpr bool operator<( unexpected_type<E> const & x, unexpected_type<E> const & y ) +{ + return x.value() < y.value(); +} + +template< typename E > +constexpr bool operator>( unexpected_type<E> const & x, unexpected_type<E> const & y ) +{ + return ( y < x ); +} + +template< typename E > +constexpr bool operator<=( unexpected_type<E> const & x, unexpected_type<E> const & y ) +{ + return ! ( y < x ); +} + +template< typename E > +constexpr bool operator>=( unexpected_type<E> const & x, unexpected_type<E> const & y ) +{ + return ! ( x < y ); +} + +#endif // nsel_P0323R + +/// x.x.5 Specialized algorithms + +template< typename E + nsel_REQUIRES_T( + std17::is_swappable<E>::value + ) +> +void swap( unexpected_type<E> & x, unexpected_type<E> & 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<std::exception_ptr> const & /*x*/, unexpected_type<std::exception_ptr> const & /*y*/ ) +{ + return false; +} + +inline constexpr bool operator>( unexpected_type<std::exception_ptr> const & /*x*/, unexpected_type<std::exception_ptr> const & /*y*/ ) +{ + return false; +} + +inline constexpr bool operator<=( unexpected_type<std::exception_ptr> const & x, unexpected_type<std::exception_ptr> const & y ) +{ + return ( x == y ); +} + +inline constexpr bool operator>=( unexpected_type<std::exception_ptr> const & x, unexpected_type<std::exception_ptr> 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<E> > : 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<E>::type > +{ + return unexpected_type< typename std::decay<E>::type >( std::forward<E>(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<void>: 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<Error>{ 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<std::exception_ptr>{ 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<Error>{ 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 + +} // 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<E>; + + template< typename U > + struct rebind + { + using type = expected<U, error_type>; + }; + + // x.x.4.1 constructors + + nsel_REQUIRES_0( + std::is_default_constructible<T>::value + ) + nsel_constexpr14 expected() + : contained( true ) + { + contained.construct_value( value_type() ); + } + + 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<E, G const &>::value + && !std::is_constructible<T, expected<U, G> & >::value + && !std::is_constructible<T, expected<U, G> && >::value + && !std::is_constructible<T, expected<U, G> const & >::value + && !std::is_constructible<T, expected<U, G> const && >::value + && !std::is_convertible< expected<U, G> & , T>::value + && !std::is_convertible< expected<U, G> &&, T>::value + && !std::is_convertible< expected<U, G> const & , T>::value + && !std::is_convertible< expected<U, G> const &&, T>::value + && (!std::is_convertible<U const &, T>::value || !std::is_convertible<G const &, E>::value ) /*=> explicit */ + ) + > + nsel_constexpr14 explicit expected( expected<U, G> 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<E, G const &>::value + && !std::is_constructible<T, expected<U, G> & >::value + && !std::is_constructible<T, expected<U, G> && >::value + && !std::is_constructible<T, expected<U, G> const & >::value + && !std::is_constructible<T, expected<U, G> const && >::value + && !std::is_convertible< expected<U, G> & , T>::value + && !std::is_convertible< expected<U, G> &&, T>::value + && !std::is_convertible< expected<U, G> const &, T>::value + && !std::is_convertible< expected<U, G> const &&, T>::value + && !(!std::is_convertible<U const &, T>::value || !std::is_convertible<G const &, E>::value ) /*=> non-explicit */ + ) + > + nsel_constexpr14 /*non-explicit*/ expected( expected<U, G> 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<E, G>::value + && !std::is_constructible<T, expected<U, G> & >::value + && !std::is_constructible<T, expected<U, G> && >::value + && !std::is_constructible<T, expected<U, G> const & >::value + && !std::is_constructible<T, expected<U, G> const && >::value + && !std::is_convertible< expected<U, G> & , T>::value + && !std::is_convertible< expected<U, G> &&, T>::value + && !std::is_convertible< expected<U, G> const & , T>::value + && !std::is_convertible< expected<U, G> const &&, T>::value + && (!std::is_convertible<U, T>::value || !std::is_convertible<G, E>::value ) /*=> explicit */ + ) + > + nsel_constexpr14 explicit expected( expected<U, G> && 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<E, G>::value + && !std::is_constructible<T, expected<U, G> & >::value + && !std::is_constructible<T, expected<U, G> && >::value + && !std::is_constructible<T, expected<U, G> const & >::value + && !std::is_constructible<T, expected<U, G> const && >::value + && !std::is_convertible< expected<U, G> & , T>::value + && !std::is_convertible< expected<U, G> &&, T>::value + && !std::is_convertible< expected<U, G> const & , T>::value + && !std::is_convertible< expected<U, G> const &&, T>::value + && !(!std::is_convertible<U, T>::value || !std::is_convertible<G, E>::value ) /*=> non-explicit */ + ) + > + nsel_constexpr14 /*non-explicit*/ expected( expected<U, G> && 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<U>::value + ) + > + nsel_constexpr14 expected( value_type const & value ) + : contained( true ) + { + contained.construct_value( value ); + } + + template< typename U = T + nsel_REQUIRES_T( + std::is_constructible<T,U&&>::value + && !std::is_same<typename std20::remove_cvref<U>::type, nonstd_lite_in_place_t(U)>::value + && !std::is_same< expected<T,E> , typename std20::remove_cvref<U>::type>::value + && !std::is_same<nonstd::unexpected_type<E>, typename std20::remove_cvref<U>::type>::value + && !std::is_convertible<U&&,T>::value /*=> explicit */ + ) + > + nsel_constexpr14 explicit expected( U && value ) noexcept + ( + std::is_nothrow_move_constructible<U>::value && + std::is_nothrow_move_constructible<E>::value + ) + : contained( true ) + { + contained.construct_value( T{ std::forward<U>( value ) } ); + } + + template< typename U = T + nsel_REQUIRES_T( + std::is_constructible<T,U&&>::value + && !std::is_same<typename std20::remove_cvref<U>::type, nonstd_lite_in_place_t(U)>::value + && !std::is_same< expected<T,E> , typename std20::remove_cvref<U>::type>::value + && !std::is_same<nonstd::unexpected_type<E>, typename std20::remove_cvref<U>::type>::value + && std::is_convertible<U&&,T>::value /*=> non-explicit */ + ) + > + nsel_constexpr14 /*non-explicit*/ expected( U && value ) noexcept + ( + std::is_nothrow_move_constructible<U>::value && + std::is_nothrow_move_constructible<E>::value + ) + : contained( true ) + { + contained.construct_value( std::forward<U>( value ) ); + } + + // construct error: + + template< typename G = E + nsel_REQUIRES_T( + std::is_constructible<E, G const & >::value + && !std::is_convertible< G const &, E>::value /*=> explicit */ + ) + > + nsel_constexpr14 explicit expected( nonstd::unexpected_type<G> const & error ) + : contained( false ) + { + contained.construct_error( E{ error.value() } ); + } + + template< typename G = E + nsel_REQUIRES_T( + std::is_constructible<E, G const & >::value + && std::is_convertible< G const &, E>::value /*=> non-explicit */ + ) + > + nsel_constexpr14 /*non-explicit*/ expected( nonstd::unexpected_type<G> const & error ) + : contained( false ) + { + contained.construct_error( error.value() ); + } + + template< typename G = E + nsel_REQUIRES_T( + std::is_constructible<E, G&& >::value + && !std::is_convertible< G&&, E>::value /*=> explicit */ + ) + > + nsel_constexpr14 explicit expected( nonstd::unexpected_type<G> && error ) + : contained( false ) + { + contained.construct_error( E{ std::move( error.value() ) } ); + } + + template< typename G = E + nsel_REQUIRES_T( + std::is_constructible<E, G&& >::value + && std::is_convertible< G&&, E>::value /*=> non-explicit */ + ) + > + nsel_constexpr14 /*non-explicit*/ expected( nonstd::unexpected_type<G> && error ) + : contained( false ) + { + contained.construct_error( std::move( error.value() ) ); + } + + // in-place construction, value + + template< typename... Args + nsel_REQUIRES_T( + std::is_constructible<T, Args&&...>::value + ) + > + nsel_constexpr14 explicit expected( nonstd_lite_in_place_t(T), Args&&... args ) + : contained( true ) + { + contained.emplace_value( std::forward<Args>( args )... ); + } + + template< typename U, typename... Args + nsel_REQUIRES_T( + std::is_constructible<T, std::initializer_list<U>, Args&&...>::value + ) + > + nsel_constexpr14 explicit expected( nonstd_lite_in_place_t(T), std::initializer_list<U> il, Args&&... args ) + : contained( true ) + { + contained.emplace_value( il, std::forward<Args>( args )... ); + } + + // in-place construction, error + + template< typename... Args + nsel_REQUIRES_T( + std::is_constructible<E, Args&&...>::value + ) + > + nsel_constexpr14 explicit expected( unexpect_t, Args&&... args ) + : contained( false ) + { + contained.emplace_error( std::forward<Args>( args )... ); + } + + template< typename U, typename... Args + nsel_REQUIRES_T( + std::is_constructible<E, std::initializer_list<U>, Args&&...>::value + ) + > + nsel_constexpr14 explicit expected( unexpect_t, std::initializer_list<U> il, Args&&... args ) + : contained( false ) + { + contained.emplace_error( il, std::forward<Args>( args )... ); + } + + // x.x.4.2 destructor + + // TODO: ~expected: triviality + // Effects: If T is not cv void and is_trivially_destructible_v<T> is false and bool(*this), calls val.~T(). If is_trivially_destructible_v<E> is false and !bool(*this), calls unexpect.~unexpected<E>(). + // Remarks: If either T is cv void or is_trivially_destructible_v<T> is true, and is_trivially_destructible_v<E> 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<E>::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<expected<T,E>, typename std20::remove_cvref<U>::type>::value + && std17::conjunction<std::is_scalar<T>, std::is_same<T, std::decay<U>> >::value + && std::is_constructible<T ,U>::value + && std::is_assignable< T&,U>::value + && std::is_nothrow_move_constructible<E>::value ) + > + expected & operator=( U && value ) + { + expected( std::forward<U>( value ) ).swap( *this ); + return *this; + } + + template< typename G = E + nsel_REQUIRES_T( + std::is_constructible<E, G const&>::value && + std::is_copy_constructible<G>::value // TODO: std::is_nothrow_copy_constructible<G> + && std::is_copy_assignable<G>::value + ) + > + expected & operator=( nonstd::unexpected_type<G> const & error ) + { + expected( unexpect, error.value() ).swap( *this ); + return *this; + } + + template< typename G = E + nsel_REQUIRES_T( + std::is_constructible<E, G&&>::value && + std::is_move_constructible<G>::value // TODO: std::is_nothrow_move_constructible<G> + && std::is_move_assignable<G>::value + ) + > + expected & operator=( nonstd::unexpected_type<G> && error ) + { + expected( unexpect, std::move( error.value() ) ).swap( *this ); + return *this; + } + + template< typename... Args + nsel_REQUIRES_T( + std::is_nothrow_constructible<T, Args&&...>::value + ) + > + value_type & emplace( Args &&... args ) + { + expected( nonstd_lite_in_place(T), std::forward<Args>(args)... ).swap( *this ); + return value(); + } + + template< typename U, typename... Args + nsel_REQUIRES_T( + std::is_nothrow_constructible<T, std::initializer_list<U>&, Args&&...>::value + ) + > + value_type & emplace( std::initializer_list<U> il, Args &&... args ) + { + expected( nonstd_lite_in_place(T), il, std::forward<Args>(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<G>::value + && ( std::is_move_constructible<U>::value || std::is_move_constructible<G>::value ) + ) + swap( expected & other ) noexcept + ( + std::is_nothrow_move_constructible<T>::value && std17::is_nothrow_swappable<T&>::value && + std::is_nothrow_move_constructible<E>::value && std17::is_nothrow_swappable<E&>::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(); + } + + constexpr value_type const & value() const & + { + return has_value() + ? ( contained.value() ) + : ( error_traits<error_type>::rethrow( contained.error() ), contained.value() ); + } + + value_type & value() & + { + return has_value() + ? ( contained.value() ) + : ( error_traits<error_type>::rethrow( contained.error() ), contained.value() ); + } + +#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<error_type>::rethrow( contained.error() ), contained.value() ) ); + } + + nsel_constexpr14 value_type && value() && + { + return std::move( has_value() + ? ( contained.value() ) + : ( error_traits<error_type>::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<U&&, T>::value + ) + > + value_type value_or( U && v ) const & + { + return has_value() + ? contained.value() + : static_cast<T>( std::forward<U>( v ) ); + } + + template< typename U + nsel_REQUIRES_T( + std::is_move_constructible< T>::value + && std::is_convertible<U&&, T>::value + ) + > + value_type value_or( U && v ) && + { + return has_value() + ? std::move( contained.value() ) + : static_cast<T>( std::forward<U>( v ) ); + } + + // unwrap() + +// template <class U, class E> +// constexpr expected<U,E> expected<expected<U,E>,E>::unwrap() const&; + +// template <class T, class E> +// constexpr expected<T,E> expected<T,E>::unwrap() const&; + +// template <class U, class E> +// expected<U,E> expected<expected<U,E>, E>::unwrap() &&; + +// template <class T, class E> +// template expected<T,E> expected<T,E>::unwrap() &&; + + // factories + +// template< typename Ex, typename F> +// expected<T,E> catch_exception(F&& f); + +// template< typename F> +// expected<decltype(func(declval<T>())),E> map(F&& func) ; + +// template< typename F> +// 'see below' bind(F&& func); + +// template< typename F> +// expected<T,E> catch_error(F&& f); + +// template< typename F> +// 'see below' then(F&& func); + +private: + detail::storage_t + < + T + ,E + , std::is_copy_constructible<T>::value && std::is_copy_constructible<E>::value + , std::is_move_constructible<T>::value && std::is_move_constructible<E>::value + > + contained; +}; + +/// class expected, void specialization + +template< typename E > +class expected<void, E> +{ +private: + template< typename, typename > friend class expected; + +public: + using value_type = void; + using error_type = E; + using unexpected_type = nonstd::unexpected_type<E>; + + // 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<G const &, E>::value /*=> explicit */ + ) + > + nsel_constexpr14 explicit expected( nonstd::unexpected_type<G> const & error ) + : contained( false ) + { + contained.construct_error( E{ error.value() } ); + } + + template< typename G = E + nsel_REQUIRES_T( + std::is_convertible<G const &, E>::value /*=> non-explicit */ + ) + > + nsel_constexpr14 /*non-explicit*/ expected( nonstd::unexpected_type<G> const & error ) + : contained( false ) + { + contained.construct_error( error.value() ); + } + + template< typename G = E + nsel_REQUIRES_T( + !std::is_convertible<G&&, E>::value /*=> explicit */ + ) + > + nsel_constexpr14 explicit expected( nonstd::unexpected_type<G> && error ) + : contained( false ) + { + contained.construct_error( E{ std::move( error.value() ) } ); + } + + template< typename G = E + nsel_REQUIRES_T( + std::is_convertible<G&&, E>::value /*=> non-explicit */ + ) + > + nsel_constexpr14 /*non-explicit*/ expected( nonstd::unexpected_type<G> && error ) + : contained( false ) + { + contained.construct_error( std::move( error.value() ) ); + } + + template< typename... Args + nsel_REQUIRES_T( + std::is_constructible<E, Args&&...>::value + ) + > + nsel_constexpr14 explicit expected( unexpect_t, Args&&... args ) + : contained( false ) + { + contained.emplace_error( std::forward<Args>( args )... ); + } + + template< typename U, typename... Args + nsel_REQUIRES_T( + std::is_constructible<E, std::initializer_list<U>, Args&&...>::value + ) + > + nsel_constexpr14 explicit expected( unexpect_t, std::initializer_list<U> il, Args&&... args ) + : contained( false ) + { + contained.emplace_error( il, std::forward<Args>( 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<E>::value && + std::is_nothrow_move_constructible<E>::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<G>::value + && std::is_move_constructible<G>::value + ) + swap( expected & other ) noexcept + ( + std::is_nothrow_move_constructible<E>::value && std17::is_nothrow_swappable<E&>::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<error_type>::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; + } + +// template constexpr 'see below' unwrap() const&; +// +// template 'see below' unwrap() &&; + + // factories + +// template< typename Ex, typename F> +// expected<void,E> catch_exception(F&& f); +// +// template< typename F> +// expected<decltype(func()), E> map(F&& func) ; +// +// template< typename F> +// 'see below' bind(F&& func) ; +// +// template< typename F> +// expected<void,E> catch_error(F&& f); +// +// template< typename F> +// 'see below' then(F&& func); + +private: + detail::storage_t + < + void + , E + , std::is_copy_constructible<E>::value + , std::is_move_constructible<E>::value + > + contained; +}; + +// x.x.4.6 expected<>: comparison operators + +template< typename T1, typename E1, typename T2, typename E2 > +constexpr bool operator==( expected<T1,E1> const & x, expected<T2,E2> const & y ) +{ + return bool(x) != bool(y) ? false : bool(x) == false ? x.error() == y.error() : *x == *y; +} + +template< typename T1, typename E1, typename T2, typename E2 > +constexpr bool operator!=( expected<T1,E1> const & x, expected<T2,E2> const & y ) +{ + return !(x == y); +} + +template< typename E1, typename E2 > +constexpr bool operator==( expected<void,E1> const & x, expected<void,E1> const & y ) +{ + return bool(x) != bool(y) ? false : bool(x) == false ? x.error() == y.error() : true; +} + +#if nsel_P0323R <= 2 + +template< typename T, typename E > +constexpr bool operator<( expected<T,E> const & x, expected<T,E> const & y ) +{ + return (!y) ? false : (!x) ? true : *x < *y; +} + +template< typename T, typename E > +constexpr bool operator>( expected<T,E> const & x, expected<T,E> const & y ) +{ + return (y < x); +} + +template< typename T, typename E > +constexpr bool operator<=( expected<T,E> const & x, expected<T,E> const & y ) +{ + return !(y < x); +} + +template< typename T, typename E > +constexpr bool operator>=( expected<T,E> const & x, expected<T,E> const & y ) +{ + return !(x < y); +} + +#endif + +// x.x.4.7 expected: comparison with T + +template< typename T1, typename E1, typename T2 > +constexpr bool operator==( expected<T1,E1> const & x, T2 const & v ) +{ + return bool(x) ? *x == v : false; +} + +template< typename T1, typename E1, typename T2 > +constexpr bool operator==(T2 const & v, expected<T1,E1> const & x ) +{ + return bool(x) ? v == *x : false; +} + +template< typename T1, typename E1, typename T2 > +constexpr bool operator!=( expected<T1,E1> 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<T1,E1> const & x ) +{ + return bool(x) ? v != *x : true; +} + +#if nsel_P0323R <= 2 + +template< typename T, typename E > +constexpr bool operator<( expected<T,E> const & x, T const & v ) +{ + return bool(x) ? *x < v : true; +} + +template< typename T, typename E > +constexpr bool operator<( T const & v, expected<T,E> const & x ) +{ + return bool(x) ? v < *x : false; +} + +template< typename T, typename E > +constexpr bool operator>( T const & v, expected<T,E> const & x ) +{ + return bool(x) ? *x < v : false; +} + +template< typename T, typename E > +constexpr bool operator>( expected<T,E> const & x, T const & v ) +{ + return bool(x) ? v < *x : false; +} + +template< typename T, typename E > +constexpr bool operator<=( T const & v, expected<T,E> const & x ) +{ + return bool(x) ? ! ( *x < v ) : false; +} + +template< typename T, typename E > +constexpr bool operator<=( expected<T,E> const & x, T const & v ) +{ + return bool(x) ? ! ( v < *x ) : true; +} + +template< typename T, typename E > +constexpr bool operator>=( expected<T,E> const & x, T const & v ) +{ + return bool(x) ? ! ( *x < v ) : false; +} + +template< typename T, typename E > +constexpr bool operator>=( T const & v, expected<T,E> 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<T1,E1> const & x, unexpected_type<E2> const & u ) +{ + return (!x) ? x.get_unexpected() == u : false; +} + +template< typename T1, typename E1 , typename E2 > +constexpr bool operator==( unexpected_type<E2> const & u, expected<T1,E1> const & x ) +{ + return ( x == u ); +} + +template< typename T1, typename E1 , typename E2 > +constexpr bool operator!=( expected<T1,E1> const & x, unexpected_type<E2> const & u ) +{ + return ! ( x == u ); +} + +template< typename T1, typename E1 , typename E2 > +constexpr bool operator!=( unexpected_type<E2> const & u, expected<T1,E1> const & x ) +{ + return ! ( x == u ); +} + +#if nsel_P0323R <= 2 + +template< typename T, typename E > +constexpr bool operator<( expected<T,E> const & x, unexpected_type<E> const & u ) +{ + return (!x) ? ( x.get_unexpected() < u ) : false; +} + +template< typename T, typename E > +constexpr bool operator<( unexpected_type<E> const & u, expected<T,E> const & x ) +{ + return (!x) ? ( u < x.get_unexpected() ) : true ; +} + +template< typename T, typename E > +constexpr bool operator>( expected<T,E> const & x, unexpected_type<E> const & u ) +{ + return ( u < x ); +} + +template< typename T, typename E > +constexpr bool operator>( unexpected_type<E> const & u, expected<T,E> const & x ) +{ + return ( x < u ); +} + +template< typename T, typename E > +constexpr bool operator<=( expected<T,E> const & x, unexpected_type<E> const & u ) +{ + return ! ( u < x ); +} + +template< typename T, typename E > +constexpr bool operator<=( unexpected_type<E> const & u, expected<T,E> const & x) +{ + return ! ( x < u ); +} + +template< typename T, typename E > +constexpr bool operator>=( expected<T,E> const & x, unexpected_type<E> const & u ) +{ + return ! ( u > x ); +} + +template< typename T, typename E > +constexpr bool operator>=( unexpected_type<E> const & u, expected<T,E> const & x ) +{ + return ! ( x > u ); +} + +#endif // nsel_P0323R + +/// x.x.x Specialized algorithms + +template< typename T, typename E + nsel_REQUIRES_T( + ( std::is_void<T>::value || std::is_move_constructible<T>::value ) + && std::is_move_constructible<E>::value + && std17::is_swappable<T>::value + && std17::is_swappable<E>::value ) +> +void swap( expected<T,E> & x, expected<T,E> & 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<T>::type > +{ + return expected< typename std::decay<T>::type >( std::forward<T>( v ) ); +} + +// expected<void> specialization: + +auto inline make_expected() -> expected<void> +{ + return expected<void>( in_place ); +} + +template< typename T > +constexpr auto make_expected_from_current_exception() -> expected<T> +{ + return expected<T>( make_unexpected_from_current_exception() ); +} + +template< typename T > +auto make_expected_from_exception( std::exception_ptr v ) -> expected<T> +{ + return expected<T>( unexpected_type<std::exception_ptr>( std::forward<std::exception_ptr>( v ) ) ); +} + +template< typename T, typename E > +constexpr auto make_expected_from_error( E e ) -> expected<T, typename std::decay<E>::type> +{ + return expected<T, typename std::decay<E>::type>( make_unexpected( e ) ); +} + +template< typename F + nsel_REQUIRES_T( ! std::is_same<typename std::result_of<F()>::type, void>::value ) +> +/*nsel_constexpr14*/ +auto make_expected_from_call( F f ) -> expected< typename std::result_of<F()>::type > +{ + try + { + return make_expected( f() ); + } + catch (...) + { + return make_unexpected_from_current_exception(); + } +} + +template< typename F + nsel_REQUIRES_T( std::is_same<typename std::result_of<F()>::type, void>::value ) +> +/*nsel_constexpr14*/ +auto make_expected_from_call( F f ) -> expected<void> +{ + 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<T,E> > +{ + using result_type = std::size_t; + using argument_type = nonstd::expected<T,E>; + + constexpr result_type operator()(argument_type const & arg) const + { + return arg ? std::hash<T>{}(*arg) : result_type{}; + } +}; + +// TBD - ?? remove? see spec. +template< typename T, typename E > +struct hash< nonstd::expected<T&,E> > +{ + using result_type = std::size_t; + using argument_type = nonstd::expected<T&,E>; + + constexpr result_type operator()(argument_type const & arg) const + { + return arg ? std::hash<T>{}(*arg) : result_type{}; + } +}; + +// TBD - implement +// bool(e), hash<expected<void,E>>()(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>()(e.error()). + +template< typename E > +struct hash< nonstd::expected<void,E> > +{ +}; + +} // 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<E>; +#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 0000000000000000000000000000000000000000..12bc5bafcb30bb8c0a1d3cd54f9af37236c432d5 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/rapidjson/allocators.h @@ -0,0 +1,692 @@ +// 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 <memory> + +#if RAPIDJSON_HAS_CXX11 +#include <type_traits> +#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 <typename BaseAllocator = CrtAllocator> +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<ChunkHeader*>(reinterpret_cast<uint8_t*>(shared) + SIZEOF_SHARED_DATA); + } + static inline uint8_t *GetChunkBuffer(SharedData *shared) + { + return reinterpret_cast<uint8_t*>(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<SharedData*>(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<SharedData*>(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<size_t>(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<ChunkHeader*>(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<uintptr_t>(buf); + if (RAPIDJSON_UNLIKELY(ubuf & mask)) { + const uintptr_t abuf = (ubuf + mask) & ~mask; + RAPIDJSON_ASSERT(size >= abuf - ubuf); + buf = reinterpret_cast<void*>(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<typename, typename = void> + struct IsRefCounted : + public FalseType + { }; + template<typename T> + struct IsRefCounted<T, typename internal::EnableIfCond<T::kRefCounted>::Type> : + public TrueType + { }; +} + +template<typename T, typename A> +inline T* Realloc(A& a, T* old_p, size_t old_n, size_t new_n) +{ + RAPIDJSON_NOEXCEPT_ASSERT(old_n <= SIZE_MAX / sizeof(T) && new_n <= SIZE_MAX / sizeof(T)); + return static_cast<T*>(a.Realloc(old_p, old_n * sizeof(T), new_n * sizeof(T))); +} + +template<typename T, typename A> +inline T *Malloc(A& a, size_t n = 1) +{ + return Realloc<T, A>(a, NULL, 0, n); +} + +template<typename T, typename A> +inline void Free(A& a, T *p, size_t n = 1) +{ + static_cast<void>(Realloc<T, A>(a, p, n, 0)); +} + +#ifdef __GNUC__ +RAPIDJSON_DIAG_PUSH +RAPIDJSON_DIAG_OFF(effc++) // std::allocator can safely be inherited +#endif + +template <typename T, typename BaseAllocator = CrtAllocator> +class StdAllocator : + public std::allocator<T> +{ + typedef std::allocator<T> allocator_type; +#if RAPIDJSON_HAS_CXX11 + typedef std::allocator_traits<allocator_type> 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<typename U> + StdAllocator(const StdAllocator<U, BaseAllocator>& 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<typename U> + struct rebind { + typedef StdAllocator<U, BaseAllocator> 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<value_type>::type &reference; + typedef typename std::add_lvalue_reference<typename std::add_const<value_type>::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 <typename ...Args> + void construct(pointer p, Args&&... args) + { + traits_type::construct(*this, p, std::forward<Args>(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 <typename U> + U* allocate(size_type n = 1, const void* = 0) + { + return RAPIDJSON_NAMESPACE::Malloc<U>(baseAllocator_, n); + } + template <typename U> + void deallocate(U* p, size_type n = 1) + { + RAPIDJSON_NAMESPACE::Free<U>(baseAllocator_, p, n); + } + + pointer allocate(size_type n = 1, const void* = 0) + { + return allocate<value_type>(n); + } + void deallocate(pointer p, size_type n = 1) + { + deallocate<value_type>(p, n); + } + +#if RAPIDJSON_HAS_CXX11 + using is_always_equal = std::is_empty<BaseAllocator>; +#endif + + template<typename U> + bool operator==(const StdAllocator<U, BaseAllocator>& rhs) const RAPIDJSON_NOEXCEPT + { + return baseAllocator_ == rhs.baseAllocator_; + } + template<typename U> + bool operator!=(const StdAllocator<U, BaseAllocator>& rhs) const RAPIDJSON_NOEXCEPT + { + return !operator==(rhs); + } + + //! rapidjson Allocator concept + static const bool kNeedFree = BaseAllocator::kNeedFree; + static const bool kRefCounted = internal::IsRefCounted<BaseAllocator>::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 <typename, typename> + friend class StdAllocator; // access to StdAllocator<!T>.* + + BaseAllocator baseAllocator_; +}; + +#if !RAPIDJSON_HAS_CXX17 // std::allocator<void> deprecated in C++17 +template <typename BaseAllocator> +class StdAllocator<void, BaseAllocator> : + public std::allocator<void> +{ + typedef std::allocator<void> 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<typename U> + StdAllocator(const StdAllocator<U, BaseAllocator>& rhs) RAPIDJSON_NOEXCEPT : + allocator_type(rhs), + baseAllocator_(rhs.baseAllocator_) + { } + + /* implicit */ + StdAllocator(const BaseAllocator& baseAllocator) RAPIDJSON_NOEXCEPT : + allocator_type(), + baseAllocator_(baseAllocator) + { } + + ~StdAllocator() RAPIDJSON_NOEXCEPT + { } + + template<typename U> + struct rebind { + typedef StdAllocator<U, BaseAllocator> other; + }; + + typedef typename allocator_type::value_type value_type; + +private: + template <typename, typename> + friend class StdAllocator; // access to StdAllocator<!T>.* + + 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 0000000000000000000000000000000000000000..fd6513db14a6afcdc3f7f969c9e3f26faf26a829 --- /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 <typename InputStream, typename Encoding = UTF8<> > +class CursorStreamWrapper : public GenericStreamWrapper<InputStream, Encoding> { +public: + typedef typename Encoding::Ch Ch; + + CursorStreamWrapper(InputStream& is): + GenericStreamWrapper<InputStream, Encoding>(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 0000000000000000000000000000000000000000..74089cb9bf2264c9a732e8b85ce5678dabf0535e --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/rapidjson/document.h @@ -0,0 +1,3028 @@ +// 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 <new> // placement new +#include <limits> +#ifdef __cpp_lib_three_way_comparison +#include <compare> +#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 <iterator> // std::random_access_iterator_tag +#endif + +#if RAPIDJSON_USE_MEMBERSMAP +#include <map> // std::multimap +#endif + +RAPIDJSON_NAMESPACE_BEGIN + +// Forward declaration. +template <typename Encoding, typename Allocator> +class GenericValue; + +template <typename Encoding, typename Allocator, typename StackAllocator> +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 <typename Encoding, typename Allocator> +class GenericMember { +public: + GenericValue<Encoding, Allocator> name; //!< name of member (must be a string) + GenericValue<Encoding, Allocator> 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<GenericMember&>(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++ <iterator> header. + + \see GenericMember, GenericValue::MemberIterator, GenericValue::ConstMemberIterator + */ +template <bool Const, typename Encoding, typename Allocator> +class GenericMemberIterator { + + friend class GenericValue<Encoding,Allocator>; + template <bool, typename, typename> friend class GenericMemberIterator; + + typedef GenericMember<Encoding,Allocator> PlainType; + typedef typename internal::MaybeAddConst<Const,PlainType>::Type ValueType; + +public: + //! Iterator type itself + typedef GenericMemberIterator Iterator; + //! Constant iterator type + typedef GenericMemberIterator<true,Encoding,Allocator> ConstIterator; + //! Non-constant iterator type + typedef GenericMemberIterator<false,Encoding,Allocator> 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 Const_> bool operator==(const GenericMemberIterator<Const_, Encoding, Allocator>& that) const { return ptr_ == that.ptr_; } + template <bool Const_> bool operator!=(const GenericMemberIterator<Const_, Encoding, Allocator>& that) const { return ptr_ != that.ptr_; } + template <bool Const_> bool operator<=(const GenericMemberIterator<Const_, Encoding, Allocator>& that) const { return ptr_ <= that.ptr_; } + template <bool Const_> bool operator>=(const GenericMemberIterator<Const_, Encoding, Allocator>& that) const { return ptr_ >= that.ptr_; } + template <bool Const_> bool operator< (const GenericMemberIterator<Const_, Encoding, Allocator>& that) const { return ptr_ < that.ptr_; } + template <bool Const_> bool operator> (const GenericMemberIterator<Const_, Encoding, Allocator>& that) const { return ptr_ > that.ptr_; } + +#ifdef __cpp_lib_three_way_comparison + template <bool Const_> std::strong_ordering operator<=>(const GenericMemberIterator<Const_, Encoding, Allocator>& 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 <bool Const, typename Encoding, typename Allocator> +class GenericMemberIterator; + +//! non-const GenericMemberIterator +template <typename Encoding, typename Allocator> +class GenericMemberIterator<false,Encoding,Allocator> { +public: + //! use plain pointer as iterator type + typedef GenericMember<Encoding,Allocator>* Iterator; +}; +//! const GenericMemberIterator +template <typename Encoding, typename Allocator> +class GenericMemberIterator<true,Encoding,Allocator> { +public: + //! use plain const pointer as iterator type + typedef const GenericMember<Encoding,Allocator>* 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<typename CharType> +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<SizeType N> + 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<SizeType N> + GenericStringRef(CharType (&str)[N]) /* = delete */; + //! Copy assignment operator not permitted - immutable type + GenericStringRef& operator=(const GenericStringRef& rhs) /* = delete */; +}; + +template<typename CharType> +const CharType GenericStringRef<CharType>::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<typename CharType> +inline GenericStringRef<CharType> StringRef(const CharType* str) { + return GenericStringRef<CharType>(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<typename CharType> +inline GenericStringRef<CharType> StringRef(const CharType* str, size_t length) { + return GenericStringRef<CharType>(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<typename CharType> +inline GenericStringRef<CharType> StringRef(const std::basic_string<CharType>& str) { + return GenericStringRef<CharType>(str.data(), SizeType(str.size())); +} +#endif + +/////////////////////////////////////////////////////////////////////////////// +// GenericValue type traits +namespace internal { + +template <typename T, typename Encoding = void, typename Allocator = void> +struct IsGenericValueImpl : FalseType {}; + +// select candidates according to nested encoding and allocator types +template <typename T> struct IsGenericValueImpl<T, typename Void<typename T::EncodingType>::Type, typename Void<typename T::AllocatorType>::Type> + : IsBaseOf<GenericValue<typename T::EncodingType, typename T::AllocatorType>, T>::Type {}; + +// helper to match arbitrary GenericValue instantiations, including derived classes +template <typename T> struct IsGenericValue : IsGenericValueImpl<T>::Type {}; + +} // namespace internal + +/////////////////////////////////////////////////////////////////////////////// +// TypeHelper + +namespace internal { + +template <typename ValueType, typename T> +struct TypeHelper {}; + +template<typename ValueType> +struct TypeHelper<ValueType, bool> { + 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<typename ValueType> +struct TypeHelper<ValueType, int> { + 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<typename ValueType> +struct TypeHelper<ValueType, unsigned> { + 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<typename ValueType> +struct TypeHelper<ValueType, long> { + 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<typename ValueType> +struct TypeHelper<ValueType, unsigned long> { + 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<typename ValueType> +struct TypeHelper<ValueType, int64_t> { + 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<typename ValueType> +struct TypeHelper<ValueType, uint64_t> { + 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<typename ValueType> +struct TypeHelper<ValueType, double> { + 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<typename ValueType> +struct TypeHelper<ValueType, float> { + 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<typename ValueType> +struct TypeHelper<ValueType, const typename ValueType::Ch*> { + 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<typename ValueType> +struct TypeHelper<ValueType, std::basic_string<typename ValueType::Ch> > { + typedef std::basic_string<typename ValueType::Ch> 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<typename ValueType> +struct TypeHelper<ValueType, typename ValueType::Array> { + 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<typename ValueType> +struct TypeHelper<ValueType, typename ValueType::ConstArray> { + typedef typename ValueType::ConstArray ArrayType; + static bool Is(const ValueType& v) { return v.IsArray(); } + static ArrayType Get(const ValueType& v) { return v.GetArray(); } +}; + +template<typename ValueType> +struct TypeHelper<ValueType, typename ValueType::Object> { + 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<typename ValueType> +struct TypeHelper<ValueType, typename ValueType::ConstObject> { + 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 <bool, typename> class GenericArray; +template <bool, typename> 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 <typename Encoding, typename Allocator = RAPIDJSON_DEFAULT_ALLOCATOR > +class GenericValue { +public: + //! Name-value pair in an object. + typedef GenericMember<Encoding, Allocator> 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<Ch> StringRefType; //!< Reference to a constant string + typedef typename GenericMemberIterator<false,Encoding,Allocator>::Iterator MemberIterator; //!< Member iterator for iterating in object. + typedef typename GenericMemberIterator<true,Encoding,Allocator>::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<Encoding, Allocator> ValueType; //!< Value type of itself. + typedef GenericArray<false, ValueType> Array; + typedef GenericArray<true, ValueType> ConstArray; + typedef GenericObject<false, ValueType> Object; + typedef GenericObject<true, ValueType> 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 <typename StackAllocator> + GenericValue(GenericDocument<Encoding,Allocator,StackAllocator>&& rhs); + + //! Move assignment from a GenericDocument is not permitted. + template <typename StackAllocator> + GenericValue& operator=(GenericDocument<Encoding,Allocator,StackAllocator>&& 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 <typename SourceAllocator> + GenericValue(const GenericValue<Encoding,SourceAllocator>& 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<GenericValue*>(allocator.Malloc(count * sizeof(GenericValue))); + const GenericValue<Encoding,SourceAllocator>* 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<const Data*>(&rhs.data_); + } + else + SetStringRaw(StringRef(rhs.GetString(), rhs.GetStringLength()), allocator); + break; + default: + data_.f.flags = rhs.data_.f.flags; + data_ = *reinterpret_cast<const Data*>(&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 <typename T> + explicit GenericValue(T b, RAPIDJSON_ENABLEIF((internal::IsSame<bool, T>))) RAPIDJSON_NOEXCEPT // See #472 +#else + explicit GenericValue(bool b) RAPIDJSON_NOEXCEPT +#endif + : data_() { + // safe-guard against failing SFINAE + RAPIDJSON_STATIC_ASSERT((internal::IsSame<bool,T>::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<uint64_t>(i64) & RAPIDJSON_UINT64_C2(0xFFFFFFFF, 0x00000000))) + data_.f.flags |= kUintFlag; + if (!(static_cast<uint64_t>(i64) & RAPIDJSON_UINT64_C2(0xFFFFFFFF, 0x80000000))) + data_.f.flags |= kIntFlag; + } + else if (i64 >= static_cast<int64_t>(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<double>(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<Ch>& 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<Allocator>::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<Ch*>(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 <typename T> + RAPIDJSON_DISABLEIF_RETURN((internal::IsPointer<T>), (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 <typename SourceAllocator> + GenericValue& CopyFrom(const GenericValue<Encoding, SourceAllocator>& rhs, Allocator& allocator, bool copyConstStrings = false) { + RAPIDJSON_ASSERT(static_cast<void*>(this) != static_cast<void const*>(&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 <typename SourceAllocator> + bool operator==(const GenericValue<Encoding, SourceAllocator>& rhs) const { + typedef GenericValue<Encoding, SourceAllocator> 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<Ch>& 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 <typename T> RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr<internal::IsPointer<T>,internal::IsGenericValue<T> >), (bool)) operator==(const T& rhs) const { return *this == GenericValue(rhs); } + + //! Not-equal-to operator + /*! \return !(*this == rhs) + */ + template <typename SourceAllocator> + bool operator!=(const GenericValue<Encoding, SourceAllocator>& 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 <typename T> RAPIDJSON_DISABLEIF_RETURN((internal::IsGenericValue<T>), (bool)) operator!=(const T& rhs) const { return !(*this == rhs); } + +#ifndef __cpp_lib_three_way_comparison + //! Equal-to operator with arbitrary types (symmetric version) + /*! \return (rhs == lhs) + */ + template <typename T> friend RAPIDJSON_DISABLEIF_RETURN((internal::IsGenericValue<T>), (bool)) operator==(const T& lhs, const GenericValue& rhs) { return rhs == lhs; } + + //! Not-Equal-to operator with arbitrary types (symmetric version) + /*! \return !(rhs == lhs) + */ + template <typename T> friend RAPIDJSON_DISABLEIF_RETURN((internal::IsGenericValue<T>), (bool)) operator!=(const T& lhs, const GenericValue& rhs) { return !(rhs == lhs); } + //@} +#endif + + //!@name Type + //@{ + + Type GetType() const { return static_cast<Type>(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<double>(u); + return (d >= 0.0) + && (d < static_cast<double>((std::numeric_limits<uint64_t>::max)())) + && (u == static_cast<uint64_t>(d)); + } + if (IsInt64()) { + int64_t i = GetInt64(); + volatile double d = static_cast<double>(i); + return (d >= static_cast<double>((std::numeric_limits<int64_t>::min)())) + && (d < static_cast<double>((std::numeric_limits<int64_t>::max)())) + && (i == static_cast<int64_t>(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<double>(-(std::numeric_limits<float>::max)()) + || a > static_cast<double>((std::numeric_limits<float>::max)())) + return false; + double b = static_cast<double>(static_cast<float>(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 <typename T> + RAPIDJSON_DISABLEIF_RETURN((internal::NotExpr<internal::IsSame<typename internal::RemoveConst<T>::Type, Ch> >),(GenericValue&)) operator[](T* name) { + GenericValue n(StringRef(name)); + return (*this)[n]; + } + template <typename T> + RAPIDJSON_DISABLEIF_RETURN((internal::NotExpr<internal::IsSame<typename internal::RemoveConst<T>::Type, Ch> >),(const GenericValue&)) operator[](T* name) const { return const_cast<GenericValue&>(*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 <typename SourceAllocator> + GenericValue& operator[](const GenericValue<Encoding, SourceAllocator>& name) { + MemberIterator member = FindMember(name); + if (member != MemberEnd()) + return member->value; + else { + RAPIDJSON_ASSERT(false); // see above note + + // This will generate -Wexit-time-destructors in clang + // static GenericValue NullValue; + // return NullValue; + + // Use static buffer and placement-new to prevent destruction + static GenericValue buffer; + return *new (reinterpret_cast<char *>(&buffer)) GenericValue(); + } + } + template <typename SourceAllocator> + const GenericValue& operator[](const GenericValue<Encoding, SourceAllocator>& name) const { return const_cast<GenericValue&>(*this)[name]; } + +#if RAPIDJSON_HAS_STDSTRING + //! Get a value from an object associated with name (string object). + GenericValue& operator[](const std::basic_string<Ch>& name) { return (*this)[GenericValue(StringRef(name))]; } + const GenericValue& operator[](const std::basic_string<Ch>& 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<Ch>& 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 <typename SourceAllocator> + bool HasMember(const GenericValue<Encoding, SourceAllocator>& 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<GenericValue&>(*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 <typename SourceAllocator> + MemberIterator FindMember(const GenericValue<Encoding, SourceAllocator>& name) { + RAPIDJSON_ASSERT(IsObject()); + RAPIDJSON_ASSERT(name.IsString()); + return DoFindMember(name); + } + template <typename SourceAllocator> ConstMemberIterator FindMember(const GenericValue<Encoding, SourceAllocator>& name) const { return const_cast<GenericValue&>(*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<Ch>& name) { return FindMember(GenericValue(StringRef(name))); } + ConstMemberIterator FindMember(const std::basic_string<Ch>& 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<Ch>& 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 <typename T> + RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr<internal::IsPointer<T>, internal::IsGenericValue<T> >), (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 <typename T> + RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr<internal::IsPointer<T>, internal::IsGenericValue<T> >), (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<Ch>& name) { return RemoveMember(GenericValue(StringRef(name))); } +#endif + + template <typename SourceAllocator> + bool RemoveMember(const GenericValue<Encoding, SourceAllocator>& 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<Ch>& name) { return EraseMember(GenericValue(StringRef(name))); } +#endif + + template <typename SourceAllocator> + bool EraseMember(const GenericValue<Encoding, SourceAllocator>& 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<GenericValue&>(*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<GenericValue&>(*this).Begin(); } + //! Constant \em past-the-end element iterator + /*! \pre IsArray() == true */ + ConstValueIterator End() const { return const_cast<GenericValue&>(*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<GenericValue*>(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<StringRefType>(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 <typename T> + RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr<internal::IsPointer<T>, internal::IsGenericValue<T> >), (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<void*>(pos), last, static_cast<size_t>(End() - last) * sizeof(GenericValue)); + data_.a.size -= static_cast<SizeType>(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<double>(data_.n.i64); // int64_t -> double (may lose precision) + RAPIDJSON_ASSERT((data_.f.flags & kUint64Flag) != 0); return static_cast<double>(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<float>(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<double>(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<Ch>& 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<Ch> + */ + template <typename T> + bool Is() const { return internal::TypeHelper<ValueType, T>::Is(*this); } + + template <typename T> + T Get() const { return internal::TypeHelper<ValueType, T>::Get(*this); } + + template <typename T> + T Get() { return internal::TypeHelper<ValueType, T>::Get(*this); } + + template<typename T> + ValueType& Set(const T& data) { return internal::TypeHelper<ValueType, T>::Set(*this, data); } + + template<typename T> + ValueType& Set(const T& data, AllocatorType& allocator) { return internal::TypeHelper<ValueType, T>::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 <typename Handler> + 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 <typename, typename> friend class GenericValue; + template <typename, typename, typename> 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<int>(kTrueType) | static_cast<int>(kBoolFlag), + kFalseFlag = static_cast<int>(kFalseType) | static_cast<int>(kBoolFlag), + kNumberIntFlag = static_cast<int>(kNumberType) | static_cast<int>(kNumberFlag | kIntFlag | kInt64Flag), + kNumberUintFlag = static_cast<int>(kNumberType) | static_cast<int>(kNumberFlag | kUintFlag | kUint64Flag | kInt64Flag), + kNumberInt64Flag = static_cast<int>(kNumberType) | static_cast<int>(kNumberFlag | kInt64Flag), + kNumberUint64Flag = static_cast<int>(kNumberType) | static_cast<int>(kNumberFlag | kUint64Flag), + kNumberDoubleFlag = static_cast<int>(kNumberType) | static_cast<int>(kNumberFlag | kDoubleFlag), + kNumberAnyFlag = static_cast<int>(kNumberType) | static_cast<int>(kNumberFlag | kIntFlag | kInt64Flag | kUintFlag | kUint64Flag | kDoubleFlag), + kConstStringFlag = static_cast<int>(kStringType) | static_cast<int>(kStringFlag), + kCopyStringFlag = static_cast<int>(kStringType) | static_cast<int>(kStringFlag | kCopyFlag), + kShortStringFlag = static_cast<int>(kStringType) | static_cast<int>(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<Flag*>(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<Ch>(MaxSize - len); } + inline SizeType GetLength() const { return static_cast<SizeType>(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<const Data, SizeType> Pair; + typedef std::multimap<Data, SizeType, Less, StdAllocator<Pair, Allocator> > 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<SizeType*>(reinterpret_cast<uintptr_t>(&map) + + RAPIDJSON_ALIGN(sizeof(Map*))); + } + + static RAPIDJSON_FORCEINLINE Member* GetMapMembers(Map* &map) { + return reinterpret_cast<Member*>(reinterpret_cast<uintptr_t>(&map) + + RAPIDJSON_ALIGN(sizeof(Map*)) + + RAPIDJSON_ALIGN(sizeof(SizeType))); + } + + static RAPIDJSON_FORCEINLINE MapIterator* GetMapIterators(Map* &map) { + return reinterpret_cast<MapIterator*>(reinterpret_cast<uintptr_t>(&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<Map**>(reinterpret_cast<uintptr_t>(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<Map**>(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<void*>(GetMapMembers(*newMap)), + static_cast<void*>(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 <typename SourceAllocator> + MemberIterator DoFindMember(const GenericValue<Encoding, SourceAllocator>& name) { + if (Member* members = GetMembersPointer()) { + Map* &map = GetMap(members); + MapIterator mit = map->find(reinterpret_cast<const Data&>(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<Member>(allocator, capacity); + } + + void DoReserveMembers(SizeType newCapacity, Allocator& allocator) { + ObjectData& o = data_.o; + if (newCapacity > o.capacity) { + Member* newMembers = Realloc<Member>(allocator, GetMembersPointer(), o.capacity, newCapacity); + RAPIDJSON_SETPOINTER(Member, o.members, newMembers); + o.capacity = newCapacity; + } + } + + template <typename SourceAllocator> + MemberIterator DoFindMember(const GenericValue<Encoding, SourceAllocator>& 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<SizeType>(&*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<void*>(&*itr), &*next, sizeof(Member)); + SizeType mpos = static_cast<SizeType>(itr - beg); + new (&mit[mpos]) MapIterator(DropMapIterator(mit[next - beg])); + mit[mpos]->second = mpos; + } + } +#else + std::memmove(static_cast<void*>(&*pos), &*last, + static_cast<size_t>(end - last) * sizeof(Member)); +#endif + o.size -= static_cast<SizeType>(last - first); + return pos; + } + + template <typename SourceAllocator> + void DoCopyMembers(const GenericValue<Encoding,SourceAllocator>& 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<Encoding,SourceAllocator>::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<GenericValue*>(allocator.Malloc(count * sizeof(GenericValue))); + SetElementsPointer(e); + std::memcpy(static_cast<void*>(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<void*>(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<Ch *>(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 <typename SourceAllocator> + bool StringEqual(const GenericValue<Encoding, SourceAllocator>& 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<UTF8<> > 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 <typename Encoding, typename Allocator = RAPIDJSON_DEFAULT_ALLOCATOR, typename StackAllocator = RAPIDJSON_DEFAULT_STACK_ALLOCATOR > +class GenericDocument : public GenericValue<Encoding, Allocator> { +public: + typedef typename Encoding::Ch Ch; //!< Character type derived from Encoding. + typedef GenericValue<Encoding, Allocator> 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<Encoding, Allocator>(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<ValueType>(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<ValueType>(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 <tt>bool f(Handler)</tt> prototype. + \param g Generator functor which sends SAX events to the parameter. + \return The document itself for fluent API. + */ + template <typename Generator> + 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<ValueType>(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 <unsigned parseFlags, typename SourceEncoding, typename InputStream> + GenericDocument& ParseStream(InputStream& is) { + GenericReader<SourceEncoding, Encoding, StackAllocator> reader( + stack_.HasAllocator() ? &stack_.GetAllocator() : 0); + ClearStackOnExit scope(*this); + parseResult_ = reader.template Parse<parseFlags>(is, *this); + if (parseResult_) { + RAPIDJSON_ASSERT(stack_.GetSize() == sizeof(ValueType)); // Got one and only one root object + ValueType::operator=(*stack_.template Pop<ValueType>(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 <unsigned parseFlags, typename InputStream> + GenericDocument& ParseStream(InputStream& is) { + return ParseStream<parseFlags, Encoding, InputStream>(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 <typename InputStream> + GenericDocument& ParseStream(InputStream& is) { + return ParseStream<kParseDefaultFlags, Encoding, InputStream>(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 <unsigned parseFlags> + GenericDocument& ParseInsitu(Ch* str) { + GenericInsituStringStream<Encoding> s(str); + return ParseStream<parseFlags | kParseInsituFlag>(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<kParseDefaultFlags>(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 <unsigned parseFlags, typename SourceEncoding> + GenericDocument& Parse(const typename SourceEncoding::Ch* str) { + RAPIDJSON_ASSERT(!(parseFlags & kParseInsituFlag)); + GenericStringStream<SourceEncoding> s(str); + return ParseStream<parseFlags, SourceEncoding>(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 <unsigned parseFlags> + GenericDocument& Parse(const Ch* str) { + return Parse<parseFlags, Encoding>(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<kParseDefaultFlags>(str); + } + + template <unsigned parseFlags, typename SourceEncoding> + GenericDocument& Parse(const typename SourceEncoding::Ch* str, size_t length) { + RAPIDJSON_ASSERT(!(parseFlags & kParseInsituFlag)); + MemoryStream ms(reinterpret_cast<const char*>(str), length * sizeof(typename SourceEncoding::Ch)); + EncodedInputStream<SourceEncoding, MemoryStream> is(ms); + ParseStream<parseFlags, SourceEncoding>(is); + return *this; + } + + template <unsigned parseFlags> + GenericDocument& Parse(const Ch* str, size_t length) { + return Parse<parseFlags, Encoding>(str, length); + } + + GenericDocument& Parse(const Ch* str, size_t length) { + return Parse<kParseDefaultFlags>(str, length); + } + +#if RAPIDJSON_HAS_STDSTRING + template <unsigned parseFlags, typename SourceEncoding> + GenericDocument& Parse(const std::basic_string<typename SourceEncoding::Ch>& str) { + // c_str() is constant complexity according to standard. Should be faster than Parse(const char*, size_t) + return Parse<parseFlags, SourceEncoding>(str.c_str()); + } + + template <unsigned parseFlags> + GenericDocument& Parse(const std::basic_string<Ch>& str) { + return Parse<parseFlags, Encoding>(str.c_str()); + } + + GenericDocument& Parse(const std::basic_string<Ch>& str) { + return Parse<kParseDefaultFlags>(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 <typename,typename,typename> friend class GenericReader; // for parsing + template <typename, typename> friend class GenericValue; // for deep copying + +public: + // Implementation of Handler + bool Null() { new (stack_.template Push<ValueType>()) ValueType(); return true; } + bool Bool(bool b) { new (stack_.template Push<ValueType>()) ValueType(b); return true; } + bool Int(int i) { new (stack_.template Push<ValueType>()) ValueType(i); return true; } + bool Uint(unsigned i) { new (stack_.template Push<ValueType>()) ValueType(i); return true; } + bool Int64(int64_t i) { new (stack_.template Push<ValueType>()) ValueType(i); return true; } + bool Uint64(uint64_t i) { new (stack_.template Push<ValueType>()) ValueType(i); return true; } + bool Double(double d) { new (stack_.template Push<ValueType>()) ValueType(d); return true; } + + bool RawNumber(const Ch* str, SizeType length, bool copy) { + if (copy) + new (stack_.template Push<ValueType>()) ValueType(str, length, GetAllocator()); + else + new (stack_.template Push<ValueType>()) ValueType(str, length); + return true; + } + + bool String(const Ch* str, SizeType length, bool copy) { + if (copy) + new (stack_.template Push<ValueType>()) ValueType(str, length, GetAllocator()); + else + new (stack_.template Push<ValueType>()) ValueType(str, length); + return true; + } + + bool StartObject() { new (stack_.template Push<ValueType>()) 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<typename ValueType::Member>(memberCount); + stack_.template Top<ValueType>()->SetObjectRaw(members, memberCount, GetAllocator()); + return true; + } + + bool StartArray() { new (stack_.template Push<ValueType>()) ValueType(kArrayType); return true; } + + bool EndArray(SizeType elementCount) { + ValueType* elements = stack_.template Pop<ValueType>(elementCount); + stack_.template Top<ValueType>()->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<ValueType>(1))->~ValueType(); + else + stack_.Clear(); + stack_.ShrinkToFit(); + } + + void Destroy() { + RAPIDJSON_DELETE(ownAllocator_); + } + + static const size_t kDefaultStackCapacity = 1024; + Allocator* allocator_; + Allocator* ownAllocator_; + internal::Stack<StackAllocator> stack_; + ParseResult parseResult_; +}; + +//! GenericDocument with UTF8 encoding +typedef GenericDocument<UTF8<> > 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 <bool Const, typename ValueT> +class GenericArray { +public: + typedef GenericArray<true, ValueT> ConstArray; + typedef GenericArray<false, ValueT> Array; + typedef ValueT PlainType; + typedef typename internal::MaybeAddConst<Const,PlainType>::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 <typename, typename> + 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 <typename T> RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr<internal::IsPointer<T>, internal::IsGenericValue<T> >), (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 <bool Const, typename ValueT> +class GenericObject { +public: + typedef GenericObject<true, ValueT> ConstObject; + typedef GenericObject<false, ValueT> Object; + typedef ValueT PlainType; + typedef typename internal::MaybeAddConst<Const,PlainType>::Type ValueType; + typedef GenericMemberIterator<Const, typename ValueT::EncodingType, typename ValueT::AllocatorType> MemberIterator; // This may be const or non-const iterator + typedef GenericMemberIterator<true, typename ValueT::EncodingType, typename ValueT::AllocatorType> ConstMemberIterator; + typedef typename ValueType::AllocatorType AllocatorType; + typedef typename ValueType::StringRefType StringRefType; + typedef typename ValueType::EncodingType EncodingType; + typedef typename ValueType::Ch Ch; + + template <typename, typename> + 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 <typename T> ValueType& operator[](T* name) const { return value_[name]; } + template <typename SourceAllocator> ValueType& operator[](const GenericValue<EncodingType, SourceAllocator>& name) const { return value_[name]; } +#if RAPIDJSON_HAS_STDSTRING + ValueType& operator[](const std::basic_string<Ch>& 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<Ch>& name) const { return value_.HasMember(name); } +#endif + template <typename SourceAllocator> bool HasMember(const GenericValue<EncodingType, SourceAllocator>& name) const { return value_.HasMember(name); } + MemberIterator FindMember(const Ch* name) const { return value_.FindMember(name); } + template <typename SourceAllocator> MemberIterator FindMember(const GenericValue<EncodingType, SourceAllocator>& name) const { return value_.FindMember(name); } +#if RAPIDJSON_HAS_STDSTRING + MemberIterator FindMember(const std::basic_string<Ch>& 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<Ch>& value, AllocatorType& allocator) const { value_.AddMember(name, value, allocator); return *this; } +#endif + template <typename T> RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr<internal::IsPointer<T>, internal::IsGenericValue<T> >), (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 <typename T> RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr<internal::IsPointer<T>, internal::IsGenericValue<T> >), (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<Ch>& name) const { return value_.RemoveMember(name); } +#endif + template <typename SourceAllocator> bool RemoveMember(const GenericValue<EncodingType, SourceAllocator>& 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<Ch>& name) const { return EraseMember(ValueType(StringRef(name))); } +#endif + template <typename SourceAllocator> bool EraseMember(const GenericValue<EncodingType, SourceAllocator>& 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 0000000000000000000000000000000000000000..cf046b89235f5732768dbca7a0fc2cd2bb99a5e4 --- /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 <typename Encoding, typename InputByteStream> +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<UTF8<>, MemoryStream> { +public: + typedef UTF8<>::Ch Ch; + + EncodedInputStream(MemoryStream& is) : is_(is) { + if (static_cast<unsigned char>(is_.Peek()) == 0xEFu) is_.Take(); + if (static_cast<unsigned char>(is_.Peek()) == 0xBBu) is_.Take(); + if (static_cast<unsigned char>(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 <typename Encoding, typename OutputByteStream> +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<Ch>::x, UTF16LE<Ch>::x, UTF16BE<Ch>::x, UTF32LE<Ch>::x, UTF32BE<Ch>::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 <typename CharType, typename InputByteStream> +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<const unsigned char *>(is_->Peek4()); + if (!c) + return; + + unsigned bom = static_cast<unsigned>(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 <typename CharType, typename OutputByteStream> +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 0000000000000000000000000000000000000000..50ad18bdc08cd0a2c1b19c0bc8f956fd16719a67 --- /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<typename OutputStream> + 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 <typename InputStream> + 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 <typename InputStream, typename OutputStream> + 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 <typename InputByteStream> + static CharType TakeBOM(InputByteStream& is); + + //! Take a character from input byte stream. + template <typename InputByteStream> + static Ch Take(InputByteStream& is); + + //! Put BOM to output byte stream. + template <typename OutputByteStream> + static void PutBOM(OutputByteStream& os); + + //! Put a character to output byte stream. + template <typename OutputByteStream> + 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<typename CharType = char> +struct UTF8 { + typedef CharType Ch; + + enum { supportUnicode = 1 }; + + template<typename OutputStream> + static void Encode(OutputStream& os, unsigned codepoint) { + if (codepoint <= 0x7F) + os.Put(static_cast<Ch>(codepoint & 0xFF)); + else if (codepoint <= 0x7FF) { + os.Put(static_cast<Ch>(0xC0 | ((codepoint >> 6) & 0xFF))); + os.Put(static_cast<Ch>(0x80 | ((codepoint & 0x3F)))); + } + else if (codepoint <= 0xFFFF) { + os.Put(static_cast<Ch>(0xE0 | ((codepoint >> 12) & 0xFF))); + os.Put(static_cast<Ch>(0x80 | ((codepoint >> 6) & 0x3F))); + os.Put(static_cast<Ch>(0x80 | (codepoint & 0x3F))); + } + else { + RAPIDJSON_ASSERT(codepoint <= 0x10FFFF); + os.Put(static_cast<Ch>(0xF0 | ((codepoint >> 18) & 0xFF))); + os.Put(static_cast<Ch>(0x80 | ((codepoint >> 12) & 0x3F))); + os.Put(static_cast<Ch>(0x80 | ((codepoint >> 6) & 0x3F))); + os.Put(static_cast<Ch>(0x80 | (codepoint & 0x3F))); + } + } + + template<typename OutputStream> + static void EncodeUnsafe(OutputStream& os, unsigned codepoint) { + if (codepoint <= 0x7F) + PutUnsafe(os, static_cast<Ch>(codepoint & 0xFF)); + else if (codepoint <= 0x7FF) { + PutUnsafe(os, static_cast<Ch>(0xC0 | ((codepoint >> 6) & 0xFF))); + PutUnsafe(os, static_cast<Ch>(0x80 | ((codepoint & 0x3F)))); + } + else if (codepoint <= 0xFFFF) { + PutUnsafe(os, static_cast<Ch>(0xE0 | ((codepoint >> 12) & 0xFF))); + PutUnsafe(os, static_cast<Ch>(0x80 | ((codepoint >> 6) & 0x3F))); + PutUnsafe(os, static_cast<Ch>(0x80 | (codepoint & 0x3F))); + } + else { + RAPIDJSON_ASSERT(codepoint <= 0x10FFFF); + PutUnsafe(os, static_cast<Ch>(0xF0 | ((codepoint >> 18) & 0xFF))); + PutUnsafe(os, static_cast<Ch>(0x80 | ((codepoint >> 12) & 0x3F))); + PutUnsafe(os, static_cast<Ch>(0x80 | ((codepoint >> 6) & 0x3F))); + PutUnsafe(os, static_cast<Ch>(0x80 | (codepoint & 0x3F))); + } + } + + template <typename InputStream> + static bool Decode(InputStream& is, unsigned* codepoint) { +#define RAPIDJSON_COPY() c = is.Take(); *codepoint = (*codepoint << 6) | (static_cast<unsigned char>(c) & 0x3Fu) +#define RAPIDJSON_TRANS(mask) result &= ((GetRange(static_cast<unsigned char>(c)) & mask) != 0) +#define RAPIDJSON_TAIL() RAPIDJSON_COPY(); RAPIDJSON_TRANS(0x70) + typename InputStream::Ch c = is.Take(); + if (!(c & 0x80)) { + *codepoint = static_cast<unsigned char>(c); + return true; + } + + unsigned char type = GetRange(static_cast<unsigned char>(c)); + if (type >= 32) { + *codepoint = 0; + } else { + *codepoint = (0xFFu >> type) & static_cast<unsigned char>(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 <typename InputStream, typename OutputStream> + static bool Validate(InputStream& is, OutputStream& os) { +#define RAPIDJSON_COPY() os.Put(c = is.Take()) +#define RAPIDJSON_TRANS(mask) result &= ((GetRange(static_cast<unsigned char>(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<unsigned char>(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 <typename InputByteStream> + static CharType TakeBOM(InputByteStream& is) { + RAPIDJSON_STATIC_ASSERT(sizeof(typename InputByteStream::Ch) == 1); + typename InputByteStream::Ch c = Take(is); + if (static_cast<unsigned char>(c) != 0xEFu) return c; + c = is.Take(); + if (static_cast<unsigned char>(c) != 0xBBu) return c; + c = is.Take(); + if (static_cast<unsigned char>(c) != 0xBFu) return c; + c = is.Take(); + return c; + } + + template <typename InputByteStream> + static Ch Take(InputByteStream& is) { + RAPIDJSON_STATIC_ASSERT(sizeof(typename InputByteStream::Ch) == 1); + return static_cast<Ch>(is.Take()); + } + + template <typename OutputByteStream> + static void PutBOM(OutputByteStream& os) { + RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputByteStream::Ch) == 1); + os.Put(static_cast<typename OutputByteStream::Ch>(0xEFu)); + os.Put(static_cast<typename OutputByteStream::Ch>(0xBBu)); + os.Put(static_cast<typename OutputByteStream::Ch>(0xBFu)); + } + + template <typename OutputByteStream> + static void Put(OutputByteStream& os, Ch c) { + RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputByteStream::Ch) == 1); + os.Put(static_cast<typename OutputByteStream::Ch>(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<typename CharType = wchar_t> +struct UTF16 { + typedef CharType Ch; + RAPIDJSON_STATIC_ASSERT(sizeof(Ch) >= 2); + + enum { supportUnicode = 1 }; + + template<typename OutputStream> + 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<typename OutputStream::Ch>(codepoint)); + } + else { + RAPIDJSON_ASSERT(codepoint <= 0x10FFFF); + unsigned v = codepoint - 0x10000; + os.Put(static_cast<typename OutputStream::Ch>((v >> 10) | 0xD800)); + os.Put(static_cast<typename OutputStream::Ch>((v & 0x3FF) | 0xDC00)); + } + } + + + template<typename OutputStream> + 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<typename OutputStream::Ch>(codepoint)); + } + else { + RAPIDJSON_ASSERT(codepoint <= 0x10FFFF); + unsigned v = codepoint - 0x10000; + PutUnsafe(os, static_cast<typename OutputStream::Ch>((v >> 10) | 0xD800)); + PutUnsafe(os, static_cast<typename OutputStream::Ch>((v & 0x3FF) | 0xDC00)); + } + } + + template <typename InputStream> + 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<unsigned>(c); + return true; + } + else if (c <= 0xDBFF) { + *codepoint = (static_cast<unsigned>(c) & 0x3FF) << 10; + c = is.Take(); + *codepoint |= (static_cast<unsigned>(c) & 0x3FF); + *codepoint += 0x10000; + return c >= 0xDC00 && c <= 0xDFFF; + } + return false; + } + + template <typename InputStream, typename OutputStream> + 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<typename OutputStream::Ch>(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<typename CharType = wchar_t> +struct UTF16LE : UTF16<CharType> { + template <typename InputByteStream> + static CharType TakeBOM(InputByteStream& is) { + RAPIDJSON_STATIC_ASSERT(sizeof(typename InputByteStream::Ch) == 1); + CharType c = Take(is); + return static_cast<uint16_t>(c) == 0xFEFFu ? Take(is) : c; + } + + template <typename InputByteStream> + static CharType Take(InputByteStream& is) { + RAPIDJSON_STATIC_ASSERT(sizeof(typename InputByteStream::Ch) == 1); + unsigned c = static_cast<uint8_t>(is.Take()); + c |= static_cast<unsigned>(static_cast<uint8_t>(is.Take())) << 8; + return static_cast<CharType>(c); + } + + template <typename OutputByteStream> + static void PutBOM(OutputByteStream& os) { + RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputByteStream::Ch) == 1); + os.Put(static_cast<typename OutputByteStream::Ch>(0xFFu)); + os.Put(static_cast<typename OutputByteStream::Ch>(0xFEu)); + } + + template <typename OutputByteStream> + static void Put(OutputByteStream& os, CharType c) { + RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputByteStream::Ch) == 1); + os.Put(static_cast<typename OutputByteStream::Ch>(static_cast<unsigned>(c) & 0xFFu)); + os.Put(static_cast<typename OutputByteStream::Ch>((static_cast<unsigned>(c) >> 8) & 0xFFu)); + } +}; + +//! UTF-16 big endian encoding. +template<typename CharType = wchar_t> +struct UTF16BE : UTF16<CharType> { + template <typename InputByteStream> + static CharType TakeBOM(InputByteStream& is) { + RAPIDJSON_STATIC_ASSERT(sizeof(typename InputByteStream::Ch) == 1); + CharType c = Take(is); + return static_cast<uint16_t>(c) == 0xFEFFu ? Take(is) : c; + } + + template <typename InputByteStream> + static CharType Take(InputByteStream& is) { + RAPIDJSON_STATIC_ASSERT(sizeof(typename InputByteStream::Ch) == 1); + unsigned c = static_cast<unsigned>(static_cast<uint8_t>(is.Take())) << 8; + c |= static_cast<unsigned>(static_cast<uint8_t>(is.Take())); + return static_cast<CharType>(c); + } + + template <typename OutputByteStream> + static void PutBOM(OutputByteStream& os) { + RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputByteStream::Ch) == 1); + os.Put(static_cast<typename OutputByteStream::Ch>(0xFEu)); + os.Put(static_cast<typename OutputByteStream::Ch>(0xFFu)); + } + + template <typename OutputByteStream> + static void Put(OutputByteStream& os, CharType c) { + RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputByteStream::Ch) == 1); + os.Put(static_cast<typename OutputByteStream::Ch>((static_cast<unsigned>(c) >> 8) & 0xFFu)); + os.Put(static_cast<typename OutputByteStream::Ch>(static_cast<unsigned>(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<typename CharType = unsigned> +struct UTF32 { + typedef CharType Ch; + RAPIDJSON_STATIC_ASSERT(sizeof(Ch) >= 4); + + enum { supportUnicode = 1 }; + + template<typename OutputStream> + static void Encode(OutputStream& os, unsigned codepoint) { + RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputStream::Ch) >= 4); + RAPIDJSON_ASSERT(codepoint <= 0x10FFFF); + os.Put(codepoint); + } + + template<typename OutputStream> + static void EncodeUnsafe(OutputStream& os, unsigned codepoint) { + RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputStream::Ch) >= 4); + RAPIDJSON_ASSERT(codepoint <= 0x10FFFF); + PutUnsafe(os, codepoint); + } + + template <typename InputStream> + 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 <typename InputStream, typename OutputStream> + 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<typename CharType = unsigned> +struct UTF32LE : UTF32<CharType> { + template <typename InputByteStream> + static CharType TakeBOM(InputByteStream& is) { + RAPIDJSON_STATIC_ASSERT(sizeof(typename InputByteStream::Ch) == 1); + CharType c = Take(is); + return static_cast<uint32_t>(c) == 0x0000FEFFu ? Take(is) : c; + } + + template <typename InputByteStream> + static CharType Take(InputByteStream& is) { + RAPIDJSON_STATIC_ASSERT(sizeof(typename InputByteStream::Ch) == 1); + unsigned c = static_cast<uint8_t>(is.Take()); + c |= static_cast<unsigned>(static_cast<uint8_t>(is.Take())) << 8; + c |= static_cast<unsigned>(static_cast<uint8_t>(is.Take())) << 16; + c |= static_cast<unsigned>(static_cast<uint8_t>(is.Take())) << 24; + return static_cast<CharType>(c); + } + + template <typename OutputByteStream> + static void PutBOM(OutputByteStream& os) { + RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputByteStream::Ch) == 1); + os.Put(static_cast<typename OutputByteStream::Ch>(0xFFu)); + os.Put(static_cast<typename OutputByteStream::Ch>(0xFEu)); + os.Put(static_cast<typename OutputByteStream::Ch>(0x00u)); + os.Put(static_cast<typename OutputByteStream::Ch>(0x00u)); + } + + template <typename OutputByteStream> + static void Put(OutputByteStream& os, CharType c) { + RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputByteStream::Ch) == 1); + os.Put(static_cast<typename OutputByteStream::Ch>(c & 0xFFu)); + os.Put(static_cast<typename OutputByteStream::Ch>((c >> 8) & 0xFFu)); + os.Put(static_cast<typename OutputByteStream::Ch>((c >> 16) & 0xFFu)); + os.Put(static_cast<typename OutputByteStream::Ch>((c >> 24) & 0xFFu)); + } +}; + +//! UTF-32 big endian encoding. +template<typename CharType = unsigned> +struct UTF32BE : UTF32<CharType> { + template <typename InputByteStream> + static CharType TakeBOM(InputByteStream& is) { + RAPIDJSON_STATIC_ASSERT(sizeof(typename InputByteStream::Ch) == 1); + CharType c = Take(is); + return static_cast<uint32_t>(c) == 0x0000FEFFu ? Take(is) : c; + } + + template <typename InputByteStream> + static CharType Take(InputByteStream& is) { + RAPIDJSON_STATIC_ASSERT(sizeof(typename InputByteStream::Ch) == 1); + unsigned c = static_cast<unsigned>(static_cast<uint8_t>(is.Take())) << 24; + c |= static_cast<unsigned>(static_cast<uint8_t>(is.Take())) << 16; + c |= static_cast<unsigned>(static_cast<uint8_t>(is.Take())) << 8; + c |= static_cast<unsigned>(static_cast<uint8_t>(is.Take())); + return static_cast<CharType>(c); + } + + template <typename OutputByteStream> + static void PutBOM(OutputByteStream& os) { + RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputByteStream::Ch) == 1); + os.Put(static_cast<typename OutputByteStream::Ch>(0x00u)); + os.Put(static_cast<typename OutputByteStream::Ch>(0x00u)); + os.Put(static_cast<typename OutputByteStream::Ch>(0xFEu)); + os.Put(static_cast<typename OutputByteStream::Ch>(0xFFu)); + } + + template <typename OutputByteStream> + static void Put(OutputByteStream& os, CharType c) { + RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputByteStream::Ch) == 1); + os.Put(static_cast<typename OutputByteStream::Ch>((c >> 24) & 0xFFu)); + os.Put(static_cast<typename OutputByteStream::Ch>((c >> 16) & 0xFFu)); + os.Put(static_cast<typename OutputByteStream::Ch>((c >> 8) & 0xFFu)); + os.Put(static_cast<typename OutputByteStream::Ch>(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<typename CharType = char> +struct ASCII { + typedef CharType Ch; + + enum { supportUnicode = 0 }; + + template<typename OutputStream> + static void Encode(OutputStream& os, unsigned codepoint) { + RAPIDJSON_ASSERT(codepoint <= 0x7F); + os.Put(static_cast<Ch>(codepoint & 0xFF)); + } + + template<typename OutputStream> + static void EncodeUnsafe(OutputStream& os, unsigned codepoint) { + RAPIDJSON_ASSERT(codepoint <= 0x7F); + PutUnsafe(os, static_cast<Ch>(codepoint & 0xFF)); + } + + template <typename InputStream> + static bool Decode(InputStream& is, unsigned* codepoint) { + uint8_t c = static_cast<uint8_t>(is.Take()); + *codepoint = c; + return c <= 0X7F; + } + + template <typename InputStream, typename OutputStream> + static bool Validate(InputStream& is, OutputStream& os) { + uint8_t c = static_cast<uint8_t>(is.Take()); + os.Put(static_cast<typename OutputStream::Ch>(c)); + return c <= 0x7F; + } + + template <typename InputByteStream> + static CharType TakeBOM(InputByteStream& is) { + RAPIDJSON_STATIC_ASSERT(sizeof(typename InputByteStream::Ch) == 1); + uint8_t c = static_cast<uint8_t>(Take(is)); + return static_cast<Ch>(c); + } + + template <typename InputByteStream> + static Ch Take(InputByteStream& is) { + RAPIDJSON_STATIC_ASSERT(sizeof(typename InputByteStream::Ch) == 1); + return static_cast<Ch>(is.Take()); + } + + template <typename OutputByteStream> + static void PutBOM(OutputByteStream& os) { + RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputByteStream::Ch) == 1); + (void)os; + } + + template <typename OutputByteStream> + static void Put(OutputByteStream& os, Ch c) { + RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputByteStream::Ch) == 1); + os.Put(static_cast<typename OutputByteStream::Ch>(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<typename CharType> +struct AutoUTF { + typedef CharType Ch; + + enum { supportUnicode = 1 }; + +#define RAPIDJSON_ENCODINGS_FUNC(x) UTF8<Ch>::x, UTF16LE<Ch>::x, UTF16BE<Ch>::x, UTF32LE<Ch>::x, UTF32BE<Ch>::x + + template<typename OutputStream> + 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<typename OutputStream> + 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 <typename InputStream> + 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 <typename InputStream, typename OutputStream> + 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<typename SourceEncoding, typename TargetEncoding> +struct Transcoder { + //! Take one Unicode codepoint from source encoding, convert it to target encoding and put it to the output stream. + template<typename InputStream, typename OutputStream> + 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<typename InputStream, typename OutputStream> + 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<typename InputStream, typename OutputStream> + static RAPIDJSON_FORCEINLINE bool Validate(InputStream& is, OutputStream& os) { + return Transcode(is, os); // Since source/target encoding is different, must transcode. + } +}; + +// Forward declaration. +template<typename Stream> +inline void PutUnsafe(Stream& stream, typename Stream::Ch c); + +//! Specialization of Transcoder with same source and target encoding. +template<typename Encoding> +struct Transcoder<Encoding, Encoding> { + template<typename InputStream, typename OutputStream> + 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<typename InputStream, typename OutputStream> + 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<typename InputStream, typename OutputStream> + 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 0000000000000000000000000000000000000000..5d2e57b7fd490b031d99a563934ae181fc2fe8ca --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/rapidjson/error/en.h @@ -0,0 +1,122 @@ +// 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'."); + 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'."); + + 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 0000000000000000000000000000000000000000..6270da11a54ea474572182a47b81cb25695512c0 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/rapidjson/error/error.h @@ -0,0 +1,216 @@ +// 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 literial 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'. +}; + +//! 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); + +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 0000000000000000000000000000000000000000..f8bb43cb0cf197862ef88a599ea0e46f2ecd6ca2 --- /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 <cstdio> + +#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<size_t>(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 0000000000000000000000000000000000000000..5d89588c218ddb930ee5df309358079553d4a474 --- /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 <cstdio> + +#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<size_t>(bufferEnd_ - current_); + while (n > avail) { + std::memset(current_, c, avail); + current_ += avail; + Flush(); + n -= avail; + avail = static_cast<size_t>(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<size_t>(current_ - buffer_), fp_); + if (result < static_cast<size_t>(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 0000000000000000000000000000000000000000..d62f77f0ecfafdf34ca723dd136c987a2227cb24 --- /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<typename CharType> struct UTF8; +template<typename CharType> struct UTF16; +template<typename CharType> struct UTF16BE; +template<typename CharType> struct UTF16LE; +template<typename CharType> struct UTF32; +template<typename CharType> struct UTF32BE; +template<typename CharType> struct UTF32LE; +template<typename CharType> struct ASCII; +template<typename CharType> struct AutoUTF; + +template<typename SourceEncoding, typename TargetEncoding> +struct Transcoder; + +// allocators.h + +class CrtAllocator; + +template <typename BaseAllocator> +class MemoryPoolAllocator; + +// stream.h + +template <typename Encoding> +struct GenericStringStream; + +typedef GenericStringStream<UTF8<char> > StringStream; + +template <typename Encoding> +struct GenericInsituStringStream; + +typedef GenericInsituStringStream<UTF8<char> > InsituStringStream; + +// stringbuffer.h + +template <typename Encoding, typename Allocator> +class GenericStringBuffer; + +typedef GenericStringBuffer<UTF8<char>, CrtAllocator> StringBuffer; + +// filereadstream.h + +class FileReadStream; + +// filewritestream.h + +class FileWriteStream; + +// memorybuffer.h + +template <typename Allocator> +struct GenericMemoryBuffer; + +typedef GenericMemoryBuffer<CrtAllocator> MemoryBuffer; + +// memorystream.h + +struct MemoryStream; + +// reader.h + +template<typename Encoding, typename Derived> +struct BaseReaderHandler; + +template <typename SourceEncoding, typename TargetEncoding, typename StackAllocator> +class GenericReader; + +typedef GenericReader<UTF8<char>, UTF8<char>, CrtAllocator> Reader; + +// writer.h + +template<typename OutputStream, typename SourceEncoding, typename TargetEncoding, typename StackAllocator, unsigned writeFlags> +class Writer; + +// prettywriter.h + +template<typename OutputStream, typename SourceEncoding, typename TargetEncoding, typename StackAllocator, unsigned writeFlags> +class PrettyWriter; + +// document.h + +template <typename Encoding, typename Allocator> +class GenericMember; + +template <bool Const, typename Encoding, typename Allocator> +class GenericMemberIterator; + +template<typename CharType> +struct GenericStringRef; + +template <typename Encoding, typename Allocator> +class GenericValue; + +typedef GenericValue<UTF8<char>, MemoryPoolAllocator<CrtAllocator> > Value; + +template <typename Encoding, typename Allocator, typename StackAllocator> +class GenericDocument; + +typedef GenericDocument<UTF8<char>, MemoryPoolAllocator<CrtAllocator>, CrtAllocator> Document; + +// pointer.h + +template <typename ValueType, typename Allocator> +class GenericPointer; + +typedef GenericPointer<Value, CrtAllocator> Pointer; + +// schema.h + +template <typename SchemaDocumentType> +class IGenericRemoteSchemaDocumentProvider; + +template <typename ValueT, typename Allocator> +class GenericSchemaDocument; + +typedef GenericSchemaDocument<Value, CrtAllocator> SchemaDocument; +typedef IGenericRemoteSchemaDocumentProvider<SchemaDocument> IRemoteSchemaDocumentProvider; + +template < + typename SchemaDocumentType, + typename OutputHandler, + typename StateAllocator> +class GenericSchemaValidator; + +typedef GenericSchemaValidator<SchemaDocument, BaseReaderHandler<UTF8<char>, 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 0000000000000000000000000000000000000000..af4873803897d37207b794567c81431b6ce24648 --- /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 <intrin.h> // 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<typename Ch> + 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<uint32_t>(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<typename Ch> + void AppendDecimal64(const Ch* begin, const Ch* end) { + uint64_t u = ParseUint64(begin, end); + if (IsZero()) + *this = u; + else { + unsigned exp = static_cast<unsigned>(end - begin); + (MultiplyPow5(exp) <<= exp) += u; // *this = *this * 10^exp + u + } + } + + void PushBack(Type digit) { + RAPIDJSON_ASSERT(count_ < kCapacity); + digits_[count_++] = digit; + } + + template<typename Ch> + 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<unsigned>(*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 (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6)) && defined(__x86_64__) + __extension__ typedef unsigned __int128 uint128; + uint128 p = static_cast<uint128>(a) * static_cast<uint128>(b); + p += k; + *outHigh = static_cast<uint64_t>(p >> 64); + return static_cast<uint64_t>(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<uint64_t>(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 0000000000000000000000000000000000000000..8fc5118aa47b8e6f3984dd64e0d32f78f5be5f04 --- /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 <intrin.h> +#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<uint32_t>(x >> 32))) + return 63 - (r + 32); + + // Scan the low 32 bits. + _BitScanReverse(&r, static_cast<uint32_t>(x & 0xFFFFFFFF)); +#endif // _WIN64 + + return 63 - r; +#elif (defined(__GNUC__) && __GNUC__ >= 4) || RAPIDJSON_HAS_BUILTIN(__builtin_clzll) + // __builtin_clzll wrapper + return static_cast<uint32_t>(__builtin_clzll(x)); +#else + // naive version + uint32_t r = 0; + while (!(x & (static_cast<uint64_t>(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 0000000000000000000000000000000000000000..f7d46539a907dd6a816a87683b36c05744d8ceca --- /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 <limits> + +#if defined(_MSC_VER) && defined(_M_AMD64) && !defined(__INTEL_COMPILER) +#include <intrin.h> +#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<int>((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 (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6)) && defined(__x86_64__) + __extension__ typedef unsigned __int128 uint128; + uint128 p = static_cast<uint128>(f) * static_cast<uint128>(rhs.f); + uint64_t h = static_cast<uint64_t>(p >> 64); + uint64_t l = static_cast<uint64_t>(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<int>(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<double>::infinity(); + } + const uint64_t be = (e == kDpDenormalExponent && (f & kDpHiddenBit) == 0) ? 0 : + static_cast<uint64_t>(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<int>(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<int>(dk); + if (dk - k > 0.0) + k++; + + unsigned index = static_cast<unsigned>((k >> 3) + 1); + *K = -(-348 + static_cast<int>(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<unsigned>(exp + 348) / 8u; + *outExp = -348 + static_cast<int>(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 0000000000000000000000000000000000000000..9f6ae3b3f008f0a6c66deaff28d336e300bb49c5 --- /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[] = { 1U, 10U, 100U, 1000U, 10000U, 100000U, 1000000U, 10000000U, 100000000U, + 1000000000U, 10000000000U, 100000000000U, 1000000000000U, + 10000000000000U, 100000000000000U, 1000000000000000U, + 10000000000000000U, 100000000000000000U, 1000000000000000000U, + 10000000000000000000U }; + const DiyFp one(uint64_t(1) << -Mp.e, Mp.e); + const DiyFp wp_w = Mp - W; + uint32_t p1 = static_cast<uint32_t>(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<char>('0' + static_cast<char>(d)); + kappa--; + uint64_t tmp = (static_cast<uint64_t>(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<char>(p2 >> -one.e); + if (d || *len) + buffer[(*len)++] = static_cast<char>('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<char>('0' + static_cast<char>(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<char>('0' + static_cast<char>(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<size_t>(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<size_t>(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<size_t>(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 0000000000000000000000000000000000000000..68c9e96649b8aa5323fb06480da7cfad84bb2485 --- /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<int>(((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 0000000000000000000000000000000000000000..9fe8c932ffa6d03ac8926574b842abb0a191eab8 --- /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<char>('0' + static_cast<char>(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<uint32_t>(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<uint32_t>(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<uint32_t>(value / kTen8); + const uint32_t v1 = static_cast<uint32_t>(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<uint32_t>(value / kTen16); // 1 to 1844 + value %= kTen16; + + if (a < 10) + *buffer++ = static_cast<char>('0' + static_cast<char>(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<char>('0' + static_cast<char>(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<uint32_t>(value / kTen8); + const uint32_t v1 = static_cast<uint32_t>(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<uint64_t>(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 0000000000000000000000000000000000000000..27092dc0d69c43e5601632170a5812c9abb3b8c6 --- /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 <type_traits> +#endif + +//@cond RAPIDJSON_INTERNAL +RAPIDJSON_NAMESPACE_BEGIN +namespace internal { + +// Helper to wrap/convert arbitrary types to void, useful for arbitrary type matching +template <typename T> struct Void { typedef void Type; }; + +/////////////////////////////////////////////////////////////////////////////// +// BoolType, TrueType, FalseType +// +template <bool Cond> struct BoolType { + static const bool Value = Cond; + typedef BoolType Type; +}; +typedef BoolType<true> TrueType; +typedef BoolType<false> FalseType; + + +/////////////////////////////////////////////////////////////////////////////// +// SelectIf, BoolExpr, NotExpr, AndExpr, OrExpr +// + +template <bool C> struct SelectIfImpl { template <typename T1, typename T2> struct Apply { typedef T1 Type; }; }; +template <> struct SelectIfImpl<false> { template <typename T1, typename T2> struct Apply { typedef T2 Type; }; }; +template <bool C, typename T1, typename T2> struct SelectIfCond : SelectIfImpl<C>::template Apply<T1,T2> {}; +template <typename C, typename T1, typename T2> struct SelectIf : SelectIfCond<C::Value, T1, T2> {}; + +template <bool Cond1, bool Cond2> struct AndExprCond : FalseType {}; +template <> struct AndExprCond<true, true> : TrueType {}; +template <bool Cond1, bool Cond2> struct OrExprCond : TrueType {}; +template <> struct OrExprCond<false, false> : FalseType {}; + +template <typename C> struct BoolExpr : SelectIf<C,TrueType,FalseType>::Type {}; +template <typename C> struct NotExpr : SelectIf<C,FalseType,TrueType>::Type {}; +template <typename C1, typename C2> struct AndExpr : AndExprCond<C1::Value, C2::Value>::Type {}; +template <typename C1, typename C2> struct OrExpr : OrExprCond<C1::Value, C2::Value>::Type {}; + + +/////////////////////////////////////////////////////////////////////////////// +// AddConst, MaybeAddConst, RemoveConst +template <typename T> struct AddConst { typedef const T Type; }; +template <bool Constify, typename T> struct MaybeAddConst : SelectIfCond<Constify, const T, T> {}; +template <typename T> struct RemoveConst { typedef T Type; }; +template <typename T> struct RemoveConst<const T> { typedef T Type; }; + + +/////////////////////////////////////////////////////////////////////////////// +// IsSame, IsConst, IsMoreConst, IsPointer +// +template <typename T, typename U> struct IsSame : FalseType {}; +template <typename T> struct IsSame<T, T> : TrueType {}; + +template <typename T> struct IsConst : FalseType {}; +template <typename T> struct IsConst<const T> : TrueType {}; + +template <typename CT, typename T> +struct IsMoreConst + : AndExpr<IsSame<typename RemoveConst<CT>::Type, typename RemoveConst<T>::Type>, + BoolType<IsConst<CT>::Value >= IsConst<T>::Value> >::Type {}; + +template <typename T> struct IsPointer : FalseType {}; +template <typename T> struct IsPointer<T*> : TrueType {}; + +/////////////////////////////////////////////////////////////////////////////// +// IsBaseOf +// +#if RAPIDJSON_HAS_CXX11_TYPETRAITS + +template <typename B, typename D> struct IsBaseOf + : BoolType< ::std::is_base_of<B,D>::value> {}; + +#else // simplified version adopted from Boost + +template<typename B, typename D> struct IsBaseOfImpl { + RAPIDJSON_STATIC_ASSERT(sizeof(B) != 0); + RAPIDJSON_STATIC_ASSERT(sizeof(D) != 0); + + typedef char (&Yes)[1]; + typedef char (&No) [2]; + + template <typename T> + 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 <typename B, typename D> struct IsBaseOf + : OrExpr<IsSame<B, D>, BoolExpr<IsBaseOfImpl<B, D> > >::Type {}; + +#endif // RAPIDJSON_HAS_CXX11_TYPETRAITS + + +////////////////////////////////////////////////////////////////////////// +// EnableIf / DisableIf +// +template <bool Condition, typename T = void> struct EnableIfCond { typedef T Type; }; +template <typename T> struct EnableIfCond<false, T> { /* empty */ }; + +template <bool Condition, typename T = void> struct DisableIfCond { typedef T Type; }; +template <typename T> struct DisableIfCond<true, T> { /* empty */ }; + +template <typename Condition, typename T = void> +struct EnableIf : EnableIfCond<Condition::Value, T> {}; + +template <typename Condition, typename T = void> +struct DisableIf : DisableIfCond<Condition::Value, T> {}; + +// SFINAE helpers +struct SfinaeTag {}; +template <typename T> struct RemoveSfinaeTag; +template <typename T> struct RemoveSfinaeTag<SfinaeTag&(*)(T)> { 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 \ + <RAPIDJSON_REMOVEFPTR_(cond)>::Type * = NULL + +#define RAPIDJSON_DISABLEIF(cond) \ + typename ::RAPIDJSON_NAMESPACE::internal::DisableIf \ + <RAPIDJSON_REMOVEFPTR_(cond)>::Type * = NULL + +#define RAPIDJSON_ENABLEIF_RETURN(cond,returntype) \ + typename ::RAPIDJSON_NAMESPACE::internal::EnableIf \ + <RAPIDJSON_REMOVEFPTR_(cond), \ + RAPIDJSON_REMOVEFPTR_(returntype)>::Type + +#define RAPIDJSON_DISABLEIF_RETURN(cond,returntype) \ + typename ::RAPIDJSON_NAMESPACE::internal::DisableIf \ + <RAPIDJSON_REMOVEFPTR_(cond), \ + RAPIDJSON_REMOVEFPTR_(returntype)>::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 0000000000000000000000000000000000000000..eae1a43ed1a06d980b9dc58f155c9c999f2ee58b --- /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 0000000000000000000000000000000000000000..6446c403af9f302dffe022a8b0f0efbaa0370184 --- /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 <typename SourceStream, typename Encoding> +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 <typename Encoding, typename Allocator> +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 <typename Encoding, typename Allocator = CrtAllocator> +class GenericRegex { +public: + typedef Encoding EncodingType; + typedef typename Encoding::Ch Ch; + template <typename, typename> 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<Encoding> ss(source); + DecodedStream<GenericStringStream<Encoding>, 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<State>()[index]; + } + + const State& GetState(SizeType index) const { + RAPIDJSON_ASSERT(index < stateCount_); + return states_.template Bottom<State>()[index]; + } + + Range& GetRange(SizeType index) { + RAPIDJSON_ASSERT(index < rangeCount_); + return ranges_.template Bottom<Range>()[index]; + } + + const Range& GetRange(SizeType index) const { + RAPIDJSON_ASSERT(index < rangeCount_); + return ranges_.template Bottom<Range>()[index]; + } + + template <typename InputStream> + void Parse(DecodedStream<InputStream, Encoding>& ds) { + Stack<Allocator> operandStack(allocator_, 256); // Frag + Stack<Allocator> operatorStack(allocator_, 256); // Operator + Stack<Allocator> atomCountStack(allocator_, 256); // unsigned (Atom per parenthesis) + + *atomCountStack.template Push<unsigned>() = 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<Operator>() < kAlternation) + if (!Eval(operandStack, *operatorStack.template Pop<Operator>(1))) + return; + *operatorStack.template Push<Operator>() = kAlternation; + *atomCountStack.template Top<unsigned>() = 0; + break; + + case '(': + *operatorStack.template Push<Operator>() = kLeftParenthesis; + *atomCountStack.template Push<unsigned>() = 0; + break; + + case ')': + while (!operatorStack.Empty() && *operatorStack.template Top<Operator>() != kLeftParenthesis) + if (!Eval(operandStack, *operatorStack.template Pop<Operator>(1))) + return; + if (operatorStack.Empty()) + return; + operatorStack.template Pop<Operator>(1); + atomCountStack.template Pop<unsigned>(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>() = 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<Operator>(1))) + return; + + // Link the operand to matching state. + if (operandStack.GetSize() == sizeof(Frag)) { + Frag* e = operandStack.template Pop<Frag>(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<State>(); + s->out = out; + s->out1 = out1; + s->codepoint = codepoint; + s->rangeStart = kRegexInvalidRange; + return stateCount_++; + } + + void PushOperand(Stack<Allocator>& operandStack, unsigned codepoint) { + SizeType s = NewState(kRegexInvalidState, kRegexInvalidState, codepoint); + *operandStack.template Push<Frag>() = Frag(s, s, s); + } + + void ImplicitConcatenation(Stack<Allocator>& atomCountStack, Stack<Allocator>& operatorStack) { + if (*atomCountStack.template Top<unsigned>()) + *operatorStack.template Push<Operator>() = kConcatenation; + (*atomCountStack.template Top<unsigned>())++; + } + + 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<Allocator>& operandStack, Operator op) { + switch (op) { + case kConcatenation: + RAPIDJSON_ASSERT(operandStack.GetSize() >= sizeof(Frag) * 2); + { + Frag e2 = *operandStack.template Pop<Frag>(1); + Frag e1 = *operandStack.template Pop<Frag>(1); + Patch(e1.out, e2.start); + *operandStack.template Push<Frag>() = 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<Frag>(1); + Frag e1 = *operandStack.template Pop<Frag>(1); + SizeType s = NewState(e1.start, e2.start, 0); + *operandStack.template Push<Frag>() = 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<Frag>(1); + SizeType s = NewState(kRegexInvalidState, e.start, 0); + *operandStack.template Push<Frag>() = Frag(s, Append(e.out, s), e.minIndex); + return true; + } + return false; + + case kZeroOrMore: + if (operandStack.GetSize() >= sizeof(Frag)) { + Frag e = *operandStack.template Pop<Frag>(1); + SizeType s = NewState(kRegexInvalidState, e.start, 0); + Patch(e.out, s); + *operandStack.template Push<Frag>() = Frag(s, s, e.minIndex); + return true; + } + return false; + + case kOneOrMore: + if (operandStack.GetSize() >= sizeof(Frag)) { + Frag e = *operandStack.template Pop<Frag>(1); + SizeType s = NewState(kRegexInvalidState, e.start, 0); + Patch(e.out, s); + *operandStack.template Push<Frag>() = Frag(e.start, s, e.minIndex); + return true; + } + return false; + + default: + // syntax error (e.g. unclosed kLeftParenthesis) + return false; + } + } + + bool EvalQuantifier(Stack<Allocator>& 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<Allocator>& operandStack) { + const Frag src = *operandStack.template Top<Frag>(); // Copy constructor to prevent invalidation + SizeType count = stateCount_ - src.minIndex; // Assumes top operand contains states in [src->minIndex, stateCount_) + State* s = states_.template Push<State>(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>() = Frag(src.start + count, src.out + count, src.minIndex + count); + stateCount_ += count; + } + + template <typename InputStream> + bool ParseUnsigned(DecodedStream<InputStream, Encoding>& 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 <typename InputStream> + bool ParseRange(DecodedStream<InputStream, Encoding>& 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<Range>(); + r->start = r->end = codepoint; + r->next = kRegexInvalidRange; + return rangeCount_++; + } + + template <typename InputStream> + bool CharacterEscape(DecodedStream<InputStream, Encoding>& 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<Allocator> states_; + Stack<Allocator> ranges_; + SizeType root_; + SizeType stateCount_; + SizeType rangeCount_; + + static const unsigned kInfinityQuantifier = ~0u; + + // For SearchWithAnchoring() + bool anchorBegin_; + bool anchorEnd_; +}; + +template <typename RegexType, typename Allocator = CrtAllocator> +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<unsigned*>(allocator_->Malloc(GetStateSetSize())); + state0_.template Reserve<SizeType>(regex_.stateCount_); + state1_.template Reserve<SizeType>(regex_.stateCount_); + } + + ~GenericRegexSearch() { + Allocator::Free(stateSet_); + RAPIDJSON_DELETE(ownAllocator_); + } + + template <typename InputStream> + bool Match(InputStream& is) { + return SearchWithAnchoring(is, true, true); + } + + bool Match(const Ch* s) { + GenericStringStream<Encoding> is(s); + return Match(is); + } + + template <typename InputStream> + bool Search(InputStream& is) { + return SearchWithAnchoring(is, regex_.anchorBegin_, regex_.anchorEnd_); + } + + bool Search(const Ch* s) { + GenericStringStream<Encoding> is(s); + return Search(is); + } + +private: + typedef typename RegexType::State State; + typedef typename RegexType::Range Range; + + template <typename InputStream> + bool SearchWithAnchoring(InputStream& is, bool anchorBegin, bool anchorEnd) { + DecodedStream<InputStream, Encoding> ds(is); + + state0_.Clear(); + Stack<Allocator> *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<SizeType>(); s != current->template End<SizeType>(); ++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<Allocator>& 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<SizeType>() = 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<Allocator> state0_; + Stack<Allocator> state1_; + uint32_t* stateSet_; +}; + +typedef GenericRegex<UTF8<> > Regex; +typedef GenericRegexSearch<Regex> 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 0000000000000000000000000000000000000000..73abd706e976926802d52564cb7f7e36b0070ba0 --- /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 <cstddef> + +#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 <typename Allocator> +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<typename T> + RAPIDJSON_FORCEINLINE void Reserve(size_t count = 1) { + // Expand the stack if needed + if (RAPIDJSON_UNLIKELY(static_cast<std::ptrdiff_t>(sizeof(T) * count) > (stackEnd_ - stackTop_))) + Expand<T>(count); + } + + template<typename T> + RAPIDJSON_FORCEINLINE T* Push(size_t count = 1) { + Reserve<T>(count); + return PushUnsafe<T>(count); + } + + template<typename T> + RAPIDJSON_FORCEINLINE T* PushUnsafe(size_t count = 1) { + RAPIDJSON_ASSERT(stackTop_); + RAPIDJSON_ASSERT(static_cast<std::ptrdiff_t>(sizeof(T) * count) <= (stackEnd_ - stackTop_)); + T* ret = reinterpret_cast<T*>(stackTop_); + stackTop_ += sizeof(T) * count; + return ret; + } + + template<typename T> + T* Pop(size_t count) { + RAPIDJSON_ASSERT(GetSize() >= count * sizeof(T)); + stackTop_ -= count * sizeof(T); + return reinterpret_cast<T*>(stackTop_); + } + + template<typename T> + T* Top() { + RAPIDJSON_ASSERT(GetSize() >= sizeof(T)); + return reinterpret_cast<T*>(stackTop_ - sizeof(T)); + } + + template<typename T> + const T* Top() const { + RAPIDJSON_ASSERT(GetSize() >= sizeof(T)); + return reinterpret_cast<T*>(stackTop_ - sizeof(T)); + } + + template<typename T> + T* End() { return reinterpret_cast<T*>(stackTop_); } + + template<typename T> + const T* End() const { return reinterpret_cast<T*>(stackTop_); } + + template<typename T> + T* Bottom() { return reinterpret_cast<T*>(stack_); } + + template<typename T> + const T* Bottom() const { return reinterpret_cast<T*>(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<size_t>(stackTop_ - stack_); } + size_t GetCapacity() const { return static_cast<size_t>(stackEnd_ - stack_); } + +private: + template<typename T> + 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<char*>(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 0000000000000000000000000000000000000000..b698a8f43fa63b342f3f6254adf68dbac99b9461 --- /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 <cwchar> + +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 <typename Ch> +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<typename Ch> +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<unsigned>(*s1) < static_cast<unsigned>(*s2) ? -1 : static_cast<unsigned>(*s1) > static_cast<unsigned>(*s2); +} + +//! Returns number of code points in a encoded string. +template<typename Encoding> +bool CountStringCodePoint(const typename Encoding::Ch* s, SizeType length, SizeType* outCount) { + RAPIDJSON_ASSERT(s != 0); + RAPIDJSON_ASSERT(outCount != 0); + GenericStringStream<Encoding> 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 0000000000000000000000000000000000000000..55f0e380bfaa351dc2b7a0f14fc2232540ec0fd9 --- /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 <climits> +#include <limits> + +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 <typename T> +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<unsigned>(dS_Exp5)) <<= static_cast<unsigned>(dS_Exp2); + + BigInteger bS(bInt); + bS.MultiplyPow5(static_cast<unsigned>(bS_Exp5)) <<= static_cast<unsigned>(bS_Exp2); + + BigInteger hS(1); + hS.MultiplyPow5(static_cast<unsigned>(hS_Exp5)) <<= static_cast<unsigned>(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<typename Ch> +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<unsigned>(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<unsigned>(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<unsigned>(error) >= precisionBits || precisionBits >= halfWay + static_cast<unsigned>(error); +} + +template<typename Ch> +inline double StrtodBigInteger(double approx, const Ch* decimals, int dLen, int dExp) { + RAPIDJSON_ASSERT(dLen >= 0); + const BigInteger dInt(decimals, static_cast<unsigned>(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<typename Ch> +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<int>(length); + + RAPIDJSON_ASSERT(length >= decimalPosition); + RAPIDJSON_ASSERT(length - decimalPosition <= INT_MAX); + int dExpAdjust = static_cast<int>(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<double>::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 0000000000000000000000000000000000000000..2cf92f93a1d371ab8e6f2e2084cc107926cff61a --- /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++ <algorithm> 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 <typename T> +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 0000000000000000000000000000000000000000..01437ec0127a01838f83215a9d101563d8e5a316 --- /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 <iosfwd> +#include <ios> + +#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 <typename StreamType> +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<size_t>(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<std::streamsize>(bufferSize_))) { + readCount_ = static_cast<size_t>(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<std::istream> IStreamWrapper; +typedef BasicIStreamWrapper<std::wistream> 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 0000000000000000000000000000000000000000..ffbc41ed1f7d2b48e809129e279fd12524fc5043 --- /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 <typename Allocator = CrtAllocator> +struct GenericMemoryBuffer { + typedef char Ch; // byte + + GenericMemoryBuffer(Allocator* allocator = 0, size_t capacity = kDefaultCapacity) : stack_(allocator, capacity) {} + + void Put(Ch c) { *stack_.template Push<Ch>() = c; } + void Flush() {} + + void Clear() { stack_.Clear(); } + void ShrinkToFit() { stack_.ShrinkToFit(); } + Ch* Push(size_t count) { return stack_.template Push<Ch>(count); } + void Pop(size_t count) { stack_.template Pop<Ch>(count); } + + const Ch* GetBuffer() const { + return stack_.template Bottom<Ch>(); + } + + size_t GetSize() const { return stack_.GetSize(); } + + static const size_t kDefaultCapacity = 256; + mutable internal::Stack<Allocator> 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<char>(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 0000000000000000000000000000000000000000..77af6c999e977a3c46efd1f486caafed5e6418a9 --- /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<size_t>(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 0000000000000000000000000000000000000000..18111286bf55bc0c89e7f47afcb046bbb02e1781 --- /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 <inttypes.h> +#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 0000000000000000000000000000000000000000..3d4477b9a024a8f326afe362ce3926e04f4c8ec9 --- /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 <stdint.h> + +#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 <boost/cstdint.hpp>. +// 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 <limits.h> + +// For Visual Studio 6 in C++ mode and for many Visual Studio versions when +// compiling for ARM we have to wrap <wchar.h> 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 <wchar.h> +#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 <wchar.h> +#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 <boost/cstdint.hpp>. +// 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 0000000000000000000000000000000000000000..11ed4d33f92250c24ebdbeb1963172c5a9a87a17 --- /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 <iosfwd> + +#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 <typename StreamType> +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<std::ostream> OStreamWrapper; +typedef BasicOStreamWrapper<std::wostream> 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 0000000000000000000000000000000000000000..67a9cb07686321a2fbb7f8759eeb52f3499324c4 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/rapidjson/pointer.h @@ -0,0 +1,1482 @@ +// 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" + +#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 + +//! Error code of 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 +}; + +/////////////////////////////////////////////////////////////////////////////// +// 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<UTF8<> > + \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 <typename ValueType, typename Allocator = CrtAllocator> +class GenericPointer { +public: + typedef typename ValueType::EncodingType EncodingType; //!< Encoding type from Value + typedef typename ValueType::Ch Ch; //!< Character type from Value + typedef GenericUri<ValueType, Allocator> 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<Ch>& 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<Token*>(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 <typename T> + RAPIDJSON_DISABLEIF_RETURN((internal::NotExpr<internal::IsSame<typename internal::RemoveConst<T>::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<Ch>& name, Allocator* allocator = 0) const { + return Append(name.c_str(), static_cast<SizeType>(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<SizeType>(end - buffer); + buffer[length] = '\0'; + + if (sizeof(Ch) == 1) { + Token token = { reinterpret_cast<Ch*>(buffer), length, index }; + return Append(token, allocator); + } + else { + Ch name[21]; + for (size_t i = 0; i <= length; i++) + name[i] = static_cast<Ch>(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<SizeType>(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<typename OutputStream> + bool Stringify(OutputStream& os) const { + return Stringify<false, OutputStream>(os); + } + + //! Stringify the pointer into URI fragment representation. + /*! + \tparam OutputStream Type of output stream. + \param os The output stream. + */ + template<typename OutputStream> + bool StringifyUriFragment(OutputStream& os) const { + return Stringify<true, OutputStream>(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<EncodingType>(GenericStringRef<Ch>(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 <typename stackAllocator> + ValueType& Create(GenericDocument<EncodingType, typename ValueType::AllocatorType, stackAllocator>& 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<EncodingType>(GenericStringRef<Ch>(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<size_t>(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<ValueType&>(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<EncodingType>(GenericStringRef<Ch>(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<size_t>(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<ValueType&>(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<Ch>& 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 <typename T> + RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr<internal::IsPointer<T>, internal::IsGenericValue<T> >), (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 <typename stackAllocator> + ValueType& GetWithDefault(GenericDocument<EncodingType, typename ValueType::AllocatorType, stackAllocator>& document, const ValueType& defaultValue) const { + return GetWithDefault(document, defaultValue, document.GetAllocator()); + } + + //! Query a value in a document with default null-terminated string. + template <typename stackAllocator> + ValueType& GetWithDefault(GenericDocument<EncodingType, typename ValueType::AllocatorType, stackAllocator>& 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 <typename stackAllocator> + ValueType& GetWithDefault(GenericDocument<EncodingType, typename ValueType::AllocatorType, stackAllocator>& document, const std::basic_string<Ch>& 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 <typename T, typename stackAllocator> + RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr<internal::IsPointer<T>, internal::IsGenericValue<T> >), (ValueType&)) + GetWithDefault(GenericDocument<EncodingType, typename ValueType::AllocatorType, stackAllocator>& 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<Ch>& 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 <typename T> + RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr<internal::IsPointer<T>, internal::IsGenericValue<T> >), (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 <typename stackAllocator> + ValueType& Set(GenericDocument<EncodingType, typename ValueType::AllocatorType, stackAllocator>& document, ValueType& value) const { + return Create(document) = value; + } + + //! Set a value in a document, with copy semantics. + template <typename stackAllocator> + ValueType& Set(GenericDocument<EncodingType, typename ValueType::AllocatorType, stackAllocator>& document, const ValueType& value) const { + return Create(document).CopyFrom(value, document.GetAllocator()); + } + + //! Set a null-terminated string in a document. + template <typename stackAllocator> + ValueType& Set(GenericDocument<EncodingType, typename ValueType::AllocatorType, stackAllocator>& 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 <typename stackAllocator> + ValueType& Set(GenericDocument<EncodingType, typename ValueType::AllocatorType, stackAllocator>& document, const std::basic_string<Ch>& 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 <typename T, typename stackAllocator> + RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr<internal::IsPointer<T>, internal::IsGenericValue<T> >), (ValueType&)) + Set(GenericDocument<EncodingType, typename ValueType::AllocatorType, stackAllocator>& 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 <typename stackAllocator> + ValueType& Swap(GenericDocument<EncodingType, typename ValueType::AllocatorType, stackAllocator>& 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<EncodingType>(GenericStringRef<Ch>(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<Ch>(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<Token *>(allocator_->Malloc(tokenCount_ * sizeof(Token) + (nameBufferSize + extraNameBufferSize) * sizeof(Ch))); + nameBuffer_ = reinterpret_cast<Ch *>(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)); + } + + // Adjust pointers to name buffer + std::ptrdiff_t diff = nameBuffer_ - rhs.nameBuffer_; + for (Token *t = tokens_; t != tokens_ + rhs.tokenCount_; ++t) + t->name += diff; + + 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<Token *>(allocator_->Malloc(tokenCount_ * sizeof(Token) + length * sizeof(Ch))); + Ch* name = nameBuffer_ = reinterpret_cast<Ch *>(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<EncodingType> os(name); + Ch* begin = os.PutBegin(); + if (!Transcoder<UTF8<>, 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<SizeType>(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<SizeType>(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 uriFragment, typename OutputStream> + 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<typename ValueType::EncodingType> source(&t->name[j]); + PercentEncodeStream<OutputStream> target(os); + if (!Transcoder<EncodingType, UTF8<> >().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<Ch>(c << 4); + Ch h = *src_; + if (h >= '0' && h <= '9') c = static_cast<Ch>(c + h - '0'); + else if (h >= 'A' && h <= 'F') c = static_cast<Ch>(c + h - 'A' + 10); + else if (h >= 'a' && h <= 'f') c = static_cast<Ch>(c + h - 'a' + 10); + else { + valid_ = false; + return 0; + } + src_++; + } + return c; + } + + size_t Tell() const { return static_cast<size_t>(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 <typename OutputStream> + class PercentEncodeStream { + public: + PercentEncodeStream(OutputStream& os) : os_(os) {} + void Put(char c) { // UTF-8 must be byte + unsigned char u = static_cast<unsigned char>(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<typename OutputStream::Ch>(hexDigits[u >> 4])); + os_.Put(static_cast<typename OutputStream::Ch>(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<Value> Pointer; + +//!@name Helper functions for GenericPointer +//@{ + +////////////////////////////////////////////////////////////////////////////// + +template <typename T> +typename T::ValueType& CreateValueByPointer(T& root, const GenericPointer<typename T::ValueType>& pointer, typename T::AllocatorType& a) { + return pointer.Create(root, a); +} + +template <typename T, typename CharType, size_t N> +typename T::ValueType& CreateValueByPointer(T& root, const CharType(&source)[N], typename T::AllocatorType& a) { + return GenericPointer<typename T::ValueType>(source, N - 1).Create(root, a); +} + +// No allocator parameter + +template <typename DocumentType> +typename DocumentType::ValueType& CreateValueByPointer(DocumentType& document, const GenericPointer<typename DocumentType::ValueType>& pointer) { + return pointer.Create(document); +} + +template <typename DocumentType, typename CharType, size_t N> +typename DocumentType::ValueType& CreateValueByPointer(DocumentType& document, const CharType(&source)[N]) { + return GenericPointer<typename DocumentType::ValueType>(source, N - 1).Create(document); +} + +////////////////////////////////////////////////////////////////////////////// + +template <typename T> +typename T::ValueType* GetValueByPointer(T& root, const GenericPointer<typename T::ValueType>& pointer, size_t* unresolvedTokenIndex = 0) { + return pointer.Get(root, unresolvedTokenIndex); +} + +template <typename T> +const typename T::ValueType* GetValueByPointer(const T& root, const GenericPointer<typename T::ValueType>& pointer, size_t* unresolvedTokenIndex = 0) { + return pointer.Get(root, unresolvedTokenIndex); +} + +template <typename T, typename CharType, size_t N> +typename T::ValueType* GetValueByPointer(T& root, const CharType (&source)[N], size_t* unresolvedTokenIndex = 0) { + return GenericPointer<typename T::ValueType>(source, N - 1).Get(root, unresolvedTokenIndex); +} + +template <typename T, typename CharType, size_t N> +const typename T::ValueType* GetValueByPointer(const T& root, const CharType(&source)[N], size_t* unresolvedTokenIndex = 0) { + return GenericPointer<typename T::ValueType>(source, N - 1).Get(root, unresolvedTokenIndex); +} + +////////////////////////////////////////////////////////////////////////////// + +template <typename T> +typename T::ValueType& GetValueByPointerWithDefault(T& root, const GenericPointer<typename T::ValueType>& pointer, const typename T::ValueType& defaultValue, typename T::AllocatorType& a) { + return pointer.GetWithDefault(root, defaultValue, a); +} + +template <typename T> +typename T::ValueType& GetValueByPointerWithDefault(T& root, const GenericPointer<typename T::ValueType>& pointer, const typename T::Ch* defaultValue, typename T::AllocatorType& a) { + return pointer.GetWithDefault(root, defaultValue, a); +} + +#if RAPIDJSON_HAS_STDSTRING +template <typename T> +typename T::ValueType& GetValueByPointerWithDefault(T& root, const GenericPointer<typename T::ValueType>& pointer, const std::basic_string<typename T::Ch>& defaultValue, typename T::AllocatorType& a) { + return pointer.GetWithDefault(root, defaultValue, a); +} +#endif + +template <typename T, typename T2> +RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr<internal::IsPointer<T2>, internal::IsGenericValue<T2> >), (typename T::ValueType&)) +GetValueByPointerWithDefault(T& root, const GenericPointer<typename T::ValueType>& pointer, T2 defaultValue, typename T::AllocatorType& a) { + return pointer.GetWithDefault(root, defaultValue, a); +} + +template <typename T, typename CharType, size_t N> +typename T::ValueType& GetValueByPointerWithDefault(T& root, const CharType(&source)[N], const typename T::ValueType& defaultValue, typename T::AllocatorType& a) { + return GenericPointer<typename T::ValueType>(source, N - 1).GetWithDefault(root, defaultValue, a); +} + +template <typename T, typename CharType, size_t N> +typename T::ValueType& GetValueByPointerWithDefault(T& root, const CharType(&source)[N], const typename T::Ch* defaultValue, typename T::AllocatorType& a) { + return GenericPointer<typename T::ValueType>(source, N - 1).GetWithDefault(root, defaultValue, a); +} + +#if RAPIDJSON_HAS_STDSTRING +template <typename T, typename CharType, size_t N> +typename T::ValueType& GetValueByPointerWithDefault(T& root, const CharType(&source)[N], const std::basic_string<typename T::Ch>& defaultValue, typename T::AllocatorType& a) { + return GenericPointer<typename T::ValueType>(source, N - 1).GetWithDefault(root, defaultValue, a); +} +#endif + +template <typename T, typename CharType, size_t N, typename T2> +RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr<internal::IsPointer<T2>, internal::IsGenericValue<T2> >), (typename T::ValueType&)) +GetValueByPointerWithDefault(T& root, const CharType(&source)[N], T2 defaultValue, typename T::AllocatorType& a) { + return GenericPointer<typename T::ValueType>(source, N - 1).GetWithDefault(root, defaultValue, a); +} + +// No allocator parameter + +template <typename DocumentType> +typename DocumentType::ValueType& GetValueByPointerWithDefault(DocumentType& document, const GenericPointer<typename DocumentType::ValueType>& pointer, const typename DocumentType::ValueType& defaultValue) { + return pointer.GetWithDefault(document, defaultValue); +} + +template <typename DocumentType> +typename DocumentType::ValueType& GetValueByPointerWithDefault(DocumentType& document, const GenericPointer<typename DocumentType::ValueType>& pointer, const typename DocumentType::Ch* defaultValue) { + return pointer.GetWithDefault(document, defaultValue); +} + +#if RAPIDJSON_HAS_STDSTRING +template <typename DocumentType> +typename DocumentType::ValueType& GetValueByPointerWithDefault(DocumentType& document, const GenericPointer<typename DocumentType::ValueType>& pointer, const std::basic_string<typename DocumentType::Ch>& defaultValue) { + return pointer.GetWithDefault(document, defaultValue); +} +#endif + +template <typename DocumentType, typename T2> +RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr<internal::IsPointer<T2>, internal::IsGenericValue<T2> >), (typename DocumentType::ValueType&)) +GetValueByPointerWithDefault(DocumentType& document, const GenericPointer<typename DocumentType::ValueType>& pointer, T2 defaultValue) { + return pointer.GetWithDefault(document, defaultValue); +} + +template <typename DocumentType, typename CharType, size_t N> +typename DocumentType::ValueType& GetValueByPointerWithDefault(DocumentType& document, const CharType(&source)[N], const typename DocumentType::ValueType& defaultValue) { + return GenericPointer<typename DocumentType::ValueType>(source, N - 1).GetWithDefault(document, defaultValue); +} + +template <typename DocumentType, typename CharType, size_t N> +typename DocumentType::ValueType& GetValueByPointerWithDefault(DocumentType& document, const CharType(&source)[N], const typename DocumentType::Ch* defaultValue) { + return GenericPointer<typename DocumentType::ValueType>(source, N - 1).GetWithDefault(document, defaultValue); +} + +#if RAPIDJSON_HAS_STDSTRING +template <typename DocumentType, typename CharType, size_t N> +typename DocumentType::ValueType& GetValueByPointerWithDefault(DocumentType& document, const CharType(&source)[N], const std::basic_string<typename DocumentType::Ch>& defaultValue) { + return GenericPointer<typename DocumentType::ValueType>(source, N - 1).GetWithDefault(document, defaultValue); +} +#endif + +template <typename DocumentType, typename CharType, size_t N, typename T2> +RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr<internal::IsPointer<T2>, internal::IsGenericValue<T2> >), (typename DocumentType::ValueType&)) +GetValueByPointerWithDefault(DocumentType& document, const CharType(&source)[N], T2 defaultValue) { + return GenericPointer<typename DocumentType::ValueType>(source, N - 1).GetWithDefault(document, defaultValue); +} + +////////////////////////////////////////////////////////////////////////////// + +template <typename T> +typename T::ValueType& SetValueByPointer(T& root, const GenericPointer<typename T::ValueType>& pointer, typename T::ValueType& value, typename T::AllocatorType& a) { + return pointer.Set(root, value, a); +} + +template <typename T> +typename T::ValueType& SetValueByPointer(T& root, const GenericPointer<typename T::ValueType>& pointer, const typename T::ValueType& value, typename T::AllocatorType& a) { + return pointer.Set(root, value, a); +} + +template <typename T> +typename T::ValueType& SetValueByPointer(T& root, const GenericPointer<typename T::ValueType>& pointer, const typename T::Ch* value, typename T::AllocatorType& a) { + return pointer.Set(root, value, a); +} + +#if RAPIDJSON_HAS_STDSTRING +template <typename T> +typename T::ValueType& SetValueByPointer(T& root, const GenericPointer<typename T::ValueType>& pointer, const std::basic_string<typename T::Ch>& value, typename T::AllocatorType& a) { + return pointer.Set(root, value, a); +} +#endif + +template <typename T, typename T2> +RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr<internal::IsPointer<T2>, internal::IsGenericValue<T2> >), (typename T::ValueType&)) +SetValueByPointer(T& root, const GenericPointer<typename T::ValueType>& pointer, T2 value, typename T::AllocatorType& a) { + return pointer.Set(root, value, a); +} + +template <typename T, typename CharType, size_t N> +typename T::ValueType& SetValueByPointer(T& root, const CharType(&source)[N], typename T::ValueType& value, typename T::AllocatorType& a) { + return GenericPointer<typename T::ValueType>(source, N - 1).Set(root, value, a); +} + +template <typename T, typename CharType, size_t N> +typename T::ValueType& SetValueByPointer(T& root, const CharType(&source)[N], const typename T::ValueType& value, typename T::AllocatorType& a) { + return GenericPointer<typename T::ValueType>(source, N - 1).Set(root, value, a); +} + +template <typename T, typename CharType, size_t N> +typename T::ValueType& SetValueByPointer(T& root, const CharType(&source)[N], const typename T::Ch* value, typename T::AllocatorType& a) { + return GenericPointer<typename T::ValueType>(source, N - 1).Set(root, value, a); +} + +#if RAPIDJSON_HAS_STDSTRING +template <typename T, typename CharType, size_t N> +typename T::ValueType& SetValueByPointer(T& root, const CharType(&source)[N], const std::basic_string<typename T::Ch>& value, typename T::AllocatorType& a) { + return GenericPointer<typename T::ValueType>(source, N - 1).Set(root, value, a); +} +#endif + +template <typename T, typename CharType, size_t N, typename T2> +RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr<internal::IsPointer<T2>, internal::IsGenericValue<T2> >), (typename T::ValueType&)) +SetValueByPointer(T& root, const CharType(&source)[N], T2 value, typename T::AllocatorType& a) { + return GenericPointer<typename T::ValueType>(source, N - 1).Set(root, value, a); +} + +// No allocator parameter + +template <typename DocumentType> +typename DocumentType::ValueType& SetValueByPointer(DocumentType& document, const GenericPointer<typename DocumentType::ValueType>& pointer, typename DocumentType::ValueType& value) { + return pointer.Set(document, value); +} + +template <typename DocumentType> +typename DocumentType::ValueType& SetValueByPointer(DocumentType& document, const GenericPointer<typename DocumentType::ValueType>& pointer, const typename DocumentType::ValueType& value) { + return pointer.Set(document, value); +} + +template <typename DocumentType> +typename DocumentType::ValueType& SetValueByPointer(DocumentType& document, const GenericPointer<typename DocumentType::ValueType>& pointer, const typename DocumentType::Ch* value) { + return pointer.Set(document, value); +} + +#if RAPIDJSON_HAS_STDSTRING +template <typename DocumentType> +typename DocumentType::ValueType& SetValueByPointer(DocumentType& document, const GenericPointer<typename DocumentType::ValueType>& pointer, const std::basic_string<typename DocumentType::Ch>& value) { + return pointer.Set(document, value); +} +#endif + +template <typename DocumentType, typename T2> +RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr<internal::IsPointer<T2>, internal::IsGenericValue<T2> >), (typename DocumentType::ValueType&)) +SetValueByPointer(DocumentType& document, const GenericPointer<typename DocumentType::ValueType>& pointer, T2 value) { + return pointer.Set(document, value); +} + +template <typename DocumentType, typename CharType, size_t N> +typename DocumentType::ValueType& SetValueByPointer(DocumentType& document, const CharType(&source)[N], typename DocumentType::ValueType& value) { + return GenericPointer<typename DocumentType::ValueType>(source, N - 1).Set(document, value); +} + +template <typename DocumentType, typename CharType, size_t N> +typename DocumentType::ValueType& SetValueByPointer(DocumentType& document, const CharType(&source)[N], const typename DocumentType::ValueType& value) { + return GenericPointer<typename DocumentType::ValueType>(source, N - 1).Set(document, value); +} + +template <typename DocumentType, typename CharType, size_t N> +typename DocumentType::ValueType& SetValueByPointer(DocumentType& document, const CharType(&source)[N], const typename DocumentType::Ch* value) { + return GenericPointer<typename DocumentType::ValueType>(source, N - 1).Set(document, value); +} + +#if RAPIDJSON_HAS_STDSTRING +template <typename DocumentType, typename CharType, size_t N> +typename DocumentType::ValueType& SetValueByPointer(DocumentType& document, const CharType(&source)[N], const std::basic_string<typename DocumentType::Ch>& value) { + return GenericPointer<typename DocumentType::ValueType>(source, N - 1).Set(document, value); +} +#endif + +template <typename DocumentType, typename CharType, size_t N, typename T2> +RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr<internal::IsPointer<T2>, internal::IsGenericValue<T2> >), (typename DocumentType::ValueType&)) +SetValueByPointer(DocumentType& document, const CharType(&source)[N], T2 value) { + return GenericPointer<typename DocumentType::ValueType>(source, N - 1).Set(document, value); +} + +////////////////////////////////////////////////////////////////////////////// + +template <typename T> +typename T::ValueType& SwapValueByPointer(T& root, const GenericPointer<typename T::ValueType>& pointer, typename T::ValueType& value, typename T::AllocatorType& a) { + return pointer.Swap(root, value, a); +} + +template <typename T, typename CharType, size_t N> +typename T::ValueType& SwapValueByPointer(T& root, const CharType(&source)[N], typename T::ValueType& value, typename T::AllocatorType& a) { + return GenericPointer<typename T::ValueType>(source, N - 1).Swap(root, value, a); +} + +template <typename DocumentType> +typename DocumentType::ValueType& SwapValueByPointer(DocumentType& document, const GenericPointer<typename DocumentType::ValueType>& pointer, typename DocumentType::ValueType& value) { + return pointer.Swap(document, value); +} + +template <typename DocumentType, typename CharType, size_t N> +typename DocumentType::ValueType& SwapValueByPointer(DocumentType& document, const CharType(&source)[N], typename DocumentType::ValueType& value) { + return GenericPointer<typename DocumentType::ValueType>(source, N - 1).Swap(document, value); +} + +////////////////////////////////////////////////////////////////////////////// + +template <typename T> +bool EraseValueByPointer(T& root, const GenericPointer<typename T::ValueType>& pointer) { + return pointer.Erase(root); +} + +template <typename T, typename CharType, size_t N> +bool EraseValueByPointer(T& root, const CharType(&source)[N]) { + return GenericPointer<typename T::ValueType>(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 0000000000000000000000000000000000000000..fe45df1d10f3c5c325af81930ba47dad7d3eb45f --- /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 OutputStream, typename SourceEncoding = UTF8<>, typename TargetEncoding = UTF8<>, typename StackAllocator = CrtAllocator, unsigned writeFlags = kWriteDefaultFlags> +class PrettyWriter : public Writer<OutputStream, SourceEncoding, TargetEncoding, StackAllocator, writeFlags> { +public: + typedef Writer<OutputStream, SourceEncoding, TargetEncoding, StackAllocator, writeFlags> 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<PrettyWriter>(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<Ch>& str) { + return String(str.data(), SizeType(str.size())); + } +#endif + + bool StartObject() { + PrettyPrefix(kObjectType); + new (Base::level_stack_.template Push<typename Base::Level>()) 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<Ch>& 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<typename Base::Level>()->inArray); // currently inside an Array, not Object + RAPIDJSON_ASSERT(0 == Base::level_stack_.template Top<typename Base::Level>()->valueCount % 2); // Object has a Key without a Value + + bool empty = Base::level_stack_.template Pop<typename Base::Level>(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>()) 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<typename Base::Level>()->inArray); + bool empty = Base::level_stack_.template Pop<typename Base::Level>(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<typename Base::Level>(); + + 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<typename OutputStream::Ch>(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 0000000000000000000000000000000000000000..a4e8953244c9b5e8b5fb1a4b15d93ddca30d93f4 --- /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 <cstdlib> // malloc(), realloc(), free(), size_t +#include <cstring> // 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 "<major>.<minor>.<patch>" 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 <string> +#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 <stdint.h> +#include <inttypes.h> +#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 <endian.h> +# 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<size_t>(7u)) & ~static_cast<size_t>(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<uint64_t>(high32) << 32) | static_cast<uint64_t>(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<type *>((reinterpret_cast<uintptr_t>(p) & static_cast<uintptr_t>(RAPIDJSON_UINT64_C2(0xFFFF0000, 0x00000000))) | reinterpret_cast<uintptr_t>(reinterpret_cast<const void*>(x)))) +#define RAPIDJSON_GETPOINTER(type, p) (reinterpret_cast<type *>(reinterpret_cast<uintptr_t>(p) & static_cast<uintptr_t>(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 <cassert> +#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 <bool x> struct STATIC_ASSERTION_FAILURE; +template <> struct STATIC_ASSERTION_FAILURE<true> { enum { value = 1 }; }; +template <size_t x> 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<bool(x) >)> \ + 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 <utility> // 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 <cassert> +#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 0000000000000000000000000000000000000000..55546601e29bdf3ed306ab5e68ac142a3e115d6e --- /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 <limits> + +#if defined(RAPIDJSON_SIMD) && defined(_MSC_VER) +#include <intrin.h> +#pragma intrinsic(_BitScanForward) +#endif +#ifdef RAPIDJSON_SSE42 +#include <nmmintrin.h> +#elif defined(RAPIDJSON_SSE2) +#include <emmintrin.h> +#elif defined(RAPIDJSON_NEON) +#include <arm_neon.h> +#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 <stdexcept> // 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 Encoding = UTF8<>, typename Derived = void> +struct BaseReaderHandler { + typedef typename Encoding::Ch Ch; + + typedef typename internal::SelectIf<internal::IsSame<Derived, void>, BaseReaderHandler, Derived>::Type Override; + + bool Default() { return true; } + bool Null() { return static_cast<Override&>(*this).Default(); } + bool Bool(bool) { return static_cast<Override&>(*this).Default(); } + bool Int(int) { return static_cast<Override&>(*this).Default(); } + bool Uint(unsigned) { return static_cast<Override&>(*this).Default(); } + bool Int64(int64_t) { return static_cast<Override&>(*this).Default(); } + bool Uint64(uint64_t) { return static_cast<Override&>(*this).Default(); } + bool Double(double) { return static_cast<Override&>(*this).Default(); } + /// enabled via kParseNumbersAsStringsFlag, string is not null-terminated (use length) + bool RawNumber(const Ch* str, SizeType len, bool copy) { return static_cast<Override&>(*this).String(str, len, copy); } + bool String(const Ch*, SizeType, bool) { return static_cast<Override&>(*this).Default(); } + bool StartObject() { return static_cast<Override&>(*this).Default(); } + bool Key(const Ch* str, SizeType len, bool copy) { return static_cast<Override&>(*this).String(str, len, copy); } + bool EndObject(SizeType) { return static_cast<Override&>(*this).Default(); } + bool StartArray() { return static_cast<Override&>(*this).Default(); } + bool EndArray(SizeType) { return static_cast<Override&>(*this).Default(); } +}; + +/////////////////////////////////////////////////////////////////////////////// +// StreamLocalCopy + +namespace internal { + +template<typename Stream, int = StreamTraits<Stream>::copyOptimization> +class StreamLocalCopy; + +//! Do copy optimization. +template<typename Stream> +class StreamLocalCopy<Stream, 1> { +public: + StreamLocalCopy(Stream& original) : s(original), original_(original) {} + ~StreamLocalCopy() { original_ = s; } + + Stream s; + +private: + StreamLocalCopy& operator=(const StreamLocalCopy&) /* = delete */; + + Stream& original_; +}; + +//! Keep reference. +template<typename Stream> +class StreamLocalCopy<Stream, 0> { +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<typename InputStream> +void SkipWhitespace(InputStream& is) { + internal::StreamLocalCopy<InputStream> 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<const char*>((reinterpret_cast<size_t>(p) + 15) & static_cast<size_t>(~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<const __m128i *>(&whitespace[0])); + + for (;; p += 16) { + const __m128i s = _mm_load_si128(reinterpret_cast<const __m128i *>(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<const __m128i *>(&whitespace[0])); + + for (; p <= end - 16; p += 16) { + const __m128i s = _mm_loadu_si128(reinterpret_cast<const __m128i *>(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<const char*>((reinterpret_cast<size_t>(p) + 15) & static_cast<size_t>(~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<const __m128i *>(&whitespaces[0][0])); + const __m128i w1 = _mm_loadu_si128(reinterpret_cast<const __m128i *>(&whitespaces[1][0])); + const __m128i w2 = _mm_loadu_si128(reinterpret_cast<const __m128i *>(&whitespaces[2][0])); + const __m128i w3 = _mm_loadu_si128(reinterpret_cast<const __m128i *>(&whitespaces[3][0])); + + for (;; p += 16) { + const __m128i s = _mm_load_si128(reinterpret_cast<const __m128i *>(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<unsigned short>(~_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<const __m128i *>(&whitespaces[0][0])); + const __m128i w1 = _mm_loadu_si128(reinterpret_cast<const __m128i *>(&whitespaces[1][0])); + const __m128i w2 = _mm_loadu_si128(reinterpret_cast<const __m128i *>(&whitespaces[2][0])); + const __m128i w3 = _mm_loadu_si128(reinterpret_cast<const __m128i *>(&whitespaces[3][0])); + + for (; p <= end - 16; p += 16) { + const __m128i s = _mm_loadu_si128(reinterpret_cast<const __m128i *>(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<unsigned short>(~_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<const char*>((reinterpret_cast<size_t>(p) + 15) & static_cast<size_t>(~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<const uint8_t *>(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<const uint8_t *>(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<char*>(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<UTF8<>, 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 <typename SourceEncoding, typename TargetEncoding, typename StackAllocator = CrtAllocator> +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 <unsigned parseFlags, typename InputStream, typename Handler> + ParseResult Parse(InputStream& is, Handler& handler) { + if (parseFlags & kParseIterativeFlag) + return IterativeParse<parseFlags>(is, handler); + + parseResult_.Clear(); + + ClearStackOnExit scope(*this); + + SkipWhitespaceAndComments<parseFlags>(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<parseFlags>(is, handler); + RAPIDJSON_PARSE_ERROR_EARLY_RETURN(parseResult_); + + if (!(parseFlags & kParseStopWhenDoneFlag)) { + SkipWhitespaceAndComments<parseFlags>(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 <typename InputStream, typename Handler> + ParseResult Parse(InputStream& is, Handler& handler) { + return Parse<kParseDefaultFlags>(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 <unsigned parseFlags, typename InputStream, typename Handler> + bool IterativeParseNext(InputStream& is, Handler& handler) { + while (RAPIDJSON_LIKELY(is.Peek() != '\0')) { + SkipWhitespaceAndComments<parseFlags>(is); + + Token t = Tokenize(is.Peek()); + IterativeParsingState n = Predict(state_, t); + IterativeParsingState d = Transit<parseFlags>(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<parseFlags>(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<unsigned parseFlags, typename InputStream> + 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<unsigned parseFlags, typename InputStream, typename Handler> + 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<parseFlags>(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<parseFlags>(is, handler, true); + RAPIDJSON_PARSE_ERROR_EARLY_RETURN_VOID; + + SkipWhitespaceAndComments<parseFlags>(is); + RAPIDJSON_PARSE_ERROR_EARLY_RETURN_VOID; + + if (RAPIDJSON_UNLIKELY(!Consume(is, ':'))) + RAPIDJSON_PARSE_ERROR(kParseErrorObjectMissColon, is.Tell()); + + SkipWhitespaceAndComments<parseFlags>(is); + RAPIDJSON_PARSE_ERROR_EARLY_RETURN_VOID; + + ParseValue<parseFlags>(is, handler); + RAPIDJSON_PARSE_ERROR_EARLY_RETURN_VOID; + + SkipWhitespaceAndComments<parseFlags>(is); + RAPIDJSON_PARSE_ERROR_EARLY_RETURN_VOID; + + ++memberCount; + + switch (is.Peek()) { + case ',': + is.Take(); + SkipWhitespaceAndComments<parseFlags>(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<unsigned parseFlags, typename InputStream, typename Handler> + 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<parseFlags>(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<parseFlags>(is, handler); + RAPIDJSON_PARSE_ERROR_EARLY_RETURN_VOID; + + ++elementCount; + SkipWhitespaceAndComments<parseFlags>(is); + RAPIDJSON_PARSE_ERROR_EARLY_RETURN_VOID; + + if (Consume(is, ',')) { + SkipWhitespaceAndComments<parseFlags>(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<unsigned parseFlags, typename InputStream, typename Handler> + 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<unsigned parseFlags, typename InputStream, typename Handler> + 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<unsigned parseFlags, typename InputStream, typename Handler> + 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<typename InputStream> + 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<typename InputStream> + 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<unsigned>(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 <typename CharType> + class StackStream { + public: + typedef CharType Ch; + + StackStream(internal::Stack<StackAllocator>& stack) : stack_(stack), length_(0) {} + RAPIDJSON_FORCEINLINE void Put(Ch c) { + *stack_.template Push<Ch>() = c; + ++length_; + } + + RAPIDJSON_FORCEINLINE void* Push(SizeType count) { + length_ += count; + return stack_.template Push<Ch>(count); + } + + size_t Length() const { return length_; } + + Ch* Pop() { + return stack_.template Pop<Ch>(length_); + } + + private: + StackStream(const StackStream&); + StackStream& operator=(const StackStream&); + + internal::Stack<StackAllocator>& stack_; + SizeType length_; + }; + + // Parse string and generate String event. Different code paths for kParseInsituFlag. + template<unsigned parseFlags, typename InputStream, typename Handler> + void ParseString(InputStream& is, Handler& handler, bool isKey = false) { + internal::StreamLocalCopy<InputStream> 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<parseFlags, SourceEncoding, SourceEncoding>(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<typename TargetEncoding::Ch*>(head); + success = (isKey ? handler.Key(str, SizeType(length), false) : handler.String(str, SizeType(length), false)); + } + else { + StackStream<typename TargetEncoding::Ch> stackStream(stack_); + ParseStringToStream<parseFlags, SourceEncoding, TargetEncoding>(s, stackStream); + RAPIDJSON_PARSE_ERROR_EARLY_RETURN_VOID; + SizeType length = static_cast<SizeType>(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<unsigned parseFlags, typename SEncoding, typename TEncoding, typename InputStream, typename OutputStream> + 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<unsigned char>(e)])) { + is.Take(); + os.Put(static_cast<typename TEncoding::Ch>(escape[static_cast<unsigned char>(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<unsigned>(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<SEncoding, TEncoding>::Validate(is, os) : + !Transcoder<SEncoding, TEncoding>::Transcode(is, os)))) + RAPIDJSON_PARSE_ERROR(kParseErrorStringInvalidEncoding, offset); + } + } + } + + template<typename InputStream, typename OutputStream> + static RAPIDJSON_FORCEINLINE void ScanCopyUnescapedString(InputStream&, OutputStream&) { + // Do nothing for generic version + } + +#if defined(RAPIDJSON_SSE2) || defined(RAPIDJSON_SSE42) + // StringStream -> StackStream<char> + static RAPIDJSON_FORCEINLINE void ScanCopyUnescapedString(StringStream& is, StackStream<char>& 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<const char*>((reinterpret_cast<size_t>(p) + 15) & static_cast<size_t>(~15)); + while (p != nextAligned) + if (RAPIDJSON_UNLIKELY(*p == '\"') || RAPIDJSON_UNLIKELY(*p == '\\') || RAPIDJSON_UNLIKELY(static_cast<unsigned>(*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<const __m128i *>(&dquote[0])); + const __m128i bs = _mm_loadu_si128(reinterpret_cast<const __m128i *>(&bslash[0])); + const __m128i sp = _mm_loadu_si128(reinterpret_cast<const __m128i *>(&space[0])); + + for (;; p += 16) { + const __m128i s = _mm_load_si128(reinterpret_cast<const __m128i *>(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<unsigned short>(_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<SizeType>(__builtin_ffs(r) - 1); + #endif + if (length != 0) { + char* q = reinterpret_cast<char*>(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<const char*>((reinterpret_cast<size_t>(p) + 15) & static_cast<size_t>(~15)); + while (p != nextAligned) + if (RAPIDJSON_UNLIKELY(*p == '\"') || RAPIDJSON_UNLIKELY(*p == '\\') || RAPIDJSON_UNLIKELY(static_cast<unsigned>(*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<const __m128i *>(&dquote[0])); + const __m128i bs = _mm_loadu_si128(reinterpret_cast<const __m128i *>(&bslash[0])); + const __m128i sp = _mm_loadu_si128(reinterpret_cast<const __m128i *>(&space[0])); + + for (;; p += 16, q += 16) { + const __m128i s = _mm_load_si128(reinterpret_cast<const __m128i *>(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<unsigned short>(_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<size_t>(__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<const char*>((reinterpret_cast<size_t>(p) + 15) & static_cast<size_t>(~15)); + for (; p != nextAligned; p++) + if (RAPIDJSON_UNLIKELY(*p == '\"') || RAPIDJSON_UNLIKELY(*p == '\\') || RAPIDJSON_UNLIKELY(static_cast<unsigned>(*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<const __m128i *>(&dquote[0])); + const __m128i bs = _mm_loadu_si128(reinterpret_cast<const __m128i *>(&bslash[0])); + const __m128i sp = _mm_loadu_si128(reinterpret_cast<const __m128i *>(&space[0])); + + for (;; p += 16) { + const __m128i s = _mm_load_si128(reinterpret_cast<const __m128i *>(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<unsigned short>(_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<size_t>(__builtin_ffs(r) - 1); +#endif + p += length; + break; + } + } + + is.src_ = is.dst_ = p; + } +#elif defined(RAPIDJSON_NEON) + // StringStream -> StackStream<char> + static RAPIDJSON_FORCEINLINE void ScanCopyUnescapedString(StringStream& is, StackStream<char>& 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<const char*>((reinterpret_cast<size_t>(p) + 15) & static_cast<size_t>(~15)); + while (p != nextAligned) + if (RAPIDJSON_UNLIKELY(*p == '\"') || RAPIDJSON_UNLIKELY(*p == '\\') || RAPIDJSON_UNLIKELY(static_cast<unsigned>(*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<const uint8_t *>(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<char*>(os.Push(length)); + for (size_t i = 0; i < length; i++) + q[i] = p[i]; + + p += length; + } + break; + } + vst1q_u8(reinterpret_cast<uint8_t *>(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<const char*>((reinterpret_cast<size_t>(p) + 15) & static_cast<size_t>(~15)); + while (p != nextAligned) + if (RAPIDJSON_UNLIKELY(*p == '\"') || RAPIDJSON_UNLIKELY(*p == '\\') || RAPIDJSON_UNLIKELY(static_cast<unsigned>(*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<uint8_t *>(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<uint8_t *>(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<const char*>((reinterpret_cast<size_t>(p) + 15) & static_cast<size_t>(~15)); + for (; p != nextAligned; p++) + if (RAPIDJSON_UNLIKELY(*p == '\"') || RAPIDJSON_UNLIKELY(*p == '\\') || RAPIDJSON_UNLIKELY(static_cast<unsigned>(*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<uint8_t *>(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<typename InputStream, typename StackCharacter, bool backup, bool pushOnTake> + class NumberStream; + + template<typename InputStream, typename StackCharacter> + class NumberStream<InputStream, StackCharacter, false, false> { + 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<typename InputStream, typename StackCharacter> + class NumberStream<InputStream, StackCharacter, true, false> : public NumberStream<InputStream, StackCharacter, false, false> { + typedef NumberStream<InputStream, StackCharacter, false, false> Base; + public: + NumberStream(GenericReader& reader, InputStream& s) : Base(reader, s), stackStream(reader.stack_) {} + + RAPIDJSON_FORCEINLINE Ch TakePush() { + stackStream.Put(static_cast<StackCharacter>(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<StackCharacter> stackStream; + }; + + template<typename InputStream, typename StackCharacter> + class NumberStream<InputStream, StackCharacter, true, true> : public NumberStream<InputStream, StackCharacter, true, false> { + typedef NumberStream<InputStream, StackCharacter, true, false> Base; + public: + NumberStream(GenericReader& reader, InputStream& s) : Base(reader, s) {} + + RAPIDJSON_FORCEINLINE Ch Take() { return Base::TakePush(); } + }; + + template<unsigned parseFlags, typename InputStream, typename Handler> + void ParseNumber(InputStream& is, Handler& handler) { + typedef typename internal::SelectIf<internal::BoolType<(parseFlags & kParseNumbersAsStringsFlag) != 0>, typename TargetEncoding::Ch, char>::Type NumberCharacter; + + internal::StreamLocalCopy<InputStream> copy(is); + NumberStream<InputStream, NumberCharacter, + ((parseFlags & kParseNumbersAsStringsFlag) != 0) ? + ((parseFlags & kParseInsituFlag) == 0) : + ((parseFlags & kParseFullPrecisionFlag) != 0), + (parseFlags & kParseNumbersAsStringsFlag) != 0 && + (parseFlags & kParseInsituFlag) == 0> 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<unsigned>(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<unsigned>(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<unsigned>(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<double>::quiet_NaN(); + useNanOrInf = true; + } + } + else if (RAPIDJSON_LIKELY(Consume(s, 'I'))) { + if (Consume(s, 'n') && Consume(s, 'f')) { + d = (minus ? -std::numeric_limits<double>::infinity() : std::numeric_limits<double>::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<double>(i64); + useDouble = true; + break; + } + i64 = i64 * 10 + static_cast<unsigned>(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<double>(i64); + useDouble = true; + break; + } + i64 = i64 * 10 + static_cast<unsigned>(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<unsigned>(s.TakePush() - '0'); + --expFrac; + if (i64 != 0) + significandDigit++; + } + } + + d = static_cast<double>(i64); +#else + // Use double to store significand in 32-bit architecture + d = static_cast<double>(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<double>(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<int>(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<int>(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<int>(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<typename TargetEncoding::Ch*>(head); + cont = handler.RawNumber(str, SizeType(length), false); + } + else { + SizeType numCharsToCopy = static_cast<SizeType>(s.Length()); + GenericStringStream<UTF8<NumberCharacter> > srcStream(s.Pop()); + StackStream<typename TargetEncoding::Ch> dstStream(stack_); + while (numCharsToCopy--) { + Transcoder<UTF8<typename TargetEncoding::Ch>, TargetEncoding>::Transcode(srcStream, dstStream); + } + dstStream.Put('\0'); + const typename TargetEncoding::Ch* str = dstStream.Pop(); + const SizeType length = static_cast<SizeType>(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<double>::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<int64_t>(~i64 + 1)); + else + cont = handler.Uint64(i64); + } + else { + if (minus) + cont = handler.Int(static_cast<int32_t>(~i + 1)); + else + cont = handler.Uint(i); + } + } + } + if (RAPIDJSON_UNLIKELY(!cont)) + RAPIDJSON_PARSE_ERROR(kParseErrorTermination, startOffset); + } + + // Parse any JSON value + template<unsigned parseFlags, typename InputStream, typename Handler> + void ParseValue(InputStream& is, Handler& handler) { + switch (is.Peek()) { + case 'n': ParseNull <parseFlags>(is, handler); break; + case 't': ParseTrue <parseFlags>(is, handler); break; + case 'f': ParseFalse <parseFlags>(is, handler); break; + case '"': ParseString<parseFlags>(is, handler); break; + case '{': ParseObject<parseFlags>(is, handler); break; + case '[': ParseArray <parseFlags>(is, handler); break; + default : + ParseNumber<parseFlags>(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<unsigned>(c) < 256) + return static_cast<Token>(tokenMap[static_cast<unsigned char>(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<IterativeParsingState>(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 <unsigned parseFlags, typename InputStream, typename Handler> + 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<SizeType>(1) = n; + // Initialize and push the member/element count. + *stack_.template Push<SizeType>(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<parseFlags>(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<parseFlags>(is, handler); + if (HasParseError()) { + return IterativeParsingErrorState; + } + return dst; + + case IterativeParsingElementState: + // Must be non-compound value. Or it would be ObjectInitial or ArrayInitial state. + ParseValue<parseFlags>(is, handler); + if (HasParseError()) { + return IterativeParsingErrorState; + } + return dst; + + case IterativeParsingMemberDelimiterState: + case IterativeParsingElementDelimiterState: + is.Take(); + // Update member/element count. + *stack_.template Top<SizeType>() = *stack_.template Top<SizeType>() + 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<SizeType>(1); + // If the object is not empty, count the last member. + if (src == IterativeParsingMemberValueState) + ++c; + // Restore the state. + IterativeParsingState n = static_cast<IterativeParsingState>(*stack_.template Pop<SizeType>(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<SizeType>(1); + // If the array is not empty, count the last element. + if (src == IterativeParsingElementState) + ++c; + // Restore the state. + IterativeParsingState n = static_cast<IterativeParsingState>(*stack_.template Pop<SizeType>(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<parseFlags>(is, handler); + if (HasParseError()) { + return IterativeParsingErrorState; + } + return IterativeParsingFinishState; + } + } + + template <typename InputStream> + 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 <unsigned parseFlags, typename InputStream, typename Handler> + ParseResult IterativeParse(InputStream& is, Handler& handler) { + parseResult_.Clear(); + ClearStackOnExit scope(*this); + IterativeParsingState state = IterativeParsingStartState; + + SkipWhitespaceAndComments<parseFlags>(is); + RAPIDJSON_PARSE_ERROR_EARLY_RETURN(parseResult_); + while (is.Peek() != '\0') { + Token t = Tokenize(is.Peek()); + IterativeParsingState n = Predict(state, t); + IterativeParsingState d = Transit<parseFlags>(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<parseFlags>(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<StackAllocator> 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<>, 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 0000000000000000000000000000000000000000..248632b0d8975a839ddc9b48ebd92c45d652e88f --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/rapidjson/schema.h @@ -0,0 +1,2808 @@ +// 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 <cmath> // 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 <regex> +#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 + +#if RAPIDJSON_SCHEMA_VERBOSE +#include "stringbuffer.h" +#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 PrintInvalidKeyword(const char* keyword) { + printf("Fail keyword: %s\n", keyword); +} + +inline void PrintInvalidKeyword(const wchar_t* keyword) { + wprintf(L"Fail keyword: %ls\n", keyword); +} + +inline void PrintInvalidDocument(const char* document) { + printf("Fail document: %s\n\n", document); +} + +inline void PrintInvalidDocument(const wchar_t* document) { + wprintf(L"Fail document: %ls\n\n", document); +} + +inline void PrintValidatorPointers(unsigned depth, const char* s, const char* d) { + printf("S: %*s%s\nD: %*s%s\n\n", depth * 4, " ", s, depth * 4, " ", d); +} + +inline void PrintValidatorPointers(unsigned depth, const wchar_t* s, const wchar_t* d) { + wprintf(L"S: %*ls%ls\nD: %*ls%ls\n\n", depth * 4, L" ", s, depth * 4, L" ", d); +} + +} // namespace internal + +#endif // RAPIDJSON_SCHEMA_VERBOSE + +/////////////////////////////////////////////////////////////////////////////// +// RAPIDJSON_INVALID_KEYWORD_RETURN + +#if RAPIDJSON_SCHEMA_VERBOSE +#define RAPIDJSON_INVALID_KEYWORD_VERBOSE(keyword) internal::PrintInvalidKeyword(keyword) +#else +#define RAPIDJSON_INVALID_KEYWORD_VERBOSE(keyword) +#endif + +#define RAPIDJSON_INVALID_KEYWORD_RETURN(code)\ +RAPIDJSON_MULTILINEMACRO_BEGIN\ + context.invalidCode = code;\ + context.invalidKeyword = SchemaType::GetValidateErrorKeyword(code).GetString();\ + RAPIDJSON_INVALID_KEYWORD_VERBOSE(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. + kValidateDefaultFlags = RAPIDJSON_VALIDATE_DEFAULT_FLAGS //!< Default validate flags. Can be customized by defining RAPIDJSON_VALIDATE_DEFAULT_FLAGS +}; + +/////////////////////////////////////////////////////////////////////////////// +// Forward declarations + +template <typename ValueType, typename Allocator> +class GenericSchemaDocument; + +namespace internal { + +template <typename SchemaDocumentType> +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 <typename SchemaType> +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 <typename SchemaType> +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, bool matched) = 0; + virtual void Disallowed() = 0; +}; + + +/////////////////////////////////////////////////////////////////////////////// +// Hasher + +// For comparison of compound value +template<typename Encoding, typename Allocator> +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<double>(i); return WriteNumber(n); } + bool Uint(unsigned u) { Number n; n.u.u = u; n.d = static_cast<double>(u); return WriteNumber(n); } + bool Int64(int64_t i) { Number n; n.u.i = i; n.d = static_cast<double>(i); return WriteNumber(n); } + bool Uint64(uint64_t u) { Number n; n.u.u = u; n.d = static_cast<double>(u); return WriteNumber(n); } + bool Double(double d) { + Number n; + if (d < 0) n.u.i = static_cast<int64_t>(d); + else n.u.u = static_cast<uint64_t>(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<uint64_t>(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<uint64_t>() = h; + return true; + } + + bool StartArray() { return true; } + bool EndArray(SizeType elementCount) { + uint64_t h = Hash(0, kArrayType); + uint64_t* e = stack_.template Pop<uint64_t>(elementCount); + for (SizeType i = 0; i < elementCount; i++) + h = Hash(h, e[i]); // Use hash to achieve element order sensitive + *stack_.template Push<uint64_t>() = h; + return true; + } + + bool IsValid() const { return stack_.GetSize() == sizeof(uint64_t); } + + uint64_t GetHashCode() const { + RAPIDJSON_ASSERT(IsValid()); + return *stack_.template Top<uint64_t>(); + } + +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<const unsigned char*>(data); + for (size_t i = 0; i < len; i++) + h = Hash(h, d[i]); + *stack_.template Push<uint64_t>() = 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<Allocator> stack_; +}; + +/////////////////////////////////////////////////////////////////////////////// +// SchemaValidationContext + +template <typename SchemaDocumentType> +struct SchemaValidationContext { + typedef Schema<SchemaDocumentType> SchemaType; + typedef ISchemaStateFactory<SchemaType> SchemaValidatorFactoryType; + typedef IValidationErrorHandler<SchemaType> ErrorHandlerType; + typedef typename SchemaType::ValueType ValueType; + typedef typename ValueType::Ch Ch; + + enum PatternValidatorType { + kPatternValidatorOnly, + kPatternValidatorWithProperty, + kPatternValidatorWithAdditionalProperty + }; + + SchemaValidationContext(SchemaValidatorFactoryType& f, ErrorHandlerType& eh, const SchemaType* s) : + factory(f), + error_handler(eh), + schema(s), + 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++) + factory.DestroySchemaValidator(validators[i]); + factory.FreeState(validators); + } + if (patternPropertiesValidators) { + for (SizeType i = 0; i < patternPropertiesValidatorCount; 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; + 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 <typename SchemaDocumentType> +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<SchemaDocumentType> Context; + typedef Schema<SchemaDocumentType> SchemaType; + typedef GenericValue<EncodingType, AllocatorType> SValue; + typedef IValidationErrorHandler<Schema> ErrorHandler; + typedef GenericUri<ValueType, AllocatorType> UriType; + friend class GenericSchemaDocument<ValueType, AllocatorType>; + + 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), + 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) + { + 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<SchemaEntry>(); + 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 + if (const ValueType* v = GetMember(value, GetIdString())) { + if (v->IsString()) { + UriType local(*v, allocator); + id_ = local.Resolve(id_, allocator); + } + } + + 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<uint64_t*>(allocator_->Malloc(sizeof(uint64_t) * v->Size())); + for (ConstValueIterator itr = v->Begin(); itr != v->End(); ++itr) { + typedef Hasher<EncodingType, MemoryPoolAllocator<> > 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); + 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); + + 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<Property*>(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_); + } + } + + if (const ValueType* v = GetMember(value, GetPatternPropertiesString())) { + PointerType q = p.Append(GetPatternPropertiesString(), allocator_); + patternProperties_ = static_cast<PatternProperty*>(allocator_->Malloc(sizeof(PatternProperty) * v->MemberCount())); + patternPropertyCount_ = 0; + + for (ConstMemberIterator itr = v->MemberBegin(); itr != v->MemberEnd(); ++itr) { + new (&patternProperties_[patternPropertyCount_]) PatternProperty(); + patternProperties_[patternPropertyCount_].pattern = CreatePattern(itr->name); + schemaDocument->CreateSchema(&patternProperties_[patternPropertyCount_].schema, q.Append(itr->name, allocator_), 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; + } + } + + 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<bool*>(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<const Schema**>(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()); + + 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); + + // 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(); + + } + + ~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 PointerType& GetPointer() const { + return pointer_; + } + + bool BeginValue(Context& context) const { + 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 { + // 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; + for (SizeType i = oneOf_.begin; i < oneOf_.begin + oneOf_.count; i++) + if (context.validators[i]->IsValid()) { + if (oneValid) { + context.error_handler.NotOneOf(&context.validators[oneOf_.begin], oneOf_.count, true); + RAPIDJSON_INVALID_KEYWORD_RETURN(kValidateErrorOneOfMatch); + } else + oneValid = true; + } + if (!oneValid) { + context.error_handler.NotOneOf(&context.validators[oneOf_.begin], oneOf_.count, false); + 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 { + if (!(type_ & (1 << kNullSchemaType))) { + DisallowedType(context, GetNullString()); + RAPIDJSON_INVALID_KEYWORD_RETURN(kValidateErrorType); + } + return CreateParallelValidator(context); + } + + bool Bool(Context& context, bool) const { + if (!(type_ & (1 << kBooleanSchemaType))) { + DisallowedType(context, GetBooleanString()); + RAPIDJSON_INVALID_KEYWORD_RETURN(kValidateErrorType); + } + return CreateParallelValidator(context); + } + + bool Int(Context& context, int i) const { + if (!CheckInt(context, i)) + return false; + return CreateParallelValidator(context); + } + + bool Uint(Context& context, unsigned u) const { + if (!CheckUint(context, u)) + return false; + return CreateParallelValidator(context); + } + + bool Int64(Context& context, int64_t i) const { + if (!CheckInt(context, i)) + return false; + return CreateParallelValidator(context); + } + + bool Uint64(Context& context, uint64_t u) const { + if (!CheckUint(context, u)) + return false; + return CreateParallelValidator(context); + } + + bool Double(Context& context, double d) const { + 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 { + if (!(type_ & (1 << kStringSchemaType))) { + DisallowedType(context, GetStringString()); + RAPIDJSON_INVALID_KEYWORD_RETURN(kValidateErrorType); + } + + if (minLength_ != 0 || maxLength_ != SizeType(~0)) { + SizeType count; + if (internal::CountStringCodePoint<EncodingType>(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 { + if (!(type_ & (1 << kObjectSchemaType))) { + DisallowedType(context, GetObjectString()); + RAPIDJSON_INVALID_KEYWORD_RETURN(kValidateErrorType); + } + + if (hasDependencies_ || hasRequired_) { + context.propertyExist = static_cast<bool*>(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<const SchemaType**>(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 { + 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 { + 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 { + 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 { + 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(); + + 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<SizeType>(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_(Ref, '$', 'r', 'e', 'f') + RAPIDJSON_STRING_(Id, 'i', 'd') + + RAPIDJSON_STRING_(SchemeEnd, ':') + RAPIDJSON_STRING_(AuthStart, '/', '/') + RAPIDJSON_STRING_(QueryStart, '?') + RAPIDJSON_STRING_(FragStart, '#') + RAPIDJSON_STRING_(Slash, '/') + RAPIDJSON_STRING_(Dot, '.') + +#undef RAPIDJSON_STRING_ + +private: + enum SchemaValueType { + kNullSchemaType, + kBooleanSchemaType, + kObjectSchemaType, + kArraySchemaType, + kStringSchemaType, + kNumberSchemaType, + kIntegerSchemaType, + kTotalSchemaType + }; + +#if RAPIDJSON_SCHEMA_USE_INTERNALREGEX + typedef internal::GenericRegex<EncodingType, AllocatorType> RegexType; +#elif RAPIDJSON_SCHEMA_USE_STDREGEX + typedef std::basic_regex<Ch> 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 <typename V1, typename V2> + 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<SizeType>(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<const Schema**>(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 <typename ValueType> + RegexType* CreatePattern(const ValueType& value) { + if (value.IsString()) { + RegexType* r = new (allocator_->Malloc(sizeof(RegexType))) RegexType(value.GetString(), allocator_); + if (!r->IsValid()) { + r->~RegexType(); + AllocatorType::Free(r); + r = 0; + } + return r; + } + return 0; + } + + static bool IsPatternMatch(const RegexType* pattern, const Ch *str, SizeType) { + GenericRegexSearch<RegexType> rs(*pattern); + return rs.Search(str); + } +#elif RAPIDJSON_SCHEMA_USE_STDREGEX + template <typename ValueType> + RegexType* CreatePattern(const ValueType& value) { + if (value.IsString()) { + RegexType *r = static_cast<RegexType*>(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&) { + AllocatorType::Free(r); + } + } + return 0; + } + + static bool IsPatternMatch(const RegexType* pattern, const Ch *str, SizeType length) { + std::match_results<const Ch*> r; + return std::regex_search(str, str + length, r, *pattern); + } +#else + template <typename ValueType> + 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); + } + + 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<ISchemaValidator**>(context.factory.MallocState(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); + } + } + + 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 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<double>(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<double>(i))) + return false; + } + + if (!multipleOf_.IsNull()) { + if (multipleOf_.IsUint64()) { + if (static_cast<uint64_t>(i >= 0 ? i : -i) % multipleOf_.GetUint64() != 0) { + context.error_handler.NotMultipleOf(i, multipleOf_); + RAPIDJSON_INVALID_KEYWORD_RETURN(kValidateErrorMultipleOf); + } + } + else if (!CheckDoubleMultipleOf(context, static_cast<double>(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<double>(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<double>(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<double>(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_; + 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_; +}; + +template<typename Stack, typename Ch> +struct TokenHelper { + RAPIDJSON_FORCEINLINE static void AppendIndexToken(Stack& documentStack, SizeType index) { + *documentStack.template Push<Ch>() = '/'; + char buffer[21]; + size_t length = static_cast<size_t>((sizeof(SizeType) == 4 ? u32toa(index, buffer) : u64toa(index, buffer)) - buffer); + for (size_t i = 0; i < length; i++) + *documentStack.template Push<Ch>() = static_cast<Ch>(buffer[i]); + } +}; + +// Partial specialized version for char to prevent buffer copying. +template <typename Stack> +struct TokenHelper<Stack, char> { + RAPIDJSON_FORCEINLINE static void AppendIndexToken(Stack& documentStack, SizeType index) { + if (sizeof(SizeType) == 4) { + char *buffer = documentStack.template Push<char>(1 + 10); // '/' + uint + *buffer++ = '/'; + const char* end = internal::u32toa(index, buffer); + documentStack.template Pop<char>(static_cast<size_t>(10 - (end - buffer))); + } + else { + char *buffer = documentStack.template Push<char>(1 + 20); // '/' + uint64 + *buffer++ = '/'; + const char* end = internal::u64toa(index, buffer); + documentStack.template Pop<char>(static_cast<size_t>(20 - (end - buffer))); + } + } +}; + +} // namespace internal + +/////////////////////////////////////////////////////////////////////////////// +// IGenericRemoteSchemaDocumentProvider + +template <typename SchemaDocumentType> +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(GenericUri<ValueType, AllocatorType> uri) { 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 <typename ValueT, typename Allocator = CrtAllocator> +class GenericSchemaDocument { +public: + typedef ValueT ValueType; + typedef IGenericRemoteSchemaDocumentProvider<GenericSchemaDocument> IRemoteSchemaDocumentProviderType; + typedef Allocator AllocatorType; + typedef typename ValueType::EncodingType EncodingType; + typedef typename EncodingType::Ch Ch; + typedef internal::Schema<GenericSchemaDocument> SchemaType; + typedef GenericPointer<ValueType, Allocator> PointerType; + typedef GenericValue<EncodingType, AllocatorType> SValue; + typedef GenericUri<ValueType, Allocator> UriType; + friend class internal::Schema<GenericSchemaDocument>; + template <typename, typename, typename> + 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 + */ + explicit GenericSchemaDocument(const ValueType& document, const Ch* uri = 0, SizeType uriLength = 0, + IRemoteSchemaDocumentProviderType* remoteProvider = 0, Allocator* allocator = 0, + const PointerType& pointer = PointerType()) : // PR #1393 + remoteProvider_(remoteProvider), + allocator_(allocator), + ownAllocator_(), + root_(), + typeless_(), + schemaMap_(allocator, kInitialSchemaMapSize), + schemaRef_(allocator, kInitialSchemaRefSize) + { + 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<SchemaType*>(allocator_->Malloc(sizeof(SchemaType))); + new (typeless_) SchemaType(this, PointerType(), ValueType(kObjectType).Move(), ValueType(kObjectType).Move(), allocator_, docId_); + + // 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_); + } + + 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_(rhs.docId_) + { + rhs.remoteProvider_ = 0; + rhs.allocator_ = 0; + rhs.ownAllocator_ = 0; + rhs.typeless_ = 0; + } +#endif + + //! Destructor + ~GenericSchemaDocument() { + while (!schemaMap_.Empty()) + schemaMap_.template Pop<SchemaEntry>(1)->~SchemaEntry(); + + if (typeless_) { + typeless_->~SchemaType(); + Allocator::Free(typeless_); + } + + RAPIDJSON_DELETE(ownAllocator_); + } + + const SValue& GetURI() const { return uri_; } + + //! Get the root schema. + const SchemaType& GetRoot() const { return *root_; } + +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; + }; + + // 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()); + if (v.IsObject()) { + if (const SchemaType* sc = GetSchema(pointer)) { + if (schema) + *schema = sc; + AddSchemaRefs(const_cast<SchemaType*>(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; + + // Resolve the source pointer to the $ref'ed schema (finally) + new (schemaRef_.template Push<SchemaRefPtr>()) SchemaRefPtr(&source); + + if (itr->value.IsString()) { + SizeType len = itr->value.GetStringLength(); + if (len > 0) { + // First resolve $ref against the in-scope id + UriType scopeId = UriType(id, allocator_); + UriType ref = UriType(itr->value, allocator_).Resolve(scopeId, allocator_); + // 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_) { + if (const GenericSchemaDocument* remoteDocument = remoteProvider_->GetRemoteDocument(ref)) { + 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()) { + // Get the subschema + if (const SchemaType *sc = remoteDocument->GetSchema(pointer)) { + if (schema) + *schema = sc; + AddSchemaRefs(const_cast<SchemaType *>(sc)); + return true; + } + } + } else { + // Plain name fragment, not allowed + } + } + } + } + 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()) { + // Get the subschema + if (const ValueType *pv = relPointer.Get(*base)) { + // Now get the absolute JSON pointer by adding relative to base + PointerType pointer(basePointer); + for (SizeType i = 0; i < relPointer.GetTokenCount(); i++) + pointer = pointer.Append(relPointer.GetTokens()[i], allocator_); + //GenericStringBuffer<EncodingType> sb; + //pointer.StringifyUriFragment(sb); + if (pointer.IsValid() && !IsCyclicRef(pointer)) { + // 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 { + // Plain name fragment, relative to the resolved URI + // 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. + PointerType pointer = PointerType(); + if (const ValueType *pv = FindId(*base, ref, pointer, UriType(ref.GetBaseString(), ref.GetBaseStringLength(), allocator_), true, basePointer)) { + if (!IsCyclicRef(pointer)) { + //GenericStringBuffer<EncodingType> sb; + //pointer.StringifyUriFragment(sb); + // 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; + } + } + } + } + } + } + + // 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)) { + resval = const_cast<ValueType *>(&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) { + while (!schemaRef_.Empty()) { + SchemaRefPtr *ref = schemaRef_.template Pop<SchemaRefPtr>(1); + SchemaEntry *entry = schemaMap_.template Push<SchemaEntry>(); + new (entry) SchemaEntry(**ref, schema, false, allocator_); + } + } + + // Added by PR #1393 + bool IsCyclicRef(const PointerType& pointer) const { + for (const SchemaRefPtr* ref = schemaRef_.template Bottom<SchemaRefPtr>(); ref != schemaRef_.template End<SchemaRefPtr>(); ++ref) + if (pointer == **ref) + return true; + return false; + } + + const SchemaType* GetSchema(const PointerType& pointer) const { + for (const SchemaEntry* target = schemaMap_.template Bottom<SchemaEntry>(); target != schemaMap_.template End<SchemaEntry>(); ++target) + if (pointer == target->pointer) + return target->schema; + return 0; + } + + PointerType GetPointer(const SchemaType* schema) const { + for (const SchemaEntry* target = schemaMap_.template Bottom<SchemaEntry>(); target != schemaMap_.template End<SchemaEntry>(); ++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<Allocator> schemaMap_; // Stores created Pointer -> Schemas + internal::Stack<Allocator> schemaRef_; // Stores Pointer(s) from $ref(s) until resolved + SValue uri_; // Schema document URI + UriType docId_; +}; + +//! GenericSchemaDocument using Value type. +typedef GenericSchemaDocument<Value> SchemaDocument; +//! IGenericRemoteSchemaDocumentProvider using SchemaDocument. +typedef IGenericRemoteSchemaDocumentProvider<SchemaDocument> 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 SchemaDocumentType::SchemaType::EncodingType>, + typename StateAllocator = CrtAllocator> +class GenericSchemaValidator : + public internal::ISchemaStateFactory<typename SchemaDocumentType::SchemaType>, + public internal::ISchemaValidator, + public internal::IValidationErrorHandler<typename SchemaDocumentType::SchemaType> { +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<Ch> StringRefType; + typedef GenericValue<EncodingType, StateAllocator> 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) +#if RAPIDJSON_SCHEMA_VERBOSE + , depth_(0) +#endif + { + } + + //! 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) +#if RAPIDJSON_SCHEMA_VERBOSE + , depth_(0) +#endif + { + } + + //! 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_; + } + + //! Checks whether the current state is valid. + // Implementation of ISchemaValidator + virtual bool IsValid() const { + if (!valid_) return false; + if (GetContinueOnErrors() && !error_.ObjectEmpty()) return false; + return true; + } + + //! 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<Ch>(), 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<GenericSchemaValidator*>(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<GenericSchemaValidator*>(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<GenericSchemaValidator*>(subvalidators[i])->GetError()); + //} + } + void NoneOf(ISchemaValidator** subvalidators, SizeType count) { + AddErrorArray(kValidateErrorAnyOf, subvalidators, count); + } + void NotOneOf(ISchemaValidator** subvalidators, SizeType count, bool matched = false) { + AddErrorArray(matched ? kValidateErrorOneOfMatch : kValidateErrorOneOf, subvalidators, count); + } + void Disallowed() { + currentError_.SetObject(); + AddCurrentError(kValidateErrorNot); + } + +#define RAPIDJSON_STRING_(name, ...) \ + static const StringRefType& Get##name##String() {\ + static const Ch s[] = { __VA_ARGS__, '\0' };\ + static const StringRefType v(s, static_cast<SizeType>(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') + +#undef RAPIDJSON_STRING_ + +#if RAPIDJSON_SCHEMA_VERBOSE +#define RAPIDJSON_SCHEMA_HANDLE_BEGIN_VERBOSE_() \ +RAPIDJSON_MULTILINEMACRO_BEGIN\ + *documentStack_.template Push<Ch>() = '\0';\ + documentStack_.template Pop<Ch>(1);\ + internal::PrintInvalidDocument(documentStack_.template Bottom<Ch>());\ +RAPIDJSON_MULTILINEMACRO_END +#else +#define RAPIDJSON_SCHEMA_HANDLE_BEGIN_VERBOSE_() +#endif + +#define RAPIDJSON_SCHEMA_HANDLE_BEGIN_(method, arg1)\ + if (!valid_) return false; \ + if ((!BeginValue() && !GetContinueOnErrors()) || (!CurrentSchema().method arg1 && !GetContinueOnErrors())) {\ + RAPIDJSON_SCHEMA_HANDLE_BEGIN_VERBOSE_();\ + valid_ = false;\ + return valid_;\ + } + +#define RAPIDJSON_SCHEMA_HANDLE_PARALLEL_(method, arg2)\ + for (Context* context = schemaStack_.template Bottom<Context>(); context != schemaStack_.template End<Context>(); context++) {\ + if (context->hasher)\ + static_cast<HasherType*>(context->hasher)->method arg2;\ + if (context->validators)\ + for (SizeType i_ = 0; i_ < context->validatorCount; i_++)\ + static_cast<GenericSchemaValidator*>(context->validators[i_])->method arg2;\ + if (context->patternPropertiesValidators)\ + for (SizeType i_ = 0; i_ < context->patternPropertiesValidatorCount; i_++)\ + static_cast<GenericSchemaValidator*>(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_HANDLE_BEGIN_(StartObject, (CurrentContext())); + RAPIDJSON_SCHEMA_HANDLE_PARALLEL_(StartObject, ()); + valid_ = !outputHandler_ || outputHandler_->StartObject(); + return valid_; + } + + bool Key(const Ch* str, SizeType len, bool copy) { + 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) { + 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_HANDLE_BEGIN_(StartArray, (CurrentContext())); + RAPIDJSON_SCHEMA_HANDLE_PARALLEL_(StartArray, ()); + valid_ = !outputHandler_ || outputHandler_->StartArray(); + return valid_; + } + + bool EndArray(SizeType elementCount) { + 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_VERBOSE_ +#undef RAPIDJSON_SCHEMA_HANDLE_BEGIN_ +#undef RAPIDJSON_SCHEMA_HANDLE_PARALLEL_ +#undef RAPIDJSON_SCHEMA_HANDLE_VALUE_ + + // Implementation of ISchemaStateFactory<SchemaType> + virtual ISchemaValidator* CreateSchemaValidator(const SchemaType& root, const bool inheritContinueOnErrors) { + ISchemaValidator* sv = new (GetStateAllocator().Malloc(sizeof(GenericSchemaValidator))) GenericSchemaValidator(*schemaDocument_, root, documentStack_.template Bottom<char>(), documentStack_.GetSize(), +#if RAPIDJSON_SCHEMA_VERBOSE + depth_ + 1, +#endif + &GetStateAllocator()); + sv->SetValidateFlags(inheritContinueOnErrors ? GetValidateFlags() : GetValidateFlags() & ~(unsigned)kValidateContinueOnErrorFlag); + return sv; + } + + virtual void DestroySchemaValidator(ISchemaValidator* validator) { + GenericSchemaValidator* v = static_cast<GenericSchemaValidator*>(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<HasherType*>(hasher)->GetHashCode(); + } + + virtual void DestroryHasher(void* hasher) { + HasherType* h = static_cast<HasherType*>(hasher); + h->~HasherType(); + StateAllocator::Free(h); + } + + virtual void* MallocState(size_t size) { + return GetStateAllocator().Malloc(size); + } + + virtual void FreeState(void* p) { + StateAllocator::Free(p); + } + +private: + typedef typename SchemaType::Context Context; + typedef GenericValue<UTF8<>, StateAllocator> HashCodeArray; + typedef internal::Hasher<EncodingType, StateAllocator> HasherType; + + GenericSchemaValidator( + const SchemaDocumentType& schemaDocument, + const SchemaType& root, + const char* basePath, size_t basePathSize, +#if RAPIDJSON_SCHEMA_VERBOSE + unsigned depth, +#endif + 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) +#if RAPIDJSON_SCHEMA_VERBOSE + , depth_(depth) +#endif + { + if (basePath && basePathSize) + memcpy(documentStack_.template Push<char>(basePathSize), basePath, basePathSize); + } + + StateAllocator& GetStateAllocator() { + if (!stateAllocator_) + stateAllocator_ = ownStateAllocator_ = RAPIDJSON_NEW(StateAllocator)(); + return *stateAllocator_; + } + + bool GetContinueOnErrors() const { + return flags_ & kValidateContinueOnErrorFlag; + } + + bool BeginValue() { + if (schemaStack_.Empty()) + PushSchema(root_); + else { + if (CurrentContext().inArray) + internal::TokenHelper<internal::Stack<StateAllocator>, 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<ISchemaValidator**>(MallocState(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() { + if (!CurrentSchema().EndValue(CurrentContext()) && !GetContinueOnErrors()) + return false; + +#if RAPIDJSON_SCHEMA_VERBOSE + GenericStringBuffer<EncodingType> sb; + schemaDocument_->GetPointer(&CurrentSchema()).Stringify(sb); + + *documentStack_.template Push<Ch>() = '\0'; + documentStack_.template Pop<Ch>(1); + internal::PrintValidatorPointers(depth_, sb.GetString(), documentStack_.template Bottom<Ch>()); +#endif + void* hasher = CurrentContext().hasher; + uint64_t h = hasher && CurrentContext().arrayUniqueness ? static_cast<HasherType*>(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<HashCodeArray*>(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<SizeType>(itr - a->Begin()), a->Size()); + // Cleanup before returning if continuing + if (GetContinueOnErrors()) { + a->PushBack(h, GetStateAllocator()); + while (!documentStack_.Empty() && *documentStack_.template Pop<Ch>(1) != '/'); + } + RAPIDJSON_INVALID_KEYWORD_RETURN(kValidateErrorUniqueItems); + } + a->PushBack(h, GetStateAllocator()); + } + } + + // Remove the last token of document pointer + while (!documentStack_.Empty() && *documentStack_.template Pop<Ch>(1) != '/') + ; + + return true; + } + + void AppendToken(const Ch* str, SizeType len) { + documentStack_.template Reserve<Ch>(1 + len * 2); // worst case all characters are escaped as two characters + *documentStack_.template PushUnsafe<Ch>() = '/'; + for (SizeType i = 0; i < len; i++) { + if (str[i] == '~') { + *documentStack_.template PushUnsafe<Ch>() = '~'; + *documentStack_.template PushUnsafe<Ch>() = '0'; + } + else if (str[i] == '/') { + *documentStack_.template PushUnsafe<Ch>() = '~'; + *documentStack_.template PushUnsafe<Ch>() = '1'; + } + else + *documentStack_.template PushUnsafe<Ch>() = str[i]; + } + } + + RAPIDJSON_FORCEINLINE void PushSchema(const SchemaType& schema) { new (schemaStack_.template Push<Context>()) Context(*this, *this, &schema); } + + RAPIDJSON_FORCEINLINE void PopSchema() { + Context* c = schemaStack_.template Pop<Context>(1); + if (HashCodeArray* a = static_cast<HashCodeArray*>(c->arrayElementHashCodes)) { + a->~HashCodeArray(); + StateAllocator::Free(a); + } + c->~Context(); + } + + void AddErrorInstanceLocation(ValueType& result, bool parent) { + GenericStringBuffer<EncodingType> sb; + PointerType instancePointer = GetInvalidDocumentPointer(); + ((parent && instancePointer.GetTokenCount() > 0) + ? PointerType(instancePointer.GetTokens(), instancePointer.GetTokenCount() - 1) + : instancePointer).StringifyUriFragment(sb); + ValueType instanceRef(sb.GetString(), static_cast<SizeType>(sb.GetSize() / sizeof(Ch)), + GetStateAllocator()); + result.AddMember(GetInstanceRefString(), instanceRef, GetStateAllocator()); + } + + void AddErrorSchemaLocation(ValueType& result, PointerType schema = PointerType()) { + GenericStringBuffer<EncodingType> 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<SizeType>(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<GenericSchemaValidator*>(subvalidators[i])->GetError(), GetStateAllocator()); + currentError_.SetObject(); + currentError_.AddMember(GetErrorsString(), errors, GetStateAllocator()); + AddCurrentError(code); + } + + const SchemaType& CurrentSchema() const { return *schemaStack_.template Top<Context>()->schema; } + Context& CurrentContext() { return *schemaStack_.template Top<Context>(); } + const Context& CurrentContext() const { return *schemaStack_.template Top<Context>(); } + + static const size_t kDefaultSchemaStackCapacity = 1024; + static const size_t kDefaultDocumentStackCapacity = 256; + const SchemaDocumentType* schemaDocument_; + const SchemaType& root_; + StateAllocator* stateAllocator_; + StateAllocator* ownStateAllocator_; + internal::Stack<StateAllocator> schemaStack_; //!< stack to store the current path of schema (BaseSchemaType *) + internal::Stack<StateAllocator> documentStack_; //!< stack to store the current path of validating document (Ch) + OutputHandler* outputHandler_; + ValueType error_; + ValueType currentError_; + ValueType missingDependents_; + bool valid_; + unsigned flags_; +#if RAPIDJSON_SCHEMA_VERBOSE + unsigned depth_; +#endif +}; + +typedef GenericSchemaValidator<SchemaDocument> 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<SourceEncoding, StackAllocator> 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 <typename Handler> + bool operator()(Handler& handler) { + GenericReader<SourceEncoding, typename SchemaDocumentType::EncodingType, StackAllocator> reader; + GenericSchemaValidator<SchemaDocumentType, Handler> validator(sd_, handler); + parseResult_ = reader.template Parse<parseFlags>(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 0000000000000000000000000000000000000000..1fd70915c5472a570e8337ba7b6c4f9366398c07 --- /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<typename Stream> +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<StringStream>. + */ + enum { copyOptimization = 0 }; +}; + +//! Reserve n characters for writing to a stream. +template<typename Stream> +inline void PutReserve(Stream& stream, size_t count) { + (void)stream; + (void)count; +} + +//! Write character to a stream, presuming buffer is reserved. +template<typename Stream> +inline void PutUnsafe(Stream& stream, typename Stream::Ch c) { + stream.Put(c); +} + +//! Put N copies of a character to a stream. +template<typename Stream, typename Ch> +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 <typename InputStream, typename Encoding = UTF8<> > +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 <typename Encoding> +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<size_t>(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 <typename Encoding> +struct StreamTraits<GenericStringStream<Encoding> > { + enum { copyOptimization = 1 }; +}; + +//! String stream with UTF8 encoding. +typedef GenericStringStream<UTF8<> > StringStream; + +/////////////////////////////////////////////////////////////////////////////// +// InsituStringStream + +//! A read-write string stream. +/*! This string stream is particularly designed for in-situ parsing. + \note implements Stream concept +*/ +template <typename Encoding> +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<size_t>(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<size_t>(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 <typename Encoding> +struct StreamTraits<GenericInsituStringStream<Encoding> > { + enum { copyOptimization = 1 }; +}; + +//! Insitu string stream with UTF8 encoding. +typedef GenericInsituStringStream<UTF8<> > 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 0000000000000000000000000000000000000000..82ad3ca6bbfe8adfc805ff7b471cec1386a99727 --- /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 <utility> // 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 <typename Encoding, typename Allocator = CrtAllocator> +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<Ch>() = c; } + void PutUnsafe(Ch c) { *stack_.template PushUnsafe<Ch>() = c; } + void Flush() {} + + void Clear() { stack_.Clear(); } + void ShrinkToFit() { + // Push and pop a null terminator. This is safe. + *stack_.template Push<Ch>() = '\0'; + stack_.ShrinkToFit(); + stack_.template Pop<Ch>(1); + } + + void Reserve(size_t count) { stack_.template Reserve<Ch>(count); } + Ch* Push(size_t count) { return stack_.template Push<Ch>(count); } + Ch* PushUnsafe(size_t count) { return stack_.template PushUnsafe<Ch>(count); } + void Pop(size_t count) { stack_.template Pop<Ch>(count); } + + const Ch* GetString() const { + // Push and pop a null terminator. This is safe. + *stack_.template Push<Ch>() = '\0'; + stack_.template Pop<Ch>(1); + + return stack_.template Bottom<Ch>(); + } + + //! 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<Allocator> stack_; + +private: + // Prohibit copy constructor & assignment operator. + GenericStringBuffer(const GenericStringBuffer&); + GenericStringBuffer& operator=(const GenericStringBuffer&); +}; + +//! String buffer with UTF8 encoding +typedef GenericStringBuffer<UTF8<> > StringBuffer; + +template<typename Encoding, typename Allocator> +inline void PutReserve(GenericStringBuffer<Encoding, Allocator>& stream, size_t count) { + stream.Reserve(count); +} + +template<typename Encoding, typename Allocator> +inline void PutUnsafe(GenericStringBuffer<Encoding, Allocator>& stream, typename Encoding::Ch c) { + stream.PutUnsafe(c); +} + +//! Implement specialized version of PutN() with memset() for better performance. +template<> +inline void PutN(GenericStringBuffer<UTF8<> >& stream, char c, size_t n) { + std::memset(stream.stack_.Push<char>(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 0000000000000000000000000000000000000000..f93e508a4f40974ef6881c7d96f57365f94c1eb3 --- /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 <typename ValueType, typename Allocator=CrtAllocator> +class GenericUri { +public: + typedef typename ValueType::Ch Ch; +#if RAPIDJSON_HAS_STDSTRING + typedef std::basic_string<Ch> 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<Ch>(uri)); + } + + // Use with specializations of GenericValue + template<typename T> GenericUri(const T& uri, Allocator* allocator = 0) : uri_(), base_(), scheme_(), auth_(), path_(), query_(), frag_(), allocator_(allocator), ownAllocator_() { + const Ch* u = uri.template Get<const Ch*>(); // TypeHelper from document.h + Parse(u, internal::StrLen<Ch>(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<Ch>(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<typename T> void Get(T& uri, Allocator& allocator) { + uri.template Set<const Ch*>(this->GetString(), allocator); // TypeHelper from document.h + } + + const Ch* GetString() const { return uri_; } + SizeType GetStringLength() const { return uri_ == 0 ? 0 : internal::StrLen<Ch>(uri_); } + const Ch* GetBaseString() const { return base_; } + SizeType GetBaseStringLength() const { return base_ == 0 ? 0 : internal::StrLen<Ch>(base_); } + const Ch* GetSchemeString() const { return scheme_; } + SizeType GetSchemeStringLength() const { return scheme_ == 0 ? 0 : internal::StrLen<Ch>(scheme_); } + const Ch* GetAuthString() const { return auth_; } + SizeType GetAuthStringLength() const { return auth_ == 0 ? 0 : internal::StrLen<Ch>(auth_); } + const Ch* GetPathString() const { return path_; } + SizeType GetPathStringLength() const { return path_ == 0 ? 0 : internal::StrLen<Ch>(path_); } + const Ch* GetQueryString() const { return query_; } + SizeType GetQueryStringLength() const { return query_ == 0 ? 0 : internal::StrLen<Ch>(query_); } + const Ch* GetFragString() const { return frag_; } + SizeType GetFragStringLength() const { return frag_ == 0 ? 0 : internal::StrLen<Ch>(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<Ch>(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<Ch*>(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<Value> 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 0000000000000000000000000000000000000000..8b389219ab93225213e2329f5dac783b7bde1ebd --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/rapidjson/writer.h @@ -0,0 +1,710 @@ +// 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 <new> // placement new + +#if defined(RAPIDJSON_SIMD) && defined(_MSC_VER) +#include <intrin.h> +#pragma intrinsic(_BitScanForward) +#endif +#ifdef RAPIDJSON_SSE42 +#include <nmmintrin.h> +#elif defined(RAPIDJSON_SSE2) +#include <emmintrin.h> +#elif defined(RAPIDJSON_NEON) +#include <arm_neon.h> +#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. + 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 OutputStream, typename SourceEncoding = UTF8<>, 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<OutputStream> 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<Ch>& str) { + return String(str.data(), SizeType(str.size())); + } +#endif + + bool StartObject() { + Prefix(kObjectType); + new (level_stack_.template Push<Level>()) 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<Ch>& 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<Level>()->inArray); // currently inside an Array, not Object + RAPIDJSON_ASSERT(0 == level_stack_.template Top<Level>()->valueCount % 2); // Object has a Key without a Value + level_stack_.template Pop<Level>(1); + return EndValue(WriteEndObject()); + } + + bool StartArray() { + Prefix(kArrayType); + new (level_stack_.template Push<Level>()) Level(true); + return WriteStartArray(); + } + + bool EndArray(SizeType elementCount = 0) { + (void)elementCount; + RAPIDJSON_ASSERT(level_stack_.GetSize() >= sizeof(Level)); + RAPIDJSON_ASSERT(level_stack_.template Top<Level>()->inArray); + level_stack_.template Pop<Level>(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<size_t>(end - buffer)); + for (const char* p = buffer; p != end; ++p) + PutUnsafe(*os_, static_cast<typename OutputStream::Ch>(*p)); + return true; + } + + bool WriteUint(unsigned u) { + char buffer[10]; + const char* end = internal::u32toa(u, buffer); + PutReserve(*os_, static_cast<size_t>(end - buffer)); + for (const char* p = buffer; p != end; ++p) + PutUnsafe(*os_, static_cast<typename OutputStream::Ch>(*p)); + return true; + } + + bool WriteInt64(int64_t i64) { + char buffer[21]; + const char* end = internal::i64toa(i64, buffer); + PutReserve(*os_, static_cast<size_t>(end - buffer)); + for (const char* p = buffer; p != end; ++p) + PutUnsafe(*os_, static_cast<typename OutputStream::Ch>(*p)); + return true; + } + + bool WriteUint64(uint64_t u64) { + char buffer[20]; + char* end = internal::u64toa(u64, buffer); + PutReserve(*os_, static_cast<size_t>(end - buffer)); + for (char* p = buffer; p != end; ++p) + PutUnsafe(*os_, static_cast<typename OutputStream::Ch>(*p)); + return true; + } + + bool WriteDouble(double d) { + if (internal::Double(d).IsNanOrInf()) { + if (!(writeFlags & kWriteNanAndInfFlag)) + return false; + 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<size_t>(end - buffer)); + for (char* p = buffer; p != end; ++p) + PutUnsafe(*os_, static_cast<typename OutputStream::Ch>(*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<SourceEncoding> is(str); + while (ScanWriteUnescapedString(is, length)) { + const Ch c = is.Peek(); + if (!TargetEncoding::supportUnicode && static_cast<unsigned>(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<unsigned>(c) < 256) && RAPIDJSON_UNLIKELY(escape[static_cast<unsigned char>(c)])) { + is.Take(); + PutUnsafe(*os_, '\\'); + PutUnsafe(*os_, static_cast<typename OutputStream::Ch>(escape[static_cast<unsigned char>(c)])); + if (escape[static_cast<unsigned char>(c)] == 'u') { + PutUnsafe(*os_, '0'); + PutUnsafe(*os_, '0'); + PutUnsafe(*os_, hexDigits[static_cast<unsigned char>(c) >> 4]); + PutUnsafe(*os_, hexDigits[static_cast<unsigned char>(c) & 0xF]); + } + } + else if (RAPIDJSON_UNLIKELY(!(writeFlags & kWriteValidateEncodingFlag ? + Transcoder<SourceEncoding, TargetEncoding>::Validate(is, *os_) : + Transcoder<SourceEncoding, TargetEncoding>::TranscodeUnsafe(is, *os_)))) + return false; + } + PutUnsafe(*os_, '\"'); + return true; + } + + bool ScanWriteUnescapedString(GenericStringStream<SourceEncoding>& 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<SourceEncoding> is(json); + while (RAPIDJSON_LIKELY(is.Tell() < length)) { + RAPIDJSON_ASSERT(is.Peek() != '\0'); + if (RAPIDJSON_UNLIKELY(!(writeFlags & kWriteValidateEncodingFlag ? + Transcoder<SourceEncoding, TargetEncoding>::Validate(is, *os_) : + Transcoder<SourceEncoding, TargetEncoding>::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<Level>(); + 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<StackAllocator> 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<StringBuffer>::WriteInt(int i) { + char *buffer = os_->Push(11); + const char* end = internal::i32toa(i, buffer); + os_->Pop(static_cast<size_t>(11 - (end - buffer))); + return true; +} + +template<> +inline bool Writer<StringBuffer>::WriteUint(unsigned u) { + char *buffer = os_->Push(10); + const char* end = internal::u32toa(u, buffer); + os_->Pop(static_cast<size_t>(10 - (end - buffer))); + return true; +} + +template<> +inline bool Writer<StringBuffer>::WriteInt64(int64_t i64) { + char *buffer = os_->Push(21); + const char* end = internal::i64toa(i64, buffer); + os_->Pop(static_cast<size_t>(21 - (end - buffer))); + return true; +} + +template<> +inline bool Writer<StringBuffer>::WriteUint64(uint64_t u) { + char *buffer = os_->Push(20); + const char* end = internal::u64toa(u, buffer); + os_->Pop(static_cast<size_t>(20 - (end - buffer))); + return true; +} + +template<> +inline bool Writer<StringBuffer>::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 (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<size_t>(25 - (end - buffer))); + return true; +} + +#if defined(RAPIDJSON_SSE2) || defined(RAPIDJSON_SSE42) +template<> +inline bool Writer<StringBuffer>::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<const char*>((reinterpret_cast<size_t>(p) + 15) & static_cast<size_t>(~15)); + const char* endAligned = reinterpret_cast<const char*>(reinterpret_cast<size_t>(end) & static_cast<size_t>(~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<const __m128i *>(&dquote[0])); + const __m128i bs = _mm_loadu_si128(reinterpret_cast<const __m128i *>(&bslash[0])); + const __m128i sp = _mm_loadu_si128(reinterpret_cast<const __m128i *>(&space[0])); + + for (; p != endAligned; p += 16) { + const __m128i s = _mm_load_si128(reinterpret_cast<const __m128i *>(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<unsigned short>(_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<SizeType>(__builtin_ffs(r) - 1); +#endif + char* q = reinterpret_cast<char*>(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<StringBuffer>::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<const char*>((reinterpret_cast<size_t>(p) + 15) & static_cast<size_t>(~15)); + const char* endAligned = reinterpret_cast<const char*>(reinterpret_cast<size_t>(end) & static_cast<size_t>(~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<const uint8_t *>(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<char*>(os_->PushUnsafe(len)); + for (size_t i = 0; i < len; i++) + q[i] = p[i]; + + p += len; + break; + } + vst1q_u8(reinterpret_cast<uint8_t *>(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 0000000000000000000000000000000000000000..d6e213498e776c34655287344417877e9afcf266 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/spdlog/async.h @@ -0,0 +1,99 @@ +// 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 <spdlog/async_logger.h> +#include <spdlog/details/registry.h> +#include <spdlog/details/thread_pool.h> + +#include <memory> +#include <mutex> +#include <functional> + +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<async_overflow_policy OverflowPolicy = async_overflow_policy::block> +struct async_factory_impl +{ + template<typename Sink, typename... SinkArgs> + static std::shared_ptr<async_logger> 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<std::recursive_mutex> tp_lock(mutex); + auto tp = registry_inst.get_tp(); + if (tp == nullptr) + { + tp = std::make_shared<details::thread_pool>(details::default_async_q_size, 1U); + registry_inst.set_tp(tp); + } + + auto sink = std::make_shared<Sink>(std::forward<SinkArgs>(args)...); + auto new_logger = std::make_shared<async_logger>(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<async_overflow_policy::block>; +using async_factory_nonblock = async_factory_impl<async_overflow_policy::overrun_oldest>; + +template<typename Sink, typename... SinkArgs> +inline std::shared_ptr<spdlog::logger> create_async(std::string logger_name, SinkArgs &&... sink_args) +{ + return async_factory::create<Sink>(std::move(logger_name), std::forward<SinkArgs>(sink_args)...); +} + +template<typename Sink, typename... SinkArgs> +inline std::shared_ptr<spdlog::logger> create_async_nb(std::string logger_name, SinkArgs &&... sink_args) +{ + return async_factory_nonblock::create<Sink>(std::move(logger_name), std::forward<SinkArgs>(sink_args)...); +} + +// set global thread pool. +inline void init_thread_pool( + size_t q_size, size_t thread_count, std::function<void()> on_thread_start, std::function<void()> on_thread_stop) +{ + auto tp = std::make_shared<details::thread_pool>(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<void()> 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<spdlog::details::thread_pool> 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 0000000000000000000000000000000000000000..a1c27a59bfc90115742eacca0ad7f12151a6e548 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/spdlog/async_logger-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 <spdlog/async_logger.h> +#endif + +#include <spdlog/sinks/sink.h> +#include <spdlog/details/thread_pool.h> + +#include <memory> +#include <string> + +SPDLOG_INLINE spdlog::async_logger::async_logger( + std::string logger_name, sinks_init_list sinks_list, std::weak_ptr<details::thread_pool> 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<details::thread_pool> 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) +{ + 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"); + } +} + +// send flush request to the thread pool +SPDLOG_INLINE void spdlog::async_logger::flush_() +{ + 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"); + } +} + +// +// 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::logger> spdlog::async_logger::clone(std::string new_name) +{ + auto cloned = std::make_shared<spdlog::async_logger>(*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 0000000000000000000000000000000000000000..91a93fcbe65499a73d9b84276845db6f4d666aed --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/spdlog/async_logger.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 + +// 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 <spdlog/logger.h> + +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. +}; + +namespace details { +class thread_pool; +} + +class SPDLOG_API async_logger final : public std::enable_shared_from_this<async_logger>, public logger +{ + friend class details::thread_pool; + +public: + template<typename It> + async_logger(std::string logger_name, It begin, It end, std::weak_ptr<details::thread_pool> 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<details::thread_pool> tp, + async_overflow_policy overflow_policy = async_overflow_policy::block); + + async_logger(std::string logger_name, sink_ptr single_sink, std::weak_ptr<details::thread_pool> tp, + async_overflow_policy overflow_policy = async_overflow_policy::block); + + std::shared_ptr<logger> 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<details::thread_pool> 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 0000000000000000000000000000000000000000..36d9f1c44982bcecc1f819d2f26b59ef33081bef --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/spdlog/cfg/argv.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 +#include <spdlog/cfg/helpers.h> +#include <spdlog/details/registry.h> + +// +// 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<const char **>(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 0000000000000000000000000000000000000000..1f39ebbb2f027b944b6cfa65b47f7a237424e0ce --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/spdlog/cfg/env.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 +#include <spdlog/cfg/helpers.h> +#include <spdlog/details/registry.h> +#include <spdlog/details/os.h> + +// +// 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 0000000000000000000000000000000000000000..675a13af180ea2bb0812995eed95a041efe27c21 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/spdlog/cfg/helpers-inl.h @@ -0,0 +1,120 @@ +// 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 <spdlog/cfg/helpers.h> +#endif + +#include <spdlog/spdlog.h> +#include <spdlog/details/os.h> +#include <spdlog/details/registry.h> + +#include <algorithm> +#include <string> +#include <utility> +#include <sstream> + +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<char>((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<std::string, std::string> 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<std::string, std::string> extract_key_vals_(const std::string &str) +{ + std::string token; + std::istringstream token_stream(str); + std::unordered_map<std::string, std::string> 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<std::string, level::level_enum> 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 0000000000000000000000000000000000000000..ab7584e05d9651d588e756a4288dc0e5cf45695a --- /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 <spdlog/common.h> +#include <unordered_map> + +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 0000000000000000000000000000000000000000..9fd2bcb547bfad545927082acd31e2d96ba0b6ce --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/spdlog/common-inl.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 + +#ifndef SPDLOG_HEADER_ONLY +# include <spdlog/common.h> +#endif + +#include <algorithm> +#include <iterator> + +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<level::level_enum>(it - std::begin(level_string_views)); + + // 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 0000000000000000000000000000000000000000..3da06cadd8a6a996ecc2caabb7a1b13b230112fd --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/spdlog/common.h @@ -0,0 +1,359 @@ +// Copyright(c) 2015-present, Gabi Melman & spdlog contributors. +// Distributed under the MIT License (http://opensource.org/licenses/MIT) + +#pragma once + +#include <spdlog/tweakme.h> +#include <spdlog/details/null_mutex.h> + +#include <atomic> +#include <chrono> +#include <initializer_list> +#include <memory> +#include <exception> +#include <string> +#include <type_traits> +#include <functional> +#include <cstdio> + +#ifdef SPDLOG_USE_STD_FORMAT +# include <string_view> +#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 <spdlog/fmt/fmt.h> + +#ifndef SPDLOG_USE_STD_FORMAT +# if FMT_VERSION >= 80000 // backward compatibility with fmt versions older than 8 +# define SPDLOG_FMT_RUNTIME(format_string) fmt::runtime(format_string) +# if defined(SPDLOG_WCHAR_FILENAMES) || defined(SPDLOG_WCHAR_TO_UTF8_SUPPORT) +# include <spdlog/fmt/xchar.h> +# endif +# else +# define SPDLOG_FMT_RUNTIME(format_string) format_string +# endif +#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 +# define SPDLOG_CONSTEXPR_FUNC +#else +# define SPDLOG_NOEXCEPT noexcept +# define SPDLOG_CONSTEXPR constexpr +# if __cplusplus >= 201402L +# define SPDLOG_CONSTEXPR_FUNC constexpr +# else +# define SPDLOG_CONSTEXPR_FUNC +# 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<const char *>(__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<sinks::sink>; +using sinks_init_list = std::initializer_list<sink_ptr>; +using err_handler = std::function<void(const std::string &err_msg)>; +#ifdef SPDLOG_USE_STD_FORMAT +namespace fmt_lib = std; + +using string_view_t = std::string_view; +using memory_buf_t = std::string; + +template<typename... Args> +using format_string_t = std::string_view; + +template<class T, class Char = char> +struct is_convertible_to_basic_format_string : std::integral_constant<bool, std::is_convertible<T, std::basic_string_view<Char>>::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<typename... Args> +using wformat_string_t = std::wstring_view; +# endif + +#else // use fmt lib instead of std::format +namespace fmt_lib = fmt; + +using string_view_t = fmt::basic_string_view<char>; +using memory_buf_t = fmt::basic_memory_buffer<char, 250>; + +template<typename... Args> +using format_string_t = fmt::format_string<Args...>; + +template<class T> +using remove_cvref_t = typename std::remove_cv<typename std::remove_reference<T>::type>::type; + +// 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<Char> is only convertible to basic_format_string<Char> but not basic_string_view<Char> +template<class T, class Char = char> +struct is_convertible_to_basic_format_string + : std::integral_constant<bool, + std::is_convertible<T, fmt::basic_string_view<Char>>::value || std::is_same<remove_cvref_t<T>, fmt::basic_runtime<Char>>::value> +{}; + +# if defined(SPDLOG_WCHAR_FILENAMES) || defined(SPDLOG_WCHAR_TO_UTF8_SUPPORT) +using wstring_view_t = fmt::basic_string_view<wchar_t>; +using wmemory_buf_t = fmt::basic_memory_buffer<wchar_t, 250>; + +template<typename... Args> +using wformat_string_t = fmt::wformat_string<Args...>; +# endif +#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<class T> +struct is_convertible_to_any_format_string : std::integral_constant<bool, is_convertible_to_basic_format_string<T, char>::value || + is_convertible_to_basic_format_string<T, wchar_t>::value> +{}; + +#if defined(SPDLOG_NO_ATOMIC_LEVELS) +using level_t = details::null_atomic_int; +#else +using level_t = std::atomic<int>; +#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 +{ + std::function<void(const filename_t &filename)> before_open; + std::function<void(const filename_t &filename, std::FILE *file_stream)> after_open; + std::function<void(const filename_t &filename, std::FILE *file_stream)> before_close; + std::function<void(const filename_t &filename)> after_close; + file_event_handlers() + : before_open{nullptr} + , after_open{nullptr} + , before_close{nullptr} + , after_close{nullptr} + {} +}; + +namespace details { + +// 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<bool B, class T = void> +using enable_if_t = typename std::enable_if<B, T>::type; + +template<typename T, typename... Args> +std::unique_ptr<T> make_unique(Args &&... args) +{ + static_assert(!std::is_array<T>::value, "arrays not supported"); + return std::unique_ptr<T>(new T(std::forward<Args>(args)...)); +} +#endif + +// to avoid useless casts (see https://github.com/nlohmann/json/issues/2893#issuecomment-889152324) +template<typename T, typename U, enable_if_t<!std::is_same<T, U>::value, int> = 0> +constexpr T conditional_static_cast(U value) +{ + return static_cast<T>(value); +} + +template<typename T, typename U, enable_if_t<std::is_same<T, U>::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 0000000000000000000000000000000000000000..2621c8f7dabde4fa44858b9ab1e93517993b52ed --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/spdlog/details/backtracer-inl.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 + +#ifndef SPDLOG_HEADER_ONLY +# include <spdlog/details/backtracer.h> +#endif +namespace spdlog { +namespace details { +SPDLOG_INLINE backtracer::backtracer(const backtracer &other) +{ + std::lock_guard<std::mutex> lock(other.mutex_); + enabled_ = other.enabled(); + messages_ = other.messages_; +} + +SPDLOG_INLINE backtracer::backtracer(backtracer &&other) SPDLOG_NOEXCEPT +{ + std::lock_guard<std::mutex> lock(other.mutex_); + enabled_ = other.enabled(); + messages_ = std::move(other.messages_); +} + +SPDLOG_INLINE backtracer &backtracer::operator=(backtracer other) +{ + std::lock_guard<std::mutex> lock(mutex_); + enabled_ = other.enabled(); + messages_ = std::move(other.messages_); + return *this; +} + +SPDLOG_INLINE void backtracer::enable(size_t size) +{ + std::lock_guard<std::mutex> lock{mutex_}; + enabled_.store(true, std::memory_order_relaxed); + messages_ = circular_q<log_msg_buffer>{size}; +} + +SPDLOG_INLINE void backtracer::disable() +{ + std::lock_guard<std::mutex> 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<std::mutex> lock{mutex_}; + messages_.push_back(log_msg_buffer{msg}); +} + +// pop all items in the q and apply the given fun on each of them. +SPDLOG_INLINE void backtracer::foreach_pop(std::function<void(const details::log_msg &)> fun) +{ + std::lock_guard<std::mutex> 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 0000000000000000000000000000000000000000..b336ee776cd09e34ca657cfa512e9f20a10ba6cb --- /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 <spdlog/details/log_msg_buffer.h> +#include <spdlog/details/circular_q.h> + +#include <atomic> +#include <mutex> +#include <functional> + +// 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<bool> enabled_{false}; + circular_q<log_msg_buffer> 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); + + // pop all items in the q and apply the given fun on each of them. + void foreach_pop(std::function<void(const details::log_msg &)> 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 0000000000000000000000000000000000000000..1f2712e7ed8fbc2e3497b6f91eeae7167698c725 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/spdlog/details/circular_q.h @@ -0,0 +1,141 @@ +// 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 <vector> +#include <cassert> + +namespace spdlog { +namespace details { +template<typename T> +class circular_q +{ + size_t max_items_ = 0; + typename std::vector<T>::size_type head_ = 0; + typename std::vector<T>::size_type tail_ = 0; + size_t overrun_counter_ = 0; + std::vector<T> 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_; + } + +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 0000000000000000000000000000000000000000..665201dd22842e5dfab5a15547f42c624b219f81 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/spdlog/details/console_globals.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 <spdlog/details/null_mutex.h> +#include <mutex> + +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 0000000000000000000000000000000000000000..d4528711ee7a9a522c0cef4cb08626c22e81a5c8 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/spdlog/details/file_helper-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 <spdlog/details/file_helper.h> +#endif + +#include <spdlog/details/os.h> +#include <spdlog/common.h> + +#include <cerrno> +#include <chrono> +#include <cstdio> +#include <string> +#include <thread> +#include <tuple> + +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::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) +{ + 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<filename_t, filename_t> 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 0000000000000000000000000000000000000000..0f5988b9ed2c1d2bdf82302084826259c4cd4c62 --- /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 <spdlog/common.h> +#include <tuple> + +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 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<filename_t, filename_t> 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 0000000000000000000000000000000000000000..1a60bc0dc205cca5596e95a6f3d06f0798f82e2e --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/spdlog/details/fmt_helper.h @@ -0,0 +1,169 @@ +// Copyright(c) 2015-present, Gabi Melman & spdlog contributors. +// Distributed under the MIT License (http://opensource.org/licenses/MIT) +#pragma once + +#include <chrono> +#include <type_traits> +#include <iterator> +#include <spdlog/fmt/fmt.h> +#include <spdlog/common.h> + +#ifdef SPDLOG_USE_STD_FORMAT +# include <charconv> +# include <limits> +#endif + +// Some fmt helpers to efficiently format and pad ints and strings +namespace spdlog { +namespace details { +namespace fmt_helper { + +inline spdlog::string_view_t to_string_view(const memory_buf_t &buf) SPDLOG_NOEXCEPT +{ + return spdlog::string_view_t{buf.data(), buf.size()}; +} + +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<typename T> +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<T>::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<int>(ec)); + } +} +#else +template<typename T> +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<typename T> +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<typename T> +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<count_type>(n)); +#else + return static_cast<unsigned int>(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<count_type>(n))); +#endif +} + +inline void pad2(int n, memory_buf_t &dest) +{ + if (n >= 0 && n < 100) // 0-99 + { + dest.push_back(static_cast<char>('0' + n / 10)); + dest.push_back(static_cast<char>('0' + n % 10)); + } + else // unlikely, but just in case, let fmt deal with it + { + fmt_lib::format_to(std::back_inserter(dest), "{:02}", n); + } +} + +template<typename T> +inline void pad_uint(T n, unsigned int width, memory_buf_t &dest) +{ + static_assert(std::is_unsigned<T>::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<typename T> +inline void pad3(T n, memory_buf_t &dest) +{ + static_assert(std::is_unsigned<T>::value, "pad3 must get unsigned T"); + if (n < 1000) + { + dest.push_back(static_cast<char>(n / 100 + '0')); + n = n % 100; + dest.push_back(static_cast<char>((n / 10) + '0')); + dest.push_back(static_cast<char>((n % 10) + '0')); + } + else + { + append_int(n, dest); + } +} + +template<typename T> +inline void pad6(T n, memory_buf_t &dest) +{ + pad_uint(n, 6, dest); +} + +template<typename T> +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<std::milliseconds>(tp) -> will return the millis part of the second +template<typename ToDuration> +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<seconds>(duration); + return duration_cast<ToDuration>(duration) - duration_cast<ToDuration>(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 0000000000000000000000000000000000000000..c6e8a7e04fa426ef6f975f53f6b5dedb18a4a7e7 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/spdlog/details/log_msg-inl.h @@ -0,0 +1,37 @@ +// 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 <spdlog/details/log_msg.h> +#endif + +#include <spdlog/details/os.h> + +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 0000000000000000000000000000000000000000..fed51abdf617c92fcb96440c632847e0fe185d23 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/spdlog/details/log_msg.h @@ -0,0 +1,37 @@ +// Copyright(c) 2015-present, Gabi Melman & spdlog contributors. +// Distributed under the MIT License (http://opensource.org/licenses/MIT) + +#pragma once + +#include <spdlog/common.h> +#include <string> + +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 0000000000000000000000000000000000000000..84d83dc2febb6d9f2e8a047a486e9d12447864dc --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/spdlog/details/log_msg_buffer-inl.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 + +#ifndef SPDLOG_HEADER_ONLY +# include <spdlog/details/log_msg_buffer.h> +#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 0000000000000000000000000000000000000000..8105506563e498fbdbce58cd9a6ded5dcdc3ed4d --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/spdlog/details/log_msg_buffer.h @@ -0,0 +1,33 @@ +// Copyright(c) 2015-present, Gabi Melman & spdlog contributors. +// Distributed under the MIT License (http://opensource.org/licenses/MIT) + +#pragma once + +#include <spdlog/details/log_msg.h> + +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 0000000000000000000000000000000000000000..b70483e5cd9c528f90bcebab7873a80deded32b5 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/spdlog/details/mpmc_blocking_q.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 + +// 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 <spdlog/details/circular_q.h> + +#include <condition_variable> +#include <mutex> + +namespace spdlog { +namespace details { + +template<typename T> +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<std::mutex> 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<std::mutex> lock(queue_mutex_); + q_.push_back(std::move(item)); + } + push_cv_.notify_one(); + } + + // try to dequeue item. if no item found. wait up to timeout and try again + // Return true, if succeeded dequeue item, false otherwise + bool dequeue_for(T &popped_item, std::chrono::milliseconds wait_duration) + { + { + std::unique_lock<std::mutex> 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; + } + +#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<std::mutex> 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<std::mutex> lock(queue_mutex_); + q_.push_back(std::move(item)); + push_cv_.notify_one(); + } + + // try to dequeue item. if no item found. wait up to timeout and try again + // Return true, if succeeded dequeue item, false otherwise + bool dequeue_for(T &popped_item, std::chrono::milliseconds wait_duration) + { + std::unique_lock<std::mutex> 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; + } + +#endif + + size_t overrun_counter() + { + std::unique_lock<std::mutex> lock(queue_mutex_); + return q_.overrun_counter(); + } + + size_t size() + { + std::unique_lock<std::mutex> lock(queue_mutex_); + return q_.size(); + } + +private: + std::mutex queue_mutex_; + std::condition_variable push_cv_; + std::condition_variable pop_cv_; + spdlog::details::circular_q<T> q_; +}; +} // 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 0000000000000000000000000000000000000000..83533d4fe25be1ba7ff4068f2f82bee60dad97fb --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/spdlog/details/null_mutex.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 + +#include <atomic> +#include <utility> +// null, no cost dummy "mutex" and dummy "atomic" int + +namespace spdlog { +namespace details { +struct null_mutex +{ + void lock() const {} + void unlock() const {} + bool try_lock() const + { + return true; + } +}; + +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 0000000000000000000000000000000000000000..c3bf691ca2e55102546776b4fd37bd6b63ed212f --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/spdlog/details/os-inl.h @@ -0,0 +1,610 @@ +// 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 <spdlog/details/os.h> +#endif + +#include <spdlog/common.h> + +#include <algorithm> +#include <chrono> +#include <cstdio> +#include <cstdlib> +#include <cstring> +#include <ctime> +#include <string> +#include <thread> +#include <array> +#include <sys/stat.h> +#include <sys/types.h> + +#ifdef _WIN32 + +# include <io.h> // _get_osfhandle and _isatty support +# include <process.h> // _get_pid support +# include <spdlog/details/windows_include.h> + +# ifdef __MINGW32__ +# include <share.h> +# endif + +# if defined(SPDLOG_WCHAR_TO_UTF8_SUPPORT) || defined(SPDLOG_WCHAR_FILENAMES) +# include <limits> +# endif + +# include <direct.h> // for _mkdir/_wmkdir + +#else // unix + +# include <fcntl.h> +# include <unistd.h> + +# ifdef __linux__ +# include <sys/syscall.h> //Use gettid() syscall under linux to get thread id + +# elif defined(_AIX) +# include <pthread.h> // for pthread_getthrds_np + +# elif defined(__DragonFly__) || defined(__FreeBSD__) +# include <pthread_np.h> // for pthread_getthreadid_np + +# elif defined(__NetBSD__) +# include <lwp.h> // for _lwp_self + +# elif defined(__sun) +# include <thread.h> // for thr_self +# endif + +#endif // unix + +#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<log_clock, typename log_clock::duration>( + std::chrono::duration_cast<typename log_clock::duration>(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<HANDLE>(_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 +# ifdef SPDLOG_WCHAR_FILENAMES + auto attribs = ::GetFileAttributesW(filename.c_str()); +# else + auto attribs = ::GetFileAttributesA(filename.c_str()); +# endif + return attribs != INVALID_FILE_ATTRIBUTES; +#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<size_t>(ret); + } + +# else // windows 32 bits + long ret = ::_filelength(fd); + if (ret >= 0) + { + return static_cast<size_t>(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 or cygwin, where fstat64 is deprecated) +# if (defined(__linux__) || defined(__sun) || defined(_AIX)) && (defined(__LP64__) || defined(_LP64)) + struct stat64 st; + if (::fstat64(fd, &st) == 0) + { + return static_cast<size_t>(st.st_size); + } +# else // other unix or linux 32 bits or cygwin + struct stat st; + if (::fstat(fd, &st) == 0) + { + return static_cast<size_t>(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(_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<long int>(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<int>(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<size_t>(::GetCurrentThreadId()); +#elif defined(__linux__) +# if defined(__ANDROID__) && defined(__ANDROID_API__) && (__ANDROID_API__ < 21) +# define SYS_gettid __NR_gettid +# endif + return static_cast<size_t>(::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<size_t>(tid); +#elif defined(__DragonFly__) || defined(__FreeBSD__) + return static_cast<size_t>(::pthread_getthreadid_np()); +#elif defined(__NetBSD__) + return static_cast<size_t>(::_lwp_self()); +#elif defined(__OpenBSD__) + return static_cast<size_t>(::getthrid()); +#elif defined(__sun) + return static_cast<size_t>(::thr_self()); +#elif __APPLE__ + uint64_t tid; + pthread_threadid_np(nullptr, &tid); + return static_cast<size_t>(tid); +#else // Default to standard C++11 (other Unix) + return static_cast<size_t>(std::hash<std::thread::id>()(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); +# ifdef SPDLOG_USE_STD_FORMAT + return buf; +# else + return fmt::to_string(buf); +# endif +} +#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<int>(::GetCurrentProcessId()); +#else + return conditional_static_cast<int>(::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<const char *, 16> 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<size_t>((std::numeric_limits<int>::max)()) / 2 - 1) + { + throw_spdlog_ex("UTF-16 string is too big to be converted to UTF-8"); + } + + int wstr_size = static_cast<int>(wstr.size()); + if (wstr_size == 0) + { + target.resize(0); + return; + } + + int result_size = static_cast<int>(target.capacity()); + if ((wstr_size + 1) * 2 > 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<size_t>((std::numeric_limits<int>::max)()) - 1) + { + throw_spdlog_ex("UTF-8 string is too big to be converted to UTF-16"); + } + + int str_size = static_cast<int>(str.size()); + if (str_size == 0) + { + target.resize(0); + return; + } + + int result_size = static_cast<int>(target.capacity()); + if (str_size + 1 > result_size) + { + result_size = ::MultiByteToWideChar(CP_UTF8, MB_ERR_INVALID_CHARS, str.data(), str_size, NULL, 0); + } + + if (result_size > 0) + { + target.resize(result_size); + result_size = ::MultiByteToWideChar(CP_UTF8, MB_ERR_INVALID_CHARS, str.data(), str_size, target.data(), result_size); + + if (result_size > 0) + { + target.resize(result_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); + + 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 +} + +} // 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 0000000000000000000000000000000000000000..b154bc4737e941146b8d2f0722955ad76aa3d2ce --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/spdlog/details/os.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 <spdlog/common.h> +#include <ctime> // std::time_t + +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); + +} // 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 0000000000000000000000000000000000000000..d4abbda314f608da91ca31e1b15e10574dc88230 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/spdlog/details/periodic_worker-inl.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 + +#ifndef SPDLOG_HEADER_ONLY +# include <spdlog/details/periodic_worker.h> +#endif + +namespace spdlog { +namespace details { + +SPDLOG_INLINE periodic_worker::periodic_worker(const std::function<void()> &callback_fun, std::chrono::seconds interval) +{ + active_ = (interval > std::chrono::seconds::zero()); + if (!active_) + { + return; + } + + worker_thread_ = std::thread([this, callback_fun, interval]() { + for (;;) + { + std::unique_lock<std::mutex> lock(this->mutex_); + if (this->cv_.wait_for(lock, interval, [this] { return !this->active_; })) + { + return; // active_ == false, so exit this thread + } + callback_fun(); + } + }); +} + +// stop the worker thread and join it +SPDLOG_INLINE periodic_worker::~periodic_worker() +{ + if (worker_thread_.joinable()) + { + { + std::lock_guard<std::mutex> 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 0000000000000000000000000000000000000000..a300218d6ff68e18eef25b58d926106e66c575ad --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/spdlog/details/periodic_worker.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 + +// 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 <chrono> +#include <condition_variable> +#include <functional> +#include <mutex> +#include <thread> +namespace spdlog { +namespace details { + +class SPDLOG_API periodic_worker +{ +public: + periodic_worker(const std::function<void()> &callback_fun, std::chrono::seconds interval); + 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 0000000000000000000000000000000000000000..c55b5eea8c66aa4b13152175b1bb24bc59ab5d32 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/spdlog/details/registry-inl.h @@ -0,0 +1,313 @@ +// 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 <spdlog/details/registry.h> +#endif + +#include <spdlog/common.h> +#include <spdlog/details/periodic_worker.h> +#include <spdlog/logger.h> +#include <spdlog/pattern_formatter.h> + +#ifndef SPDLOG_DISABLE_DEFAULT_LOGGER +// support for the default stdout color logger +# ifdef _WIN32 +# include <spdlog/sinks/wincolor_sink.h> +# else +# include <spdlog/sinks/ansicolor_sink.h> +# endif +#endif // SPDLOG_DISABLE_DEFAULT_LOGGER + +#include <chrono> +#include <functional> +#include <memory> +#include <string> +#include <unordered_map> + +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<sinks::wincolor_stdout_sink_mt>(); +# else + auto color_sink = std::make_shared<sinks::ansicolor_stdout_sink_mt>(); +# endif + + const char *default_logger_name = ""; + default_logger_ = std::make_shared<spdlog::logger>(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<logger> new_logger) +{ + std::lock_guard<std::mutex> lock(logger_map_mutex_); + register_logger_(std::move(new_logger)); +} + +SPDLOG_INLINE void registry::initialize_logger(std::shared_ptr<logger> new_logger) +{ + std::lock_guard<std::mutex> 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<logger> registry::get(const std::string &logger_name) +{ + std::lock_guard<std::mutex> lock(logger_map_mutex_); + auto found = loggers_.find(logger_name); + return found == loggers_.end() ? nullptr : found->second; +} + +SPDLOG_INLINE std::shared_ptr<logger> registry::default_logger() +{ + std::lock_guard<std::mutex> 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<logger> new_default_logger) +{ + std::lock_guard<std::mutex> lock(logger_map_mutex_); + // remove previous default logger from the map + if (default_logger_ != nullptr) + { + loggers_.erase(default_logger_->name()); + } + 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<thread_pool> tp) +{ + std::lock_guard<std::recursive_mutex> lock(tp_mutex_); + tp_ = std::move(tp); +} + +SPDLOG_INLINE std::shared_ptr<thread_pool> registry::get_tp() +{ + std::lock_guard<std::recursive_mutex> 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> formatter) +{ + std::lock_guard<std::mutex> 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<std::mutex> 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<std::mutex> 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<std::mutex> 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<std::mutex> lock(logger_map_mutex_); + for (auto &l : loggers_) + { + l.second->flush_on(log_level); + } + flush_level_ = log_level; +} + +SPDLOG_INLINE void registry::flush_every(std::chrono::seconds interval) +{ + std::lock_guard<std::mutex> lock(flusher_mutex_); + auto clbk = [this]() { this->flush_all(); }; + periodic_flusher_ = details::make_unique<periodic_worker>(clbk, interval); +} + +SPDLOG_INLINE void registry::set_error_handler(err_handler handler) +{ + std::lock_guard<std::mutex> 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<void(const std::shared_ptr<logger>)> &fun) +{ + std::lock_guard<std::mutex> lock(logger_map_mutex_); + for (auto &l : loggers_) + { + fun(l.second); + } +} + +SPDLOG_INLINE void registry::flush_all() +{ + std::lock_guard<std::mutex> lock(logger_map_mutex_); + for (auto &l : loggers_) + { + l.second->flush(); + } +} + +SPDLOG_INLINE void registry::drop(const std::string &logger_name) +{ + std::lock_guard<std::mutex> lock(logger_map_mutex_); + loggers_.erase(logger_name); + if (default_logger_ && default_logger_->name() == logger_name) + { + default_logger_.reset(); + } +} + +SPDLOG_INLINE void registry::drop_all() +{ + std::lock_guard<std::mutex> 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<std::mutex> lock(flusher_mutex_); + periodic_flusher_.reset(); + } + + drop_all(); + + { + std::lock_guard<std::recursive_mutex> 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<std::mutex> 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<std::mutex> 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::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<logger> 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 0000000000000000000000000000000000000000..97473ea33c9c80252e92d871afe4977eb007628b --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/spdlog/details/registry.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 + +// 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 <spdlog/common.h> + +#include <chrono> +#include <functional> +#include <memory> +#include <string> +#include <unordered_map> +#include <mutex> + +namespace spdlog { +class logger; + +namespace details { +class thread_pool; +class periodic_worker; + +class SPDLOG_API registry +{ +public: + using log_levels = std::unordered_map<std::string, level::level_enum>; + registry(const registry &) = delete; + registry &operator=(const registry &) = delete; + + void register_logger(std::shared_ptr<logger> new_logger); + void initialize_logger(std::shared_ptr<logger> new_logger); + std::shared_ptr<logger> get(const std::string &logger_name); + std::shared_ptr<logger> 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. + // default logger is stored in default_logger_ (for faster retrieval) and in the loggers_ map. + void set_default_logger(std::shared_ptr<logger> new_default_logger); + + void set_tp(std::shared_ptr<thread_pool> tp); + + std::shared_ptr<thread_pool> get_tp(); + + // Set global formatter. Each sink in each logger will get a clone of this object + void set_formatter(std::unique_ptr<formatter> 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); + + void flush_every(std::chrono::seconds interval); + + void set_error_handler(err_handler handler); + + void apply_all(const std::function<void(const std::shared_ptr<logger>)> &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(); + +private: + registry(); + ~registry(); + + void throw_if_exists_(const std::string &logger_name); + void register_logger_(std::shared_ptr<logger> new_logger); + bool set_level_from_cfg_(logger *logger); + std::mutex logger_map_mutex_, flusher_mutex_; + std::recursive_mutex tp_mutex_; + std::unordered_map<std::string, std::shared_ptr<logger>> loggers_; + log_levels log_levels_; + std::unique_ptr<formatter> formatter_; + spdlog::level::level_enum global_log_level_ = level::info; + level::level_enum flush_level_ = level::off; + err_handler err_handler_; + std::shared_ptr<thread_pool> tp_; + std::unique_ptr<periodic_worker> periodic_flusher_; + std::shared_ptr<logger> 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 0000000000000000000000000000000000000000..1f729ab936b40dd9b551a2638dc5b23bf5b613ec --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/spdlog/details/synchronous_factory.h @@ -0,0 +1,24 @@ +// 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<typename Sink, typename... SinkArgs> + static std::shared_ptr<spdlog::logger> create(std::string logger_name, SinkArgs &&... args) + { + auto sink = std::make_shared<Sink>(std::forward<SinkArgs>(args)...); + auto new_logger = std::make_shared<spdlog::logger>(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 0000000000000000000000000000000000000000..9d3647aaabf5a960eb0cacd0bd21abb00dd029da --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/spdlog/details/tcp_client-windows.h @@ -0,0 +1,160 @@ +// 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 <spdlog/common.h> +#include <spdlog/details/os.h> + +#include <winsock2.h> +#include <windows.h> +#include <ws2tcpip.h> +#include <stdlib.h> +#include <stdio.h> +#include <string> + +#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_INET; // IPv4 + 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<char *>(&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<size_t>(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 0000000000000000000000000000000000000000..0daff0eb4333b19c70023f205a7561d8e83bfd08 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/spdlog/details/tcp_client.h @@ -0,0 +1,145 @@ +// 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 <spdlog/common.h> +#include <spdlog/details/os.h> + +#include <sys/socket.h> +#include <arpa/inet.h> +#include <unistd.h> +#include <netdb.h> +#include <netinet/tcp.h> + +#include <string> + +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_INET; // IPv4 + 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<char *>(&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<char *>(&enable_flag), sizeof(enable_flag)); +#endif + +#if !defined(SO_NOSIGPIPE) && !defined(MSG_NOSIGNAL) +# error "tcp_sink would raise SIGPIPE since niether 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<size_t>(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 0000000000000000000000000000000000000000..e4b3e1c49f394747e839f4981510342d274d6b7c --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/spdlog/details/thread_pool-inl.h @@ -0,0 +1,136 @@ +// 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 <spdlog/details/thread_pool.h> +#endif + +#include <spdlog/common.h> +#include <cassert> + +namespace spdlog { +namespace details { + +SPDLOG_INLINE thread_pool::thread_pool( + size_t q_max_items, size_t threads_n, std::function<void()> on_thread_start, std::function<void()> 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<void()> 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(); +} + +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 + { + q_.enqueue_nowait(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; + bool dequeued = q_.dequeue_for(incoming_async_msg, std::chrono::seconds(10)); + if (!dequeued) + { + return true; + } + + 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 0000000000000000000000000000000000000000..63738b5b6211c473b9cebd36bc9388bc5a17ba23 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/spdlog/details/thread_pool.h @@ -0,0 +1,121 @@ +// Copyright(c) 2015-present, Gabi Melman & spdlog contributors. +// Distributed under the MIT License (http://opensource.org/licenses/MIT) + +#pragma once + +#include <spdlog/details/log_msg_buffer.h> +#include <spdlog/details/mpmc_blocking_q.h> +#include <spdlog/details/os.h> + +#include <chrono> +#include <memory> +#include <thread> +#include <vector> +#include <functional> + +namespace spdlog { +class async_logger; + +namespace details { + +using async_logger_ptr = std::shared_ptr<spdlog::async_logger>; + +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<log_msg_buffer *>(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<item_type>; + + thread_pool(size_t q_max_items, size_t threads_n, std::function<void()> on_thread_start, std::function<void()> on_thread_stop); + thread_pool(size_t q_max_items, size_t threads_n, std::function<void()> 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(); + size_t queue_size(); + +private: + q_type q_; + + std::vector<std::thread> 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 0000000000000000000000000000000000000000..8e763356dc79ee430eaac708f14d2826fe4ef3fa --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/spdlog/details/udp_client-windows.h @@ -0,0 +1,111 @@ +// 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 <spdlog/common.h> +#include <spdlog/details/os.h> +#include <spdlog/details/windows_include.h> +#include <winsock2.h> +#include <ws2tcpip.h> +#include <stdlib.h> +#include <stdio.h> +#include <string> + +#pragma comment(lib, "Ws2_32.lib") +#pragma comment(lib, "Mswsock.lib") +#pragma comment(lib, "AdvApi32.lib") + +namespace spdlog { +namespace details { +class udp_client +{ + static constexpr int TX_BUFFER_SIZE = 1024 * 10; + SOCKET socket_ = INVALID_SOCKET; + sockaddr_in addr_ = {0}; + + 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<const char *>(&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<int>(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 0000000000000000000000000000000000000000..2db5b89e7341656a7d25a59efa8264faa6e400aa --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/spdlog/details/udp_client.h @@ -0,0 +1,94 @@ +// 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 <spdlog/common.h> +#include <spdlog/details/os.h> + +#include <sys/socket.h> +#include <netinet/in.h> +#include <arpa/inet.h> +#include <unistd.h> +#include <netdb.h> +#include <netinet/udp.h> + +#include <string> + +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<const char *>(&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 0000000000000000000000000000000000000000..a92390b9a55b64a846583fcecf43e75efc862f0c --- /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 <windows.h> 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 0000000000000000000000000000000000000000..93e5c28b5c231c311cfc9ecaf2e70333e772dbd3 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/spdlog/fmt/bin_to_hex.h @@ -0,0 +1,246 @@ +// +// Copyright(c) 2015 Gabi Melman. +// Distributed under the MIT License (http://opensource.org/licenses/MIT) +// + +#pragma once + +#include <cctype> +#include <spdlog/common.h> + +#if defined(__has_include) && __has_include(<version>) +# include <version> +#endif + +#if __cpp_lib_span >= 202002L +# include <span> +#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<char> 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<typename It> +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<typename Container> +inline details::dump_info<typename Container::const_iterator> 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<Iter>(std::begin(container), std::end(container), size_per_line); +} + +#if __cpp_lib_span >= 202002L + +template<typename Value, size_t Extent> +inline details::dump_info<typename std::span<Value, Extent>::iterator> to_hex( + const std::span<Value, Extent> &container, size_t size_per_line = 32) +{ + using Container = std::span<Value, Extent>; + static_assert(sizeof(typename Container::value_type) == 1, "sizeof(Container::value_type) != 1"); + using Iter = typename Container::iterator; + return details::dump_info<Iter>(std::begin(container), std::end(container), size_per_line); +} + +#endif + +// create dump_info from ranges +template<typename It> +inline details::dump_info<It> to_hex(const It range_begin, const It range_end, size_t size_per_line = 32) +{ + return details::dump_info<It>(range_begin, range_end, size_per_line); +} + +} // namespace spdlog + +namespace +#ifdef SPDLOG_USE_STD_FORMAT + std +#else + fmt +#endif +{ + +template<typename T> +struct formatter<spdlog::details::dump_info<T>, 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<typename ParseContext> + 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<typename FormatContext, typename Container> + auto format(const spdlog::details::dump_info<Container> &the_range, FormatContext &ctx) -> 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<int>(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<unsigned char>(*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<unsigned char>(*j); + *inserter++ = std::isprint(pc) ? static_cast<char>(*j) : '.'; + } + } + + put_newline(inserter, static_cast<size_t>(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) + { + *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<unsigned char>(*j); + *inserter++ = std::isprint(pc) ? static_cast<char>(*j) : '.'; + } + } + return inserter; + } + + // put newline(and position header) + template<typename It> + void put_newline(It inserter, std::size_t pos) + { +#ifdef _WIN32 + *inserter++ = '\r'; +#endif + *inserter++ = '\n'; + + if (put_positions) + { + spdlog::fmt_lib::format_to(inserter, "{:04X}: ", pos); + } + } +}; +} // namespace std diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/spdlog/fmt/bundled/args.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/spdlog/fmt/bundled/args.h new file mode 100644 index 0000000000000000000000000000000000000000..9a8e4ed2cebb84c65b32633fcf82eb7cc6f92990 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/spdlog/fmt/bundled/args.h @@ -0,0 +1,234 @@ +// Formatting library for C++ - dynamic format arguments +// +// 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_ + +#include <functional> // std::reference_wrapper +#include <memory> // std::unique_ptr +#include <vector> + +#include "core.h" + +FMT_BEGIN_NAMESPACE + +namespace detail { + +template <typename T> struct is_reference_wrapper : std::false_type {}; +template <typename T> +struct is_reference_wrapper<std::reference_wrapper<T>> : std::true_type {}; + +template <typename T> const T& unwrap(const T& v) { return v; } +template <typename T> const T& unwrap(const std::reference_wrapper<T>& v) { + return static_cast<const T&>(v); +} + +class dynamic_arg_list { + // 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 storage_node_base is made a fake template. + template <typename = void> struct node { + virtual ~node() = default; + std::unique_ptr<node<>> next; + }; + + template <typename T> struct typed_node : node<> { + T value; + + template <typename Arg> + FMT_CONSTEXPR typed_node(const Arg& arg) : value(arg) {} + + template <typename Char> + FMT_CONSTEXPR typed_node(const basic_string_view<Char>& arg) + : value(arg.data(), arg.size()) {} + }; + + std::unique_ptr<node<>> head_; + + public: + template <typename T, typename Arg> const T& push(const Arg& arg) { + auto new_node = std::unique_ptr<typed_node<T>>(new typed_node<T>(arg)); + auto& value = new_node->value; + new_node->next = std::move(head_); + head_ = std::move(new_node); + return value; + } +}; +} // namespace detail + +/** + \rst + A dynamic version of `fmt::format_arg_store`. + It's equipped with a storage to potentially temporary objects which lifetimes + could be shorter than the format arguments object. + + It can be implicitly converted into `~fmt::basic_format_args` for passing + into type-erased formatting functions such as `~fmt::vformat`. + \endrst + */ +template <typename Context> +class dynamic_format_arg_store +#if FMT_GCC_VERSION && FMT_GCC_VERSION < 409 + // Workaround a GCC template argument substitution bug. + : public basic_format_args<Context> +#endif +{ + private: + using char_type = typename Context::char_type; + + template <typename T> struct need_copy { + static constexpr detail::type mapped_type = + detail::mapped_type_constant<T, Context>::value; + + enum { + value = !(detail::is_reference_wrapper<T>::value || + std::is_same<T, basic_string_view<char_type>>::value || + std::is_same<T, detail::std_string_view<char_type>>::value || + (mapped_type != detail::type::cstring_type && + mapped_type != detail::type::string_type && + mapped_type != detail::type::custom_type)) + }; + }; + + template <typename T> + using stored_type = conditional_t<detail::is_string<T>::value && + !has_formatter<T, Context>::value && + !detail::is_reference_wrapper<T>::value, + std::basic_string<char_type>, T>; + + // Storage of basic_format_arg must be contiguous. + std::vector<basic_format_arg<Context>> data_; + std::vector<detail::named_arg_info<char_type>> 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<Context>; + + unsigned long long get_types() const { + return detail::is_unpacked_bit | data_.size() | + (named_info_.empty() + ? 0ULL + : static_cast<unsigned long long>(detail::has_named_args_bit)); + } + + const basic_format_arg<Context>* data() const { + return named_info_.empty() ? data_.data() : data_.data() + 1; + } + + template <typename T> void emplace_arg(const T& arg) { + data_.emplace_back(detail::make_arg<Context>(arg)); + } + + template <typename T> + void emplace_arg(const detail::named_arg<char_type, T>& arg) { + if (named_info_.empty()) { + constexpr const detail::named_arg_info<char_type>* zero_ptr{nullptr}; + data_.insert(data_.begin(), {zero_ptr, 0}); + } + data_.emplace_back(detail::make_arg<Context>(detail::unwrap(arg.value))); + auto pop_one = [](std::vector<basic_format_arg<Context>>* data) { + data->pop_back(); + }; + std::unique_ptr<std::vector<basic_format_arg<Context>>, decltype(pop_one)> + guard{&data_, pop_one}; + named_info_.push_back({arg.name, static_cast<int>(data_.size() - 2u)}); + data_[0].value_.named_args = {named_info_.data(), named_info_.size()}; + guard.release(); + } + + public: + constexpr dynamic_format_arg_store() = default; + + /** + \rst + 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<fmt::format_context> store; + store.push_back(42); + store.push_back("abc"); + store.push_back(1.5f); + std::string result = fmt::vformat("{} and {} and {}", store); + \endrst + */ + template <typename T> void push_back(const T& arg) { + if (detail::const_check(need_copy<T>::value)) + emplace_arg(dynamic_args_.push<stored_type<T>>(arg)); + else + emplace_arg(detail::unwrap(arg)); + } + + /** + \rst + Adds a reference to the argument into the dynamic store for later passing to + a formatting function. + + **Example**:: + + fmt::dynamic_format_arg_store<fmt::format_context> 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" + \endrst + */ + template <typename T> void push_back(std::reference_wrapper<T> arg) { + static_assert( + need_copy<T>::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 <typename T> + void push_back(const detail::named_arg<char_type, T>& arg) { + const char_type* arg_name = + dynamic_args_.push<std::basic_string<char_type>>(arg.name).c_str(); + if (detail::const_check(need_copy<T>::value)) { + emplace_arg( + fmt::arg(arg_name, dynamic_args_.push<stored_type<T>>(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(); + } + + /** + \rst + Reserves space to store at least *new_cap* arguments including + *new_cap_named* named arguments. + \endrst + */ + 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/spdlog/fmt/bundled/chrono.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/spdlog/fmt/bundled/chrono.h new file mode 100644 index 0000000000000000000000000000000000000000..682efd8d21b1464dd40a641ba8096f8f2c915197 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/spdlog/fmt/bundled/chrono.h @@ -0,0 +1,2067 @@ +// 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_ + +#include <algorithm> +#include <chrono> +#include <ctime> +#include <iterator> +#include <locale> +#include <ostream> +#include <type_traits> + +#include "format.h" + +FMT_BEGIN_NAMESPACE + +// Enable tzset. +#ifndef FMT_USE_TZSET +// UWP doesn't provide _tzset. +# if FMT_HAS_INCLUDE("winapifamily.h") +# include <winapifamily.h> +# 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 <typename To, typename From, + FMT_ENABLE_IF(!std::is_same<From, To>::value && + std::numeric_limits<From>::is_signed == + std::numeric_limits<To>::is_signed)> +FMT_CONSTEXPR To lossless_integral_conversion(const From from, int& ec) { + ec = 0; + using F = std::numeric_limits<From>; + using T = std::numeric_limits<To>; + 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<To>(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 <typename To, typename From, + FMT_ENABLE_IF(!std::is_same<From, To>::value && + std::numeric_limits<From>::is_signed != + std::numeric_limits<To>::is_signed)> +FMT_CONSTEXPR To lossless_integral_conversion(const From from, int& ec) { + ec = 0; + using F = std::numeric_limits<From>; + using T = std::numeric_limits<To>; + 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<From>(detail::max_value<To>())) { + ec = 1; + return {}; + } + } + + if (detail::const_check(!F::is_signed && T::is_signed && + F::digits >= T::digits) && + from > static_cast<From>(detail::max_value<To>())) { + ec = 1; + return {}; + } + return static_cast<To>(from); // Lossless conversion. +} + +template <typename To, typename From, + FMT_ENABLE_IF(std::is_same<From, To>::value)> +FMT_CONSTEXPR To lossless_integral_conversion(const From from, int& ec) { + 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 <typename To, typename From, + FMT_ENABLE_IF(!std::is_same<From, To>::value)> +FMT_CONSTEXPR To safe_float_conversion(const From from, int& ec) { + ec = 0; + using T = std::numeric_limits<To>; + static_assert(std::is_floating_point<From>::value, "From must be floating"); + static_assert(std::is_floating_point<To>::value, "To must be floating"); + + // catch the only happy case + if (std::isfinite(from)) { + if (from >= T::lowest() && from <= (T::max)()) { + return static_cast<To>(from); + } + // not within range. + ec = 1; + return {}; + } + + // nan and inf will be preserved + return static_cast<To>(from); +} // function + +template <typename To, typename From, + FMT_ENABLE_IF(std::is_same<From, To>::value)> +FMT_CONSTEXPR To safe_float_conversion(const From from, int& ec) { + ec = 0; + static_assert(std::is_floating_point<From>::value, "From must be floating"); + return from; +} + +/** + * safe duration cast between integral durations + */ +template <typename To, typename FromRep, typename FromPeriod, + FMT_ENABLE_IF(std::is_integral<FromRep>::value), + FMT_ENABLE_IF(std::is_integral<typename To::rep>::value)> +To safe_duration_cast(std::chrono::duration<FromRep, FromPeriod> from, + int& ec) { + using From = std::chrono::duration<FromRep, FromPeriod>; + 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<typename From::period, typename To::period> {}; + + 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<typename From::rep, typename To::rep, + decltype(Factor::num)>::type; + + // safe conversion to IntermediateRep + IntermediateRep count = + lossless_integral_conversion<IntermediateRep>(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<IntermediateRep>() / Factor::num; + if (count > max1) { + ec = 1; + return {}; + } + const auto min1 = + (std::numeric_limits<IntermediateRep>::min)() / Factor::num; + if (count < min1) { + ec = 1; + return {}; + } + count *= Factor::num; + } + + if (detail::const_check(Factor::den != 1)) count /= Factor::den; + auto tocount = lossless_integral_conversion<typename To::rep>(count, ec); + return ec ? To() : To(tocount); +} + +/** + * safe duration_cast between floating point durations + */ +template <typename To, typename FromRep, typename FromPeriod, + FMT_ENABLE_IF(std::is_floating_point<FromRep>::value), + FMT_ENABLE_IF(std::is_floating_point<typename To::rep>::value)> +To safe_duration_cast(std::chrono::duration<FromRep, FromPeriod> from, + int& ec) { + using From = std::chrono::duration<FromRep, FromPeriod>; + ec = 0; + if (std::isnan(from.count())) { + // nan in, gives nan out. easy. + return To{std::numeric_limits<typename To::rep>::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<typename From::period, typename To::period> {}; + + 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<typename From::rep, typename To::rep, + decltype(Factor::num)>::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<IntermediateRep>(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<IntermediateRep>() / + static_cast<IntermediateRep>(Factor::num); + if (count > max1) { + ec = 1; + return {}; + } + constexpr auto min1 = std::numeric_limits<IntermediateRep>::lowest() / + static_cast<IntermediateRep>(Factor::num); + if (count < min1) { + ec = 1; + return {}; + } + count *= static_cast<IntermediateRep>(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<IntermediateRep, intmax_t>::type; + count /= static_cast<common_t>(Factor::den); + } + + // convert to the to type, safely + using ToRep = typename To::rep; + + const ToRep tocount = safe_float_conversion<ToRep>(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 <typename T = void> struct null {}; +inline null<> localtime_r FMT_NOMACRO(...) { return null<>(); } +inline null<> localtime_s(...) { return null<>(); } +inline null<> gmtime_r(...) { return null<>(); } +inline null<> gmtime_s(...) { return null<>(); } + +inline const std::locale& get_classic_locale() { + static const auto& locale = std::locale::classic(); + return locale; +} + +template <typename CodeUnit> struct codecvt_result { + static constexpr const size_t max_size = 32; + CodeUnit buf[max_size]; + CodeUnit* end; +}; +template <typename CodeUnit> +constexpr const size_t codecvt_result<CodeUnit>::max_size; + +template <typename CodeUnit> +void write_codecvt(codecvt_result<CodeUnit>& out, string_view in_buf, + const std::locale& loc) { + using codecvt = std::codecvt<CodeUnit, char, std::mbstate_t>; +#if FMT_CLANG_VERSION +# pragma clang diagnostic push +# pragma clang diagnostic ignored "-Wdeprecated" + auto& f = std::use_facet<codecvt>(loc); +# pragma clang diagnostic pop +#else + auto& f = std::use_facet<codecvt>(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 <typename OutputIt> +auto write_encoded_tm_str(OutputIt out, string_view in, const std::locale& loc) + -> OutputIt { + if (detail::is_utf8() && loc != get_classic_locale()) { + // char16_t and char32_t codecvts are broken in MSVC (linkage errors) and + // gcc-4. +#if FMT_MSC_VER != 0 || \ + (defined(__GLIBCXX__) && !defined(_GLIBCXX_USE_DUAL_ABI)) + // 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<code_unit>; + unit_t unit; + write_codecvt(unit, in, loc); + // In UTF-8 is used one to four one-byte code units. + auto&& buf = basic_memory_buffer<char, unit_t::max_size * 4>(); + for (code_unit* p = unit.buf; p != unit.end; ++p) { + uint32_t c = static_cast<uint32_t>(*p); + if (sizeof(code_unit) == 2 && c >= 0xd800 && c <= 0xdfff) { + // surrogate pair + ++p; + if (p == unit.end || (c & 0xfc00) != 0xd800 || + (*p & 0xfc00) != 0xdc00) { + FMT_THROW(format_error("failed to format time")); + } + c = (c << 10) + static_cast<uint32_t>(*p) - 0x35fdc00; + } + if (c < 0x80) { + buf.push_back(static_cast<char>(c)); + } else if (c < 0x800) { + buf.push_back(static_cast<char>(0xc0 | (c >> 6))); + buf.push_back(static_cast<char>(0x80 | (c & 0x3f))); + } else if ((c >= 0x800 && c <= 0xd7ff) || (c >= 0xe000 && c <= 0xffff)) { + buf.push_back(static_cast<char>(0xe0 | (c >> 12))); + buf.push_back(static_cast<char>(0x80 | ((c & 0xfff) >> 6))); + buf.push_back(static_cast<char>(0x80 | (c & 0x3f))); + } else if (c >= 0x10000 && c <= 0x10ffff) { + buf.push_back(static_cast<char>(0xf0 | (c >> 18))); + buf.push_back(static_cast<char>(0x80 | ((c & 0x3ffff) >> 12))); + buf.push_back(static_cast<char>(0x80 | ((c & 0xfff) >> 6))); + buf.push_back(static_cast<char>(0x80 | (c & 0x3f))); + } else { + FMT_THROW(format_error("failed to format time")); + } + } + return copy_str<char>(buf.data(), buf.data() + buf.size(), out); + } + return copy_str<char>(in.data(), in.data() + in.size(), out); +} + +template <typename Char, typename OutputIt, + FMT_ENABLE_IF(!std::is_same<Char, char>::value)> +auto write_tm_str(OutputIt out, string_view sv, const std::locale& loc) + -> OutputIt { + codecvt_result<Char> unit; + write_codecvt(unit, sv, loc); + return copy_str<Char>(unit.buf, unit.end, out); +} + +template <typename Char, typename OutputIt, + FMT_ENABLE_IF(std::is_same<Char, char>::value)> +auto write_tm_str(OutputIt out, string_view sv, const std::locale& loc) + -> OutputIt { + return write_encoded_tm_str(out, sv, loc); +} + +template <typename Char> +inline void do_write(buffer<Char>& buf, const std::tm& time, + const std::locale& loc, char format, char modifier) { + auto&& format_buf = formatbuf<std::basic_streambuf<Char>>(buf); + auto&& os = std::basic_ostream<Char>(&format_buf); + os.imbue(loc); + using iterator = std::ostreambuf_iterator<Char>; + const auto& facet = std::use_facet<std::time_put<Char, iterator>>(loc); + auto end = facet.put(os, os, Char(' '), &time, format, modifier); + if (end.failed()) FMT_THROW(format_error("failed to format time")); +} + +template <typename Char, typename OutputIt, + FMT_ENABLE_IF(!std::is_same<Char, char>::value)> +auto write(OutputIt out, const std::tm& time, const std::locale& loc, + char format, char modifier = 0) -> OutputIt { + auto&& buf = get_buffer<Char>(out); + do_write<Char>(buf, time, loc, format, modifier); + return buf.out(); +} + +template <typename Char, typename OutputIt, + FMT_ENABLE_IF(std::is_same<Char, char>::value)> +auto write(OutputIt out, const std::tm& time, const std::locale& loc, + char format, char modifier = 0) -> OutputIt { + auto&& buf = basic_memory_buffer<Char>(); + do_write<char>(buf, time, loc, format, modifier); + return write_encoded_tm_str(out, string_view(buf.data(), buf.size()), loc); +} + +} // namespace detail + +FMT_MODULE_EXPORT_BEGIN + +/** + 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 std::tm localtime(std::time_t time) { + struct dispatcher { + std::time_t time_; + std::tm tm_; + + dispatcher(std::time_t t) : time_(t) {} + + bool run() { + using namespace fmt::detail; + return handle(localtime_r(&time_, &tm_)); + } + + bool handle(std::tm* tm) { return tm != nullptr; } + + bool handle(detail::null<>) { + using namespace fmt::detail; + return fallback(localtime_s(&tm_, &time_)); + } + + bool fallback(int res) { return res == 0; } + +#if !FMT_MSC_VER + bool fallback(detail::null<>) { + 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_; +} + +inline std::tm localtime( + std::chrono::time_point<std::chrono::system_clock> time_point) { + return localtime(std::chrono::system_clock::to_time_t(time_point)); +} + +/** + 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 std::tm gmtime(std::time_t time) { + struct dispatcher { + std::time_t time_; + std::tm tm_; + + dispatcher(std::time_t t) : time_(t) {} + + bool run() { + using namespace fmt::detail; + return handle(gmtime_r(&time_, &tm_)); + } + + bool handle(std::tm* tm) { return tm != nullptr; } + + bool handle(detail::null<>) { + using namespace fmt::detail; + return fallback(gmtime_s(&tm_, &time_)); + } + + bool fallback(int res) { return res == 0; } + +#if !FMT_MSC_VER + bool fallback(detail::null<>) { + std::tm* tm = std::gmtime(&time_); + if (tm) tm_ = *tm; + return tm != nullptr; + } +#endif + }; + dispatcher gt(time); + // Too big time values may be unsupported. + if (!gt.run()) FMT_THROW(format_error("time_t value out of range")); + return gt.tm_; +} + +inline std::tm gmtime( + std::chrono::time_point<std::chrono::system_clock> time_point) { + return gmtime(std::chrono::system_clock::to_time_t(time_point)); +} + +FMT_BEGIN_DETAIL_NAMESPACE + +// 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<unsigned long long>(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<unsigned long long>(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]; + memcpy(tmp, &digits, len); + std::reverse_copy(tmp, tmp + len, buf); + } else { + memcpy(buf, &digits, len); + } +} + +template <typename Period> FMT_CONSTEXPR inline const char* get_units() { + if (std::is_same<Period, std::atto>::value) return "as"; + if (std::is_same<Period, std::femto>::value) return "fs"; + if (std::is_same<Period, std::pico>::value) return "ps"; + if (std::is_same<Period, std::nano>::value) return "ns"; + if (std::is_same<Period, std::micro>::value) return "µs"; + if (std::is_same<Period, std::milli>::value) return "ms"; + if (std::is_same<Period, std::centi>::value) return "cs"; + if (std::is_same<Period, std::deci>::value) return "ds"; + if (std::is_same<Period, std::ratio<1>>::value) return "s"; + if (std::is_same<Period, std::deca>::value) return "das"; + if (std::is_same<Period, std::hecto>::value) return "hs"; + if (std::is_same<Period, std::kilo>::value) return "ks"; + if (std::is_same<Period, std::mega>::value) return "Ms"; + if (std::is_same<Period, std::giga>::value) return "Gs"; + if (std::is_same<Period, std::tera>::value) return "Ts"; + if (std::is_same<Period, std::peta>::value) return "Ps"; + if (std::is_same<Period, std::exa>::value) return "Es"; + if (std::is_same<Period, std::ratio<60>>::value) return "m"; + if (std::is_same<Period, std::ratio<3600>>::value) return "h"; + return nullptr; +} + +enum class numeric_system { + standard, + // Alternative numeric system, e.g. å二 instead of 12 in ja_JP locale. + alternative +}; + +// Parses a put_time-like format string and invokes handler actions. +template <typename Char, typename Handler> +FMT_CONSTEXPR const Char* parse_chrono_format(const Char* begin, + const Char* end, + Handler&& handler) { + auto ptr = begin; + while (ptr != end) { + 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 '%': + 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); + break; + case 'W': + handler.on_dec1_week_of_year(numeric_system::standard); + break; + case 'V': + handler.on_iso_week_of_year(numeric_system::standard); + break; + case 'j': + handler.on_day_of_year(); + break; + case 'd': + handler.on_day_of_month(numeric_system::standard); + break; + case 'e': + handler.on_day_of_month_space(numeric_system::standard); + break; + // Hour, minute, second: + case 'H': + handler.on_24_hour(numeric_system::standard); + break; + case 'I': + handler.on_12_hour(numeric_system::standard); + break; + case 'M': + handler.on_minute(numeric_system::standard); + break; + case 'S': + handler.on_second(numeric_system::standard); + 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(); + 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; + 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); + break; + case 'W': + handler.on_dec1_week_of_year(numeric_system::alternative); + break; + case 'V': + handler.on_iso_week_of_year(numeric_system::alternative); + break; + case 'd': + handler.on_day_of_month(numeric_system::alternative); + break; + case 'e': + handler.on_day_of_month_space(numeric_system::alternative); + 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); + break; + case 'I': + handler.on_12_hour(numeric_system::alternative); + break; + case 'M': + handler.on_minute(numeric_system::alternative); + break; + case 'S': + handler.on_second(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 <typename Derived> struct null_chrono_spec_handler { + FMT_CONSTEXPR void unsupported() { + static_cast<Derived*>(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) { unsupported(); } + FMT_CONSTEXPR void on_dec1_week_of_year(numeric_system) { unsupported(); } + FMT_CONSTEXPR void on_iso_week_of_year(numeric_system) { unsupported(); } + FMT_CONSTEXPR void on_day_of_year() { unsupported(); } + FMT_CONSTEXPR void on_day_of_month(numeric_system) { unsupported(); } + FMT_CONSTEXPR void on_day_of_month_space(numeric_system) { 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() { unsupported(); } + FMT_CONSTEXPR void on_tz_name() { unsupported(); } +}; + +struct tm_format_checker : null_chrono_spec_handler<tm_format_checker> { + FMT_NORETURN void unsupported() { FMT_THROW(format_error("no format")); } + + template <typename Char> + 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) {} + FMT_CONSTEXPR void on_dec1_week_of_year(numeric_system) {} + FMT_CONSTEXPR void on_iso_week_of_year(numeric_system) {} + FMT_CONSTEXPR void on_day_of_year() {} + FMT_CONSTEXPR void on_day_of_month(numeric_system) {} + FMT_CONSTEXPR void on_day_of_month_space(numeric_system) {} + FMT_CONSTEXPR void on_24_hour(numeric_system) {} + FMT_CONSTEXPR void on_12_hour(numeric_system) {} + FMT_CONSTEXPR void on_minute(numeric_system) {} + FMT_CONSTEXPR void on_second(numeric_system) {} + 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() {} + FMT_CONSTEXPR void on_tz_name() {} +}; + +inline const char* tm_wday_full_name(int wday) { + static constexpr const char* full_name_list[] = { + "Sunday", "Monday", "Tuesday", "Wednesday", + "Thursday", "Friday", "Saturday"}; + return wday >= 0 && wday <= 6 ? full_name_list[wday] : "?"; +} +inline const char* tm_wday_short_name(int wday) { + static constexpr const char* short_name_list[] = {"Sun", "Mon", "Tue", "Wed", + "Thu", "Fri", "Sat"}; + return wday >= 0 && wday <= 6 ? short_name_list[wday] : "???"; +} + +inline const char* tm_mon_full_name(int mon) { + 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 const char* tm_mon_short_name(int mon) { + 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 <typename T, typename = void> +struct has_member_data_tm_gmtoff : std::false_type {}; +template <typename T> +struct has_member_data_tm_gmtoff<T, void_t<decltype(T::tm_gmtoff)>> + : std::true_type {}; + +template <typename T, typename = void> +struct has_member_data_tm_zone : std::false_type {}; +template <typename T> +struct has_member_data_tm_zone<T, void_t<decltype(T::tm_zone)>> + : std::true_type {}; + +#if FMT_USE_TZSET +inline void tzset_once() { + static bool init = []() -> bool { + _tzset(); + return true; + }(); + ignore_unused(init); +} +#endif + +template <typename OutputIt, typename Char> class tm_writer { + private: + static constexpr int days_per_week = 7; + + const std::locale& loc_; + const bool is_classic_; + OutputIt out_; + 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<int>(l); + } + + // Algorithm: + // https://en.wikipedia.org/wiki/ISO_week_date#Calculating_the_week_number_from_a_month_and_day_of_the_month_or_ordinal_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<char>('0' + to_unsigned(value) % 10); + } + void write2(int value) { + const char* d = digits2(to_unsigned(value) % 100); + *out_++ = *d++; + *out_++ = *d; + } + + 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<long long> n = to_unsigned(year); + const int num_digits = count_digits(n); + if (width > num_digits) out_ = std::fill_n(out_, width - num_digits, '0'); + out_ = format_decimal<Char>(out_, n, num_digits).end; + } + void write_year(long long year) { + if (year >= 0 && year < 10000) { + write2(static_cast<int>(year / 100)); + write2(static_cast<int>(year % 100)); + } else { + write_year_extended(year); + } + } + + void write_utc_offset(long offset) { + if (offset < 0) { + *out_++ = '-'; + offset = -offset; + } else { + *out_++ = '+'; + } + offset /= 60; + write2(static_cast<int>(offset / 60)); + write2(static_cast<int>(offset % 60)); + } + template <typename T, FMT_ENABLE_IF(has_member_data_tm_gmtoff<T>::value)> + void format_utc_offset_impl(const T& tm) { + write_utc_offset(tm.tm_gmtoff); + } + template <typename T, FMT_ENABLE_IF(!has_member_data_tm_gmtoff<T>::value)> + void format_utc_offset_impl(const T& tm) { +#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); +#else + ignore_unused(tm); + format_localized('z'); +#endif + } + + template <typename T, FMT_ENABLE_IF(has_member_data_tm_zone<T>::value)> + void format_tz_name_impl(const T& tm) { + if (is_classic_) + out_ = write_tm_str<Char>(out_, tm.tm_zone, loc_); + else + format_localized('Z'); + } + template <typename T, FMT_ENABLE_IF(!has_member_data_tm_zone<T>::value)> + void format_tz_name_impl(const T&) { + format_localized('Z'); + } + + void format_localized(char format, char modifier = 0) { + out_ = write<Char>(out_, tm_, loc_, format, modifier); + } + + public: + tm_writer(const std::locale& loc, OutputIt out, const std::tm& tm) + : loc_(loc), + is_classic_(loc_ == get_classic_locale()), + out_(out), + tm_(tm) {} + + OutputIt out() const { return out_; } + + FMT_CONSTEXPR void on_text(const Char* begin, const Char* end) { + out_ = copy_str<Char>(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_space(numeric_system::standard); + *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_str<Char>(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(to_unsigned(year / 100))); + } else { + offset = 4; + write_year_extended(year); + year = 0; + } + write_digit2_separated(buf + 2, static_cast<unsigned>(year % 100), + to_unsigned(tm_mon() + 1), to_unsigned(tm_mday()), + '-'); + out_ = copy_str<Char>(std::begin(buf) + offset, std::end(buf), out_); + } + + void on_utc_offset() { format_utc_offset_impl(tm_); } + 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<int>(upper)); + } else { + out_ = write<Char>(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) { + if (is_classic_ || ns == numeric_system::standard) + return write2((tm_yday() + days_per_week - tm_wday()) / days_per_week); + format_localized('U', 'O'); + } + void on_dec1_week_of_year(numeric_system ns) { + 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); + } else { + format_localized('W', 'O'); + } + } + void on_iso_week_of_year(numeric_system ns) { + if (is_classic_ || ns == numeric_system::standard) + return write2(tm_iso_week_of_year()); + 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) { + if (is_classic_ || ns == numeric_system::standard) return write2(tm_mday()); + format_localized('d', 'O'); + } + void on_day_of_month_space(numeric_system ns) { + if (is_classic_ || ns == numeric_system::standard) { + auto mday = to_unsigned(tm_mday()) % 100; + const char* d2 = digits2(mday); + *out_++ = mday < 10 ? ' ' : d2[0]; + *out_++ = d2[1]; + } else { + format_localized('e', 'O'); + } + } + + void on_24_hour(numeric_system ns) { + if (is_classic_ || ns == numeric_system::standard) return write2(tm_hour()); + format_localized('H', 'O'); + } + void on_12_hour(numeric_system ns) { + if (is_classic_ || ns == numeric_system::standard) + return write2(tm_hour12()); + format_localized('I', 'O'); + } + void on_minute(numeric_system ns) { + if (is_classic_ || ns == numeric_system::standard) return write2(tm_min()); + format_localized('M', 'O'); + } + void on_second(numeric_system ns) { + if (is_classic_ || ns == numeric_system::standard) return write2(tm_sec()); + 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_str<Char>(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() { + char buf[8]; + write_digit2_separated(buf, to_unsigned(tm_hour()), to_unsigned(tm_min()), + to_unsigned(tm_sec()), ':'); + out_ = copy_str<Char>(std::begin(buf), std::end(buf), out_); + } + + 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<chrono_format_checker> { + FMT_NORETURN void unsupported() { FMT_THROW(format_error("no date")); } + + template <typename Char> + FMT_CONSTEXPR void on_text(const Char*, const Char*) {} + FMT_CONSTEXPR void on_24_hour(numeric_system) {} + FMT_CONSTEXPR void on_12_hour(numeric_system) {} + FMT_CONSTEXPR void on_minute(numeric_system) {} + FMT_CONSTEXPR void on_second(numeric_system) {} + 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() {} + FMT_CONSTEXPR void on_duration_unit() {} +}; + +template <typename T, FMT_ENABLE_IF(std::is_integral<T>::value)> +inline bool isnan(T) { + return false; +} +template <typename T, FMT_ENABLE_IF(std::is_floating_point<T>::value)> +inline bool isnan(T value) { + return std::isnan(value); +} + +template <typename T, FMT_ENABLE_IF(std::is_integral<T>::value)> +inline bool isfinite(T) { + return true; +} + +// Converts value to Int and checks that it's in the range [0, upper). +template <typename T, typename Int, FMT_ENABLE_IF(std::is_integral<T>::value)> +inline Int to_nonnegative_int(T value, Int upper) { + FMT_ASSERT(value >= 0 && to_unsigned(value) <= to_unsigned(upper), + "invalid value"); + (void)upper; + return static_cast<Int>(value); +} +template <typename T, typename Int, FMT_ENABLE_IF(!std::is_integral<T>::value)> +inline Int to_nonnegative_int(T value, Int upper) { + if (value < 0 || value > static_cast<T>(upper)) + FMT_THROW(format_error("invalid value")); + return static_cast<Int>(value); +} + +template <typename T, FMT_ENABLE_IF(std::is_integral<T>::value)> +inline T mod(T x, int y) { + return x % static_cast<T>(y); +} +template <typename T, FMT_ENABLE_IF(std::is_floating_point<T>::value)> +inline T mod(T x, int y) { + return std::fmod(x, static_cast<T>(y)); +} + +// If T is an integral type, maps T to its unsigned counterpart, otherwise +// leaves it unchanged (unlike std::make_unsigned). +template <typename T, bool INTEGRAL = std::is_integral<T>::value> +struct make_unsigned_or_unchanged { + using type = T; +}; + +template <typename T> struct make_unsigned_or_unchanged<T, true> { + using type = typename std::make_unsigned<T>::type; +}; + +#if FMT_SAFE_DURATION_CAST +// throwing version of safe_duration_cast +template <typename To, typename FromRep, typename FromPeriod> +To fmt_safe_duration_cast(std::chrono::duration<FromRep, FromPeriod> from) { + int ec; + To to = safe_duration_cast::safe_duration_cast<To>(from, ec); + if (ec) FMT_THROW(format_error("cannot format duration")); + return to; +} +#endif + +template <typename Rep, typename Period, + FMT_ENABLE_IF(std::is_integral<Rep>::value)> +inline std::chrono::duration<Rep, std::milli> get_milliseconds( + std::chrono::duration<Rep, Period> d) { + // 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<decltype(d), std::chrono::seconds>::type; + const auto d_as_common = fmt_safe_duration_cast<CommonSecondsType>(d); + const auto d_as_whole_seconds = + fmt_safe_duration_cast<std::chrono::seconds>(d_as_common); + // this conversion should be nonproblematic + const auto diff = d_as_common - d_as_whole_seconds; + const auto ms = + fmt_safe_duration_cast<std::chrono::duration<Rep, std::milli>>(diff); + return ms; +#else + auto s = std::chrono::duration_cast<std::chrono::seconds>(d); + return std::chrono::duration_cast<std::chrono::milliseconds>(d - s); +#endif +} + +// Returns 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. +constexpr int count_fractional_digits(long long num, long long den, int n = 0) { + return num % den == 0 + ? n + : (n > 18 ? 6 : count_fractional_digits(num * 10, den, n + 1)); +} + +constexpr long long pow10(std::uint32_t n) { + return n == 0 ? 1 : 10 * pow10(n - 1); +} + +template <class Rep, class Period, + FMT_ENABLE_IF(std::numeric_limits<Rep>::is_signed)> +constexpr std::chrono::duration<Rep, Period> abs( + std::chrono::duration<Rep, Period> d) { + // We need to compare the duration using the count() method directly + // due to a compiler bug in clang-11 regarding the spaceship operator, + // when -Wzero-as-null-pointer-constant is enabled. + // In clang-12 the bug has been fixed. See + // https://bugs.llvm.org/show_bug.cgi?id=46235 and the reproducible example: + // https://www.godbolt.org/z/Knbb5joYx. + return d.count() >= d.zero().count() ? d : -d; +} + +template <class Rep, class Period, + FMT_ENABLE_IF(!std::numeric_limits<Rep>::is_signed)> +constexpr std::chrono::duration<Rep, Period> abs( + std::chrono::duration<Rep, Period> d) { + return d; +} + +template <typename Char, typename Rep, typename OutputIt, + FMT_ENABLE_IF(std::is_integral<Rep>::value)> +OutputIt format_duration_value(OutputIt out, Rep val, int) { + return write<Char>(out, val); +} + +template <typename Char, typename Rep, typename OutputIt, + FMT_ENABLE_IF(std::is_floating_point<Rep>::value)> +OutputIt format_duration_value(OutputIt out, Rep val, int precision) { + auto specs = basic_format_specs<Char>(); + specs.precision = precision; + specs.type = precision >= 0 ? presentation_type::fixed_lower + : presentation_type::general_lower; + return write<Char>(out, val, specs); +} + +template <typename Char, typename OutputIt> +OutputIt copy_unit(string_view unit, OutputIt out, Char) { + return std::copy(unit.begin(), unit.end(), out); +} + +template <typename OutputIt> +OutputIt copy_unit(string_view unit, OutputIt out, wchar_t) { + // 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 <typename Char, typename Period, typename OutputIt> +OutputIt format_duration_unit(OutputIt out) { + if (const char* unit = get_units<Period>()) + return copy_unit(string_view(unit), out, Char()); + *out++ = '['; + out = write<Char>(out, Period::num); + if (const_check(Period::den != 1)) { + *out++ = '/'; + out = write<Char>(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) { + if (localized) + ::new (&locale_) std::locale(loc.template get<std::locale>()); + } + ~get_locale() { + if (has_locale_) locale_.~locale(); + } + operator const std::locale&() const { + return has_locale_ ? locale_ : get_classic_locale(); + } +}; + +template <typename FormatContext, typename OutputIt, typename Rep, + typename Period> +struct chrono_formatter { + FormatContext& context; + OutputIt out; + int precision; + bool localized = false; + // rep is unsigned to avoid overflow. + using rep = + conditional_t<std::is_integral<Rep>::value && sizeof(Rep) < sizeof(int), + unsigned, typename make_unsigned_or_unchanged<Rep>::type>; + rep val; + using seconds = std::chrono::duration<rep>; + seconds s; + using milliseconds = std::chrono::duration<rep, std::milli>; + bool negative; + + using char_type = typename FormatContext::char_type; + using tm_writer_type = tm_writer<OutputIt, char_type>; + + chrono_formatter(FormatContext& ctx, OutputIt o, + std::chrono::duration<Rep, Period> d) + : context(ctx), + out(o), + val(static_cast<rep>(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. +#if FMT_SAFE_DURATION_CAST + // might need checked conversion (rep!=Rep) + auto tmpval = std::chrono::duration<rep, Period>(val); + s = fmt_safe_duration_cast<seconds>(tmpval); +#else + s = std::chrono::duration_cast<seconds>( + std::chrono::duration<rep, Period>(val)); +#endif + } + + // returns true if nan or inf, writes to out. + bool handle_nan_inf() { + 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; + } + + Rep hour() const { return static_cast<Rep>(mod((s.count() / 3600), 24)); } + + Rep hour12() const { + Rep hour = static_cast<Rep>(mod((s.count() / 3600), 12)); + return hour <= 0 ? 12 : hour; + } + + Rep minute() const { return static_cast<Rep>(mod((s.count() / 60), 60)); } + Rep second() const { return static_cast<Rep>(mod(s.count(), 60)); } + + std::tm time() const { + 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) { + write_sign(); + if (isnan(value)) return write_nan(); + uint32_or_64_or_128_t<int> n = + to_unsigned(to_nonnegative_int(value, max_value<int>())); + int num_digits = detail::count_digits(n); + if (width > num_digits) out = std::fill_n(out, width - num_digits, '0'); + out = format_decimal<char_type>(out, n, num_digits).end; + } + + template <class Duration> void write_fractional_seconds(Duration d) { + constexpr auto num_fractional_digits = + count_fractional_digits(Duration::period::num, Duration::period::den); + + using subsecond_precision = std::chrono::duration< + typename std::common_type<typename Duration::rep, + std::chrono::seconds::rep>::type, + std::ratio<1, detail::pow10(num_fractional_digits)>>; + if (std::ratio_less<typename subsecond_precision::period, + std::chrono::seconds::period>::value) { + *out++ = '.'; + // Don't convert long double to integer seconds to avoid overflow. + using sec = conditional_t< + std::is_same<typename Duration::rep, long double>::value, + std::chrono::duration<long double>, std::chrono::seconds>; + auto fractional = detail::abs(d) - std::chrono::duration_cast<sec>(d); + const auto subseconds = + std::chrono::treat_as_floating_point< + typename subsecond_precision::rep>::value + ? fractional.count() + : std::chrono::duration_cast<subsecond_precision>(fractional) + .count(); + uint32_or_64_or_128_t<long long> n = + to_unsigned(to_nonnegative_int(subseconds, max_value<long long>())); + int num_digits = detail::count_digits(n); + if (num_fractional_digits > num_digits) + out = std::fill_n(out, num_fractional_digits - num_digits, '0'); + out = format_decimal<char_type>(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 <typename Callback, typename... Args> + 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() {} + 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) {} + void on_dec1_week_of_year(numeric_system) {} + void on_iso_week_of_year(numeric_system) {} + void on_day_of_year() {} + void on_day_of_month(numeric_system) {} + void on_day_of_month_space(numeric_system) {} + + void on_24_hour(numeric_system ns) { + if (handle_nan_inf()) return; + + if (ns == numeric_system::standard) return write(hour(), 2); + auto time = tm(); + time.tm_hour = to_nonnegative_int(hour(), 24); + format_tm(time, &tm_writer_type::on_24_hour, ns); + } + + void on_12_hour(numeric_system ns) { + if (handle_nan_inf()) return; + + if (ns == numeric_system::standard) return write(hour12(), 2); + auto time = tm(); + time.tm_hour = to_nonnegative_int(hour12(), 12); + format_tm(time, &tm_writer_type::on_12_hour, ns); + } + + void on_minute(numeric_system ns) { + if (handle_nan_inf()) return; + + if (ns == numeric_system::standard) return write(minute(), 2); + auto time = tm(); + time.tm_min = to_nonnegative_int(minute(), 60); + format_tm(time, &tm_writer_type::on_minute, ns); + } + + void on_second(numeric_system ns) { + if (handle_nan_inf()) return; + + if (ns == numeric_system::standard) { + write(second(), 2); + write_fractional_seconds(std::chrono::duration<rep, Period>{val}); + return; + } + auto time = tm(); + time.tm_sec = to_nonnegative_int(second(), 60); + format_tm(time, &tm_writer_type::on_second, ns); + } + + 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); + } + + 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<char_type>(out, val, precision); + } + + void on_duration_unit() { + out = format_duration_unit<char_type, Period>(out); + } +}; + +FMT_END_DETAIL_NAMESPACE + +#if defined(__cpp_lib_chrono) && __cpp_lib_chrono >= 201907 +using weekday = std::chrono::weekday; +#else +// A fallback version of weekday. +class weekday { + private: + unsigned char value; + + public: + weekday() = default; + explicit constexpr weekday(unsigned wd) noexcept + : value(static_cast<unsigned char>(wd != 7 ? wd : 0)) {} + constexpr unsigned c_encoding() const noexcept { return value; } +}; + +class year_month_day {}; +#endif + +// A rudimentary weekday formatter. +template <typename Char> struct formatter<weekday, Char> { + private: + bool localized = false; + + public: + FMT_CONSTEXPR auto parse(basic_format_parse_context<Char>& ctx) + -> decltype(ctx.begin()) { + auto begin = ctx.begin(), end = ctx.end(); + if (begin != end && *begin == 'L') { + ++begin; + localized = true; + } + return begin; + } + + template <typename FormatContext> + auto format(weekday wd, FormatContext& ctx) const -> decltype(ctx.out()) { + auto time = std::tm(); + time.tm_wday = static_cast<int>(wd.c_encoding()); + detail::get_locale loc(localized, ctx.locale()); + auto w = detail::tm_writer<decltype(ctx.out()), Char>(loc, ctx.out(), time); + w.on_abbr_weekday(); + return w.out(); + } +}; + +template <typename Rep, typename Period, typename Char> +struct formatter<std::chrono::duration<Rep, Period>, Char> { + private: + basic_format_specs<Char> specs; + int precision = -1; + using arg_ref_type = detail::arg_ref<Char>; + arg_ref_type width_ref; + arg_ref_type precision_ref; + bool localized = false; + basic_string_view<Char> format_str; + using duration = std::chrono::duration<Rep, Period>; + + struct spec_handler { + formatter& f; + basic_format_parse_context<Char>& context; + basic_string_view<Char> format_str; + + template <typename Id> FMT_CONSTEXPR arg_ref_type make_arg_ref(Id arg_id) { + context.check_arg_id(arg_id); + return arg_ref_type(arg_id); + } + + FMT_CONSTEXPR arg_ref_type make_arg_ref(basic_string_view<Char> arg_id) { + context.check_arg_id(arg_id); + return arg_ref_type(arg_id); + } + + FMT_CONSTEXPR arg_ref_type make_arg_ref(detail::auto_id) { + return arg_ref_type(context.next_arg_id()); + } + + void on_error(const char* msg) { FMT_THROW(format_error(msg)); } + FMT_CONSTEXPR void on_fill(basic_string_view<Char> fill) { + f.specs.fill = fill; + } + FMT_CONSTEXPR void on_align(align_t align) { f.specs.align = align; } + FMT_CONSTEXPR void on_width(int width) { f.specs.width = width; } + FMT_CONSTEXPR void on_precision(int _precision) { + f.precision = _precision; + } + FMT_CONSTEXPR void end_precision() {} + + template <typename Id> FMT_CONSTEXPR void on_dynamic_width(Id arg_id) { + f.width_ref = make_arg_ref(arg_id); + } + + template <typename Id> FMT_CONSTEXPR void on_dynamic_precision(Id arg_id) { + f.precision_ref = make_arg_ref(arg_id); + } + }; + + using iterator = typename basic_format_parse_context<Char>::iterator; + struct parse_range { + iterator begin; + iterator end; + }; + + FMT_CONSTEXPR parse_range do_parse(basic_format_parse_context<Char>& ctx) { + auto begin = ctx.begin(), end = ctx.end(); + if (begin == end || *begin == '}') return {begin, begin}; + spec_handler handler{*this, ctx, format_str}; + begin = detail::parse_align(begin, end, handler); + if (begin == end) return {begin, begin}; + begin = detail::parse_width(begin, end, handler); + if (begin == end) return {begin, begin}; + if (*begin == '.') { + if (std::is_floating_point<Rep>::value) + begin = detail::parse_precision(begin, end, handler); + else + handler.on_error("precision not allowed for this argument type"); + } + if (begin != end && *begin == 'L') { + ++begin; + localized = true; + } + end = detail::parse_chrono_format(begin, end, + detail::chrono_format_checker()); + return {begin, end}; + } + + public: + FMT_CONSTEXPR auto parse(basic_format_parse_context<Char>& ctx) + -> decltype(ctx.begin()) { + auto range = do_parse(ctx); + format_str = basic_string_view<Char>( + &*range.begin, detail::to_unsigned(range.end - range.begin)); + return range.end; + } + + template <typename FormatContext> + auto format(const duration& d, FormatContext& ctx) const + -> decltype(ctx.out()) { + auto specs_copy = specs; + auto precision_copy = precision; + auto begin = format_str.begin(), end = format_str.end(); + // As a possible future optimization, we could avoid extra copying if width + // is not specified. + basic_memory_buffer<Char> buf; + auto out = std::back_inserter(buf); + detail::handle_dynamic_spec<detail::width_checker>(specs_copy.width, + width_ref, ctx); + detail::handle_dynamic_spec<detail::precision_checker>(precision_copy, + precision_ref, ctx); + if (begin == end || *begin == '}') { + out = detail::format_duration_value<Char>(out, d.count(), precision_copy); + detail::format_duration_unit<Char, Period>(out); + } else { + detail::chrono_formatter<FormatContext, decltype(out), Rep, Period> f( + ctx, out, d); + f.precision = precision_copy; + f.localized = localized; + detail::parse_chrono_format(begin, end, f); + } + return detail::write( + ctx.out(), basic_string_view<Char>(buf.data(), buf.size()), specs_copy); + } +}; + +template <typename Char, typename Duration> +struct formatter<std::chrono::time_point<std::chrono::system_clock, Duration>, + Char> : formatter<std::tm, Char> { + FMT_CONSTEXPR formatter() { + this->do_parse(default_specs, + default_specs + sizeof(default_specs) / sizeof(Char)); + } + + template <typename ParseContext> + FMT_CONSTEXPR auto parse(ParseContext& ctx) -> decltype(ctx.begin()) { + return this->do_parse(ctx.begin(), ctx.end(), true); + } + + template <typename FormatContext> + auto format(std::chrono::time_point<std::chrono::system_clock> val, + FormatContext& ctx) const -> decltype(ctx.out()) { + return formatter<std::tm, Char>::format(localtime(val), ctx); + } + + static constexpr const Char default_specs[] = {'%', 'F', ' ', '%', 'T'}; +}; + +template <typename Char, typename Duration> +constexpr const Char + formatter<std::chrono::time_point<std::chrono::system_clock, Duration>, + Char>::default_specs[]; + +template <typename Char> struct formatter<std::tm, Char> { + private: + enum class spec { + unknown, + year_month_day, + hh_mm_ss, + }; + spec spec_ = spec::unknown; + basic_string_view<Char> specs; + + protected: + template <typename It> + FMT_CONSTEXPR auto do_parse(It begin, It end, bool with_default = false) + -> It { + if (begin != end && *begin == ':') ++begin; + end = detail::parse_chrono_format(begin, end, detail::tm_format_checker()); + if (!with_default || end != begin) + specs = {begin, detail::to_unsigned(end - begin)}; + // basic_string_view<>::compare isn't constexpr before C++17. + if (specs.size() == 2 && specs[0] == Char('%')) { + if (specs[1] == Char('F')) + spec_ = spec::year_month_day; + else if (specs[1] == Char('T')) + spec_ = spec::hh_mm_ss; + } + return end; + } + + public: + template <typename ParseContext> + FMT_CONSTEXPR auto parse(ParseContext& ctx) -> decltype(ctx.begin()) { + return this->do_parse(ctx.begin(), ctx.end()); + } + + template <typename FormatContext> + auto format(const std::tm& tm, FormatContext& ctx) const + -> decltype(ctx.out()) { + const auto loc_ref = ctx.locale(); + detail::get_locale loc(static_cast<bool>(loc_ref), loc_ref); + auto w = detail::tm_writer<decltype(ctx.out()), Char>(loc, ctx.out(), tm); + if (spec_ == spec::year_month_day) + w.on_iso_date(); + else if (spec_ == spec::hh_mm_ss) + w.on_iso_time(); + else + detail::parse_chrono_format(specs.begin(), specs.end(), w); + return w.out(); + } +}; + +FMT_MODULE_EXPORT_END +FMT_END_NAMESPACE + +#endif // FMT_CHRONO_H_ diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/spdlog/fmt/bundled/color.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/spdlog/fmt/bundled/color.h new file mode 100644 index 0000000000000000000000000000000000000000..dfbe482938e7e655af996ecfb293af6959114044 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/spdlog/fmt/bundled/color.h @@ -0,0 +1,638 @@ +// 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" + +// __declspec(deprecated) is broken in some MSVC versions. +#if FMT_MSC_VER +# define FMT_DEPRECATED_NONMSVC +#else +# define FMT_DEPRECATED_NONMSVC FMT_DEPRECATED +#endif + +FMT_BEGIN_NAMESPACE +FMT_MODULE_EXPORT_BEGIN + +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; +}; + +FMT_BEGIN_DETAIL_NAMESPACE + +// color is a struct of either a rgb color or a terminal color. +struct color_type { + FMT_CONSTEXPR color_type() FMT_NOEXCEPT : is_rgb(), value{} {} + FMT_CONSTEXPR color_type(color rgb_color) FMT_NOEXCEPT : is_rgb(true), + value{} { + value.rgb_color = static_cast<uint32_t>(rgb_color); + } + FMT_CONSTEXPR color_type(rgb rgb_color) FMT_NOEXCEPT : is_rgb(true), value{} { + value.rgb_color = (static_cast<uint32_t>(rgb_color.r) << 16) | + (static_cast<uint32_t>(rgb_color.g) << 8) | rgb_color.b; + } + FMT_CONSTEXPR color_type(terminal_color term_color) FMT_NOEXCEPT : is_rgb(), + value{} { + value.term_color = static_cast<uint8_t>(term_color); + } + bool is_rgb; + union color_union { + uint8_t term_color; + uint32_t rgb_color; + } value; +}; + +FMT_END_DETAIL_NAMESPACE + +/** A text style consisting of foreground and background colors and emphasis. */ +class text_style { + public: + FMT_CONSTEXPR text_style(emphasis em = emphasis()) FMT_NOEXCEPT + : set_foreground_color(), + set_background_color(), + ems(em) {} + + FMT_CONSTEXPR text_style& operator|=(const text_style& rhs) { + 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) + FMT_THROW(format_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) + FMT_THROW(format_error("can't OR a terminal color")); + background_color.value.rgb_color |= rhs.background_color.value.rgb_color; + } + + ems = static_cast<emphasis>(static_cast<uint8_t>(ems) | + static_cast<uint8_t>(rhs.ems)); + return *this; + } + + friend FMT_CONSTEXPR text_style operator|(text_style lhs, + const text_style& rhs) { + return lhs |= rhs; + } + + FMT_DEPRECATED_NONMSVC FMT_CONSTEXPR text_style& operator&=( + const text_style& rhs) { + return and_assign(rhs); + } + + FMT_DEPRECATED_NONMSVC friend FMT_CONSTEXPR text_style + operator&(text_style lhs, const text_style& rhs) { + return lhs.and_assign(rhs); + } + + FMT_CONSTEXPR bool has_foreground() const FMT_NOEXCEPT { + return set_foreground_color; + } + FMT_CONSTEXPR bool has_background() const FMT_NOEXCEPT { + return set_background_color; + } + FMT_CONSTEXPR bool has_emphasis() const FMT_NOEXCEPT { + return static_cast<uint8_t>(ems) != 0; + } + FMT_CONSTEXPR detail::color_type get_foreground() const FMT_NOEXCEPT { + FMT_ASSERT(has_foreground(), "no foreground specified for this style"); + return foreground_color; + } + FMT_CONSTEXPR detail::color_type get_background() const FMT_NOEXCEPT { + FMT_ASSERT(has_background(), "no background specified for this style"); + return background_color; + } + FMT_CONSTEXPR emphasis get_emphasis() const FMT_NOEXCEPT { + 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) FMT_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; + } + } + + // DEPRECATED! + FMT_CONSTEXPR text_style& and_assign(const text_style& rhs) { + 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) + FMT_THROW(format_error("can't AND 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) + FMT_THROW(format_error("can't AND a terminal color")); + background_color.value.rgb_color &= rhs.background_color.value.rgb_color; + } + + ems = static_cast<emphasis>(static_cast<uint8_t>(ems) & + static_cast<uint8_t>(rhs.ems)); + return *this; + } + + friend FMT_CONSTEXPR_DECL text_style fg(detail::color_type foreground) + FMT_NOEXCEPT; + + friend FMT_CONSTEXPR_DECL text_style bg(detail::color_type background) + FMT_NOEXCEPT; + + 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 text_style fg(detail::color_type foreground) FMT_NOEXCEPT { + return text_style(true, foreground); +} + +/** Creates a text style from the background color. */ +FMT_CONSTEXPR inline text_style bg(detail::color_type background) FMT_NOEXCEPT { + return text_style(false, background); +} + +FMT_CONSTEXPR inline text_style operator|(emphasis lhs, + emphasis rhs) FMT_NOEXCEPT { + return text_style(lhs) | rhs; +} + +FMT_BEGIN_DETAIL_NAMESPACE + +template <typename Char> struct ansi_color_escape { + FMT_CONSTEXPR ansi_color_escape(detail::color_type text_color, + const char* esc) FMT_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<Char>('\x1b'); + buffer[index++] = static_cast<Char>('['); + + if (value >= 100u) { + buffer[index++] = static_cast<Char>('1'); + value %= 100u; + } + buffer[index++] = static_cast<Char>('0' + value / 10u); + buffer[index++] = static_cast<Char>('0' + value % 10u); + + buffer[index++] = static_cast<Char>('m'); + buffer[index++] = static_cast<Char>('\0'); + return; + } + + for (int i = 0; i < 7; i++) { + buffer[i] = static_cast<Char>(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<Char>(0); + } + FMT_CONSTEXPR ansi_color_escape(emphasis em) FMT_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<Char>('\x1b'); + buffer[index++] = static_cast<Char>('['); + buffer[index++] = static_cast<Char>('0' + em_codes[i]); + buffer[index++] = static_cast<Char>('m'); + } + buffer[index++] = static_cast<Char>(0); + } + FMT_CONSTEXPR operator const Char*() const FMT_NOEXCEPT { return buffer; } + + FMT_CONSTEXPR const Char* begin() const FMT_NOEXCEPT { return buffer; } + FMT_CONSTEXPR_CHAR_TRAITS const Char* end() const FMT_NOEXCEPT { + return buffer + std::char_traits<Char>::length(buffer); + } + + 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) FMT_NOEXCEPT { + out[0] = static_cast<Char>('0' + c / 100); + out[1] = static_cast<Char>('0' + c / 10 % 10); + out[2] = static_cast<Char>('0' + c % 10); + out[3] = static_cast<Char>(delimiter); + } + static FMT_CONSTEXPR bool has_emphasis(emphasis em, + emphasis mask) FMT_NOEXCEPT { + return static_cast<uint8_t>(em) & static_cast<uint8_t>(mask); + } +}; + +template <typename Char> +FMT_CONSTEXPR ansi_color_escape<Char> make_foreground_color( + detail::color_type foreground) FMT_NOEXCEPT { + return ansi_color_escape<Char>(foreground, "\x1b[38;2;"); +} + +template <typename Char> +FMT_CONSTEXPR ansi_color_escape<Char> make_background_color( + detail::color_type background) FMT_NOEXCEPT { + return ansi_color_escape<Char>(background, "\x1b[48;2;"); +} + +template <typename Char> +FMT_CONSTEXPR ansi_color_escape<Char> make_emphasis(emphasis em) FMT_NOEXCEPT { + return ansi_color_escape<Char>(em); +} + +template <typename Char> +inline void fputs(const Char* chars, FILE* stream) FMT_NOEXCEPT { + std::fputs(chars, stream); +} + +template <> +inline void fputs<wchar_t>(const wchar_t* chars, FILE* stream) FMT_NOEXCEPT { + std::fputws(chars, stream); +} + +template <typename Char> inline void reset_color(FILE* stream) FMT_NOEXCEPT { + fputs("\x1b[0m", stream); +} + +template <> inline void reset_color<wchar_t>(FILE* stream) FMT_NOEXCEPT { + fputs(L"\x1b[0m", stream); +} + +template <typename Char> +inline void reset_color(buffer<Char>& buffer) FMT_NOEXCEPT { + auto reset_color = string_view("\x1b[0m"); + buffer.append(reset_color.begin(), reset_color.end()); +} + +template <typename Char> +void vformat_to(buffer<Char>& buf, const text_style& ts, + basic_string_view<Char> format_str, + basic_format_args<buffer_context<type_identity_t<Char>>> args) { + bool has_style = false; + if (ts.has_emphasis()) { + has_style = true; + auto emphasis = detail::make_emphasis<Char>(ts.get_emphasis()); + buf.append(emphasis.begin(), emphasis.end()); + } + if (ts.has_foreground()) { + has_style = true; + auto foreground = detail::make_foreground_color<Char>(ts.get_foreground()); + buf.append(foreground.begin(), foreground.end()); + } + if (ts.has_background()) { + has_style = true; + auto background = detail::make_background_color<Char>(ts.get_background()); + buf.append(background.begin(), background.end()); + } + detail::vformat_to(buf, format_str, args, {}); + if (has_style) detail::reset_color<Char>(buf); +} + +FMT_END_DETAIL_NAMESPACE + +template <typename S, typename Char = char_t<S>> +void vprint(std::FILE* f, const text_style& ts, const S& format, + basic_format_args<buffer_context<type_identity_t<Char>>> args) { + basic_memory_buffer<Char> buf; + detail::vformat_to(buf, ts, to_string_view(format), args); + buf.push_back(Char(0)); + detail::fputs(buf.data(), f); +} + +/** + \rst + 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); + \endrst + */ +template <typename S, typename... Args, + FMT_ENABLE_IF(detail::is_string<S>::value)> +void print(std::FILE* f, const text_style& ts, const S& format_str, + const Args&... args) { + vprint(f, ts, format_str, + fmt::make_args_checked<Args...>(format_str, args...)); +} + +/** + \rst + 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); + \endrst + */ +template <typename S, typename... Args, + FMT_ENABLE_IF(detail::is_string<S>::value)> +void print(const text_style& ts, const S& format_str, const Args&... args) { + return print(stdout, ts, format_str, args...); +} + +template <typename S, typename Char = char_t<S>> +inline std::basic_string<Char> vformat( + const text_style& ts, const S& format_str, + basic_format_args<buffer_context<type_identity_t<Char>>> args) { + basic_memory_buffer<Char> buf; + detail::vformat_to(buf, ts, to_string_view(format_str), args); + return fmt::to_string(buf); +} + +/** + \rst + Formats arguments and returns the result as a string using ANSI + escape sequences to specify text formatting. + + **Example**:: + + #include <fmt/color.h> + std::string message = fmt::format(fmt::emphasis::bold | fg(fmt::color::red), + "The answer is {}", 42); + \endrst +*/ +template <typename S, typename... Args, typename Char = char_t<S>> +inline std::basic_string<Char> format(const text_style& ts, const S& format_str, + const Args&... args) { + return fmt::vformat(ts, to_string_view(format_str), + fmt::make_args_checked<Args...>(format_str, args...)); +} + +/** + Formats a string with the given text_style and writes the output to ``out``. + */ +template <typename OutputIt, typename Char, + FMT_ENABLE_IF(detail::is_output_iterator<OutputIt, Char>::value)> +OutputIt vformat_to( + OutputIt out, const text_style& ts, basic_string_view<Char> format_str, + basic_format_args<buffer_context<type_identity_t<Char>>> args) { + auto&& buf = detail::get_buffer<Char>(out); + detail::vformat_to(buf, ts, format_str, args); + return detail::get_iterator(buf); +} + +/** + \rst + 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<char> out; + fmt::format_to(std::back_inserter(out), + fmt::emphasis::bold | fg(fmt::color::red), "{}", 42); + \endrst +*/ +template <typename OutputIt, typename S, typename... Args, + bool enable = detail::is_output_iterator<OutputIt, char_t<S>>::value&& + detail::is_string<S>::value> +inline auto format_to(OutputIt out, const text_style& ts, const S& format_str, + Args&&... args) -> + typename std::enable_if<enable, OutputIt>::type { + return vformat_to(out, ts, to_string_view(format_str), + fmt::make_args_checked<Args...>(format_str, args...)); +} + +FMT_MODULE_EXPORT_END +FMT_END_NAMESPACE + +#endif // FMT_COLOR_H_ diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/spdlog/fmt/bundled/compile.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/spdlog/fmt/bundled/compile.h new file mode 100644 index 0000000000000000000000000000000000000000..1dba3ddb5222b15aaef2bcc41eaef8bc0a4647a5 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/spdlog/fmt/bundled/compile.h @@ -0,0 +1,642 @@ +// 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_ + +#include "format.h" + +FMT_BEGIN_NAMESPACE +namespace detail { + +// 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; + using _Unchecked_type = counting_iterator; // Mark iterator as checked. + + struct value_type { + template <typename T> void operator=(const T&) {} + }; + + counting_iterator() : count_(0) {} + + size_t count() const { return count_; } + + counting_iterator& operator++() { + ++count_; + return *this; + } + counting_iterator operator++(int) { + auto it = *this; + ++*this; + return it; + } + + friend counting_iterator operator+(counting_iterator it, difference_type n) { + it.count_ += static_cast<size_t>(n); + return it; + } + + value_type operator*() const { return {}; } +}; + +template <typename Char, typename InputIt> +inline counting_iterator copy_str(InputIt begin, InputIt end, + counting_iterator it) { + return it + (end - begin); +} + +template <typename OutputIt> class truncating_iterator_base { + protected: + OutputIt out_; + size_t limit_; + size_t count_ = 0; + + truncating_iterator_base() : out_(), limit_(0) {} + + truncating_iterator_base(OutputIt out, size_t limit) + : out_(out), limit_(limit) {} + + public: + using iterator_category = std::output_iterator_tag; + using value_type = typename std::iterator_traits<OutputIt>::value_type; + using difference_type = std::ptrdiff_t; + using pointer = void; + using reference = void; + using _Unchecked_type = + truncating_iterator_base; // Mark iterator as checked. + + OutputIt base() const { return out_; } + size_t count() const { return count_; } +}; + +// An output iterator that truncates the output and counts the number of objects +// written to it. +template <typename OutputIt, + typename Enable = typename std::is_void< + typename std::iterator_traits<OutputIt>::value_type>::type> +class truncating_iterator; + +template <typename OutputIt> +class truncating_iterator<OutputIt, std::false_type> + : public truncating_iterator_base<OutputIt> { + mutable typename truncating_iterator_base<OutputIt>::value_type blackhole_; + + public: + using value_type = typename truncating_iterator_base<OutputIt>::value_type; + + truncating_iterator() = default; + + truncating_iterator(OutputIt out, size_t limit) + : truncating_iterator_base<OutputIt>(out, limit) {} + + truncating_iterator& operator++() { + if (this->count_++ < this->limit_) ++this->out_; + return *this; + } + + truncating_iterator operator++(int) { + auto it = *this; + ++*this; + return it; + } + + value_type& operator*() const { + return this->count_ < this->limit_ ? *this->out_ : blackhole_; + } +}; + +template <typename OutputIt> +class truncating_iterator<OutputIt, std::true_type> + : public truncating_iterator_base<OutputIt> { + public: + truncating_iterator() = default; + + truncating_iterator(OutputIt out, size_t limit) + : truncating_iterator_base<OutputIt>(out, limit) {} + + template <typename T> truncating_iterator& operator=(T val) { + if (this->count_++ < this->limit_) *this->out_++ = val; + return *this; + } + + truncating_iterator& operator++() { return *this; } + truncating_iterator& operator++(int) { return *this; } + truncating_iterator& operator*() { return *this; } +}; + +// A compile-time string which is compiled into fast formatting code. +class compiled_string {}; + +template <typename S> +struct is_compiled_string : std::is_base_of<compiled_string, S> {}; + +/** + \rst + 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); + \endrst + */ +#if defined(__cpp_if_constexpr) && defined(__cpp_return_type_deduction) +# define FMT_COMPILE(s) \ + FMT_STRING_IMPL(s, fmt::detail::compiled_string, explicit) +#else +# define FMT_COMPILE(s) FMT_STRING(s) +#endif + +#if FMT_USE_NONTYPE_TEMPLATE_PARAMETERS +template <typename Char, size_t N, + fmt::detail_exported::fixed_string<Char, N> Str> +struct udl_compiled_string : compiled_string { + using char_type = Char; + constexpr operator basic_string_view<char_type>() const { + return {Str.data, N - 1}; + } +}; +#endif + +template <typename T, typename... Tail> +const T& first(const T& value, const Tail&...) { + return value; +} + +#if defined(__cpp_if_constexpr) && defined(__cpp_return_type_deduction) +template <typename... Args> struct type_list {}; + +// Returns a reference to the argument at index N from [first, rest...]. +template <int N, typename T, typename... Args> +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<N - 1>(rest...); +} + +template <typename Char, typename... Args> +constexpr int get_arg_index_by_name(basic_string_view<Char> name, + type_list<Args...>) { + return get_arg_index_by_name<Args...>(name); +} + +template <int N, typename> struct get_type_impl; + +template <int N, typename... Args> struct get_type_impl<N, type_list<Args...>> { + using type = + remove_cvref_t<decltype(detail::get<N>(std::declval<Args>()...))>; +}; + +template <int N, typename T> +using get_type = typename get_type_impl<N, T>::type; + +template <typename T> struct is_compiled_format : std::false_type {}; + +template <typename Char> struct text { + basic_string_view<Char> data; + using char_type = Char; + + template <typename OutputIt, typename... Args> + constexpr OutputIt format(OutputIt out, const Args&...) const { + return write<Char>(out, data); + } +}; + +template <typename Char> +struct is_compiled_format<text<Char>> : std::true_type {}; + +template <typename Char> +constexpr text<Char> make_text(basic_string_view<Char> s, size_t pos, + size_t size) { + return {{&s[pos], size}}; +} + +template <typename Char> struct code_unit { + Char value; + using char_type = Char; + + template <typename OutputIt, typename... Args> + constexpr OutputIt format(OutputIt out, const Args&...) const { + return write<Char>(out, value); + } +}; + +// This ensures that the argument type is convertible to `const T&`. +template <typename T, int N, typename... Args> +constexpr const T& get_arg_checked(const Args&... args) { + const auto& arg = detail::get<N>(args...); + if constexpr (detail::is_named_arg<remove_cvref_t<decltype(arg)>>()) { + return arg.value; + } else { + return arg; + } +} + +template <typename Char> +struct is_compiled_format<code_unit<Char>> : std::true_type {}; + +// A replacement field that refers to argument N. +template <typename Char, typename T, int N> struct field { + using char_type = Char; + + template <typename OutputIt, typename... Args> + constexpr OutputIt format(OutputIt out, const Args&... args) const { + return write<Char>(out, get_arg_checked<T, N>(args...)); + } +}; + +template <typename Char, typename T, int N> +struct is_compiled_format<field<Char, T, N>> : std::true_type {}; + +// A replacement field that refers to argument with name. +template <typename Char> struct runtime_named_field { + using char_type = Char; + basic_string_view<Char> name; + + template <typename OutputIt, typename T> + 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<Char> arg_name, const T& arg) { + if constexpr (is_named_arg<typename std::remove_cv<T>::type>::value) { + if (arg_name == arg.name) { + out = write<Char>(out, arg.value); + return true; + } + } + return false; + } + + template <typename OutputIt, typename... Args> + 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 <typename Char> +struct is_compiled_format<runtime_named_field<Char>> : std::true_type {}; + +// A replacement field that refers to argument N and has format specifiers. +template <typename Char, typename T, int N> struct spec_field { + using char_type = Char; + formatter<T, Char> fmt; + + template <typename OutputIt, typename... Args> + constexpr FMT_INLINE OutputIt format(OutputIt out, + const Args&... args) const { + const auto& vargs = + fmt::make_format_args<basic_format_context<OutputIt, Char>>(args...); + basic_format_context<OutputIt, Char> ctx(out, vargs); + return fmt.format(get_arg_checked<T, N>(args...), ctx); + } +}; + +template <typename Char, typename T, int N> +struct is_compiled_format<spec_field<Char, T, N>> : std::true_type {}; + +template <typename L, typename R> struct concat { + L lhs; + R rhs; + using char_type = typename L::char_type; + + template <typename OutputIt, typename... Args> + constexpr OutputIt format(OutputIt out, const Args&... args) const { + out = lhs.format(out, args...); + return rhs.format(out, args...); + } +}; + +template <typename L, typename R> +struct is_compiled_format<concat<L, R>> : std::true_type {}; + +template <typename L, typename R> +constexpr concat<L, R> make_concat(L lhs, R rhs) { + return {lhs, rhs}; +} + +struct unknown_format {}; + +template <typename Char> +constexpr size_t parse_text(basic_string_view<Char> str, size_t pos) { + for (size_t size = str.size(); pos != size; ++pos) { + if (str[pos] == '{' || str[pos] == '}') break; + } + return pos; +} + +template <typename Args, size_t POS, int ID, typename S> +constexpr auto compile_format_string(S format_str); + +template <typename Args, size_t POS, int ID, typename T, typename S> +constexpr auto parse_tail(T head, S format_str) { + if constexpr (POS != + basic_string_view<typename S::char_type>(format_str).size()) { + constexpr auto tail = compile_format_string<Args, POS, ID>(format_str); + if constexpr (std::is_same<remove_cvref_t<decltype(tail)>, + unknown_format>()) + return tail; + else + return make_concat(head, tail); + } else { + return head; + } +} + +template <typename T, typename Char> struct parse_specs_result { + formatter<T, Char> fmt; + size_t end; + int next_arg_id; +}; + +constexpr int manual_indexing_id = -1; + +template <typename T, typename Char> +constexpr parse_specs_result<T, Char> parse_specs(basic_string_view<Char> str, + size_t pos, int next_arg_id) { + str.remove_prefix(pos); + auto ctx = basic_format_parse_context<Char>(str, {}, next_arg_id); + auto f = formatter<T, Char>(); + auto end = f.parse(ctx); + return {f, pos + fmt::detail::to_unsigned(end - str.data()) + 1, + next_arg_id == 0 ? manual_indexing_id : ctx.next_arg_id()}; +} + +template <typename Char> struct arg_id_handler { + arg_ref<Char> arg_id; + + constexpr int operator()() { + FMT_ASSERT(false, "handler cannot be used with automatic indexing"); + return 0; + } + constexpr int operator()(int id) { + arg_id = arg_ref<Char>(id); + return 0; + } + constexpr int operator()(basic_string_view<Char> id) { + arg_id = arg_ref<Char>(id); + return 0; + } + + constexpr void on_error(const char* message) { + FMT_THROW(format_error(message)); + } +}; + +template <typename Char> struct parse_arg_id_result { + arg_ref<Char> arg_id; + const Char* arg_id_end; +}; + +template <int ID, typename Char> +constexpr auto parse_arg_id(const Char* begin, const Char* end) { + auto handler = arg_id_handler<Char>{arg_ref<Char>{}}; + auto arg_id_end = parse_arg_id(begin, end, handler); + return parse_arg_id_result<Char>{handler.arg_id, arg_id_end}; +} + +template <typename T, typename Enable = void> struct field_type { + using type = remove_cvref_t<T>; +}; + +template <typename T> +struct field_type<T, enable_if_t<detail::is_named_arg<T>::value>> { + using type = remove_cvref_t<decltype(T::value)>; +}; + +template <typename T, typename Args, size_t END_POS, int ARG_INDEX, int NEXT_ID, + typename S> +constexpr auto parse_replacement_field_then_tail(S format_str) { + using char_type = typename S::char_type; + constexpr auto str = basic_string_view<char_type>(format_str); + constexpr char_type c = END_POS != str.size() ? str[END_POS] : char_type(); + if constexpr (c == '}') { + return parse_tail<Args, END_POS + 1, NEXT_ID>( + field<char_type, typename field_type<T>::type, ARG_INDEX>(), + format_str); + } else if constexpr (c == ':') { + constexpr auto result = parse_specs<typename field_type<T>::type>( + str, END_POS + 1, NEXT_ID == manual_indexing_id ? 0 : NEXT_ID); + return parse_tail<Args, result.end, result.next_arg_id>( + spec_field<char_type, typename field_type<T>::type, ARG_INDEX>{ + result.fmt}, + format_str); + } +} + +// Compiles a non-empty format string and returns the compiled representation +// or unknown_format() on unrecognized input. +template <typename Args, size_t POS, int ID, typename S> +constexpr auto compile_format_string(S format_str) { + using char_type = typename S::char_type; + constexpr auto str = basic_string_view<char_type>(format_str); + 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<Args, POS + 2, ID>(make_text(str, POS, 1), format_str); + } 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<get_type<ID, Args>, Args, + POS + 1, ID, next_id>( + format_str); + } else { + constexpr auto arg_id_result = + parse_arg_id<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<get_type<arg_index, Args>, + Args, arg_id_end_pos, + arg_index, manual_indexing_id>( + format_str); + } 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 != invalid_arg_index) { + constexpr auto next_id = + ID != manual_indexing_id ? ID + 1 : manual_indexing_id; + return parse_replacement_field_then_tail< + decltype(get_type<arg_index, Args>::value), Args, arg_id_end_pos, + arg_index, next_id>(format_str); + } else { + if constexpr (c == '}') { + return parse_tail<Args, arg_id_end_pos + 1, ID>( + runtime_named_field<char_type>{arg_id_result.arg_id.val.name}, + format_str); + } 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<Args, POS + 2, ID>(make_text(str, POS, 1), format_str); + } else { + constexpr auto end = parse_text(str, POS + 1); + if constexpr (end - POS > 1) { + return parse_tail<Args, end, ID>(make_text(str, POS, end - POS), + format_str); + } else { + return parse_tail<Args, end, ID>(code_unit<char_type>{str[POS]}, + format_str); + } + } +} + +template <typename... Args, typename S, + FMT_ENABLE_IF(detail::is_compiled_string<S>::value)> +constexpr auto compile(S format_str) { + constexpr auto str = basic_string_view<typename S::char_type>(format_str); + if constexpr (str.size() == 0) { + return detail::make_text(str, 0, 0); + } else { + constexpr auto result = + detail::compile_format_string<detail::type_list<Args...>, 0, 0>( + format_str); + return result; + } +} +#endif // defined(__cpp_if_constexpr) && defined(__cpp_return_type_deduction) +} // namespace detail + +FMT_MODULE_EXPORT_BEGIN + +#if defined(__cpp_if_constexpr) && defined(__cpp_return_type_deduction) + +template <typename CompiledFormat, typename... Args, + typename Char = typename CompiledFormat::char_type, + FMT_ENABLE_IF(detail::is_compiled_format<CompiledFormat>::value)> +FMT_INLINE std::basic_string<Char> format(const CompiledFormat& cf, + const Args&... args) { + auto s = std::basic_string<Char>(); + cf.format(std::back_inserter(s), args...); + return s; +} + +template <typename OutputIt, typename CompiledFormat, typename... Args, + FMT_ENABLE_IF(detail::is_compiled_format<CompiledFormat>::value)> +constexpr FMT_INLINE OutputIt format_to(OutputIt out, const CompiledFormat& cf, + const Args&... args) { + return cf.format(out, args...); +} + +template <typename S, typename... Args, + FMT_ENABLE_IF(detail::is_compiled_string<S>::value)> +FMT_INLINE std::basic_string<typename S::char_type> format(const S&, + Args&&... args) { + if constexpr (std::is_same<typename S::char_type, char>::value) { + constexpr auto str = basic_string_view<typename S::char_type>(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<decltype(first)>>::value) { + return fmt::to_string(first.value); + } else { + return fmt::to_string(first); + } + } + } + constexpr auto compiled = detail::compile<Args...>(S()); + if constexpr (std::is_same<remove_cvref_t<decltype(compiled)>, + detail::unknown_format>()) { + return format(static_cast<basic_string_view<typename S::char_type>>(S()), + std::forward<Args>(args)...); + } else { + return format(compiled, std::forward<Args>(args)...); + } +} + +template <typename OutputIt, typename S, typename... Args, + FMT_ENABLE_IF(detail::is_compiled_string<S>::value)> +FMT_CONSTEXPR OutputIt format_to(OutputIt out, const S&, Args&&... args) { + constexpr auto compiled = detail::compile<Args...>(S()); + if constexpr (std::is_same<remove_cvref_t<decltype(compiled)>, + detail::unknown_format>()) { + return format_to(out, + static_cast<basic_string_view<typename S::char_type>>(S()), + std::forward<Args>(args)...); + } else { + return format_to(out, compiled, std::forward<Args>(args)...); + } +} +#endif + +template <typename OutputIt, typename S, typename... Args, + FMT_ENABLE_IF(detail::is_compiled_string<S>::value)> +format_to_n_result<OutputIt> format_to_n(OutputIt out, size_t n, + const S& format_str, Args&&... args) { + auto it = format_to(detail::truncating_iterator<OutputIt>(out, n), format_str, + std::forward<Args>(args)...); + return {it.base(), it.count()}; +} + +template <typename S, typename... Args, + FMT_ENABLE_IF(detail::is_compiled_string<S>::value)> +size_t formatted_size(const S& format_str, const Args&... args) { + return format_to(detail::counting_iterator(), format_str, args...).count(); +} + +template <typename S, typename... Args, + FMT_ENABLE_IF(detail::is_compiled_string<S>::value)> +void print(std::FILE* f, const S& format_str, const Args&... args) { + memory_buffer buffer; + format_to(std::back_inserter(buffer), format_str, args...); + detail::print(f, {buffer.data(), buffer.size()}); +} + +template <typename S, typename... Args, + FMT_ENABLE_IF(detail::is_compiled_string<S>::value)> +void print(const S& format_str, const Args&... args) { + print(stdout, format_str, args...); +} + +#if FMT_USE_NONTYPE_TEMPLATE_PARAMETERS +inline namespace literals { +template <detail_exported::fixed_string Str> +constexpr detail::udl_compiled_string< + remove_cvref_t<decltype(Str.data[0])>, + sizeof(Str.data) / sizeof(decltype(Str.data[0])), Str> +operator""_cf() { + return {}; +} +} // namespace literals +#endif + +FMT_MODULE_EXPORT_END +FMT_END_NAMESPACE + +#endif // FMT_COMPILE_H_ diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/spdlog/fmt/bundled/core.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/spdlog/fmt/bundled/core.h new file mode 100644 index 0000000000000000000000000000000000000000..92a7aa1df69ba84553c987c591a1bac1ec187c88 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/spdlog/fmt/bundled/core.h @@ -0,0 +1,3236 @@ +// Formatting library for C++ - the core API for char/UTF-8 +// +// Copyright (c) 2012 - present, Victor Zverovich +// All rights reserved. +// +// For the license information refer to format.h. + +#ifndef FMT_CORE_H_ +#define FMT_CORE_H_ + +#include <cstddef> // std::byte +#include <cstdio> // std::FILE +#include <cstring> +#include <iterator> +#include <limits> +#include <string> +#include <type_traits> + +// The fmt library version in the form major * 10000 + minor * 100 + patch. +#define FMT_VERSION 80101 + +#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) && \ + !defined(__NVCOMPILER) +# define FMT_GCC_VERSION (__GNUC__ * 100 + __GNUC_MINOR__) +#else +# define FMT_GCC_VERSION 0 +#endif + +#ifndef FMT_GCC_PRAGMA +// Workaround _Pragma bug https://gcc.gnu.org/bugzilla/show_bug.cgi?id=59884. +# if FMT_GCC_VERSION >= 504 +# define FMT_GCC_PRAGMA(arg) _Pragma(arg) +# else +# define FMT_GCC_PRAGMA(arg) +# endif +#endif + +#ifdef __ICL +# define FMT_ICC_VERSION __ICL +#elif defined(__INTEL_COMPILER) +# define FMT_ICC_VERSION __INTEL_COMPILER +#else +# define FMT_ICC_VERSION 0 +#endif + +#ifdef __NVCC__ +# define FMT_NVCC __NVCC__ +#else +# define FMT_NVCC 0 +#endif + +#ifdef _MSC_VER +# define FMT_MSC_VER _MSC_VER +# define FMT_MSC_WARNING(...) __pragma(warning(__VA_ARGS__)) +#else +# define FMT_MSC_VER 0 +# define FMT_MSC_WARNING(...) +#endif + +#ifdef __has_feature +# define FMT_HAS_FEATURE(x) __has_feature(x) +#else +# define FMT_HAS_FEATURE(x) 0 +#endif + +#if defined(__has_include) && \ + (!defined(__INTELLISENSE__) || FMT_MSC_VER > 1900) && \ + (!FMT_ICC_VERSION || FMT_ICC_VERSION >= 1600) +# 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 + +#ifdef _MSVC_LANG +# define FMT_CPLUSPLUS _MSVC_LANG +#else +# define FMT_CPLUSPLUS __cplusplus +#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)) + +// Check if relaxed C++14 constexpr is supported. +// GCC doesn't allow throw in constexpr until version 6 (bug 67371). +#ifndef FMT_USE_CONSTEXPR +# define FMT_USE_CONSTEXPR \ + (FMT_HAS_FEATURE(cxx_relaxed_constexpr) || FMT_MSC_VER >= 1912 || \ + (FMT_GCC_VERSION >= 600 && __cplusplus >= 201402L)) && \ + !FMT_NVCC && !FMT_ICC_VERSION +#endif +#if FMT_USE_CONSTEXPR +# define FMT_CONSTEXPR constexpr +# define FMT_CONSTEXPR_DECL constexpr +#else +# define FMT_CONSTEXPR +# define FMT_CONSTEXPR_DECL +#endif + +#if ((__cplusplus >= 202002L) && \ + (!defined(_GLIBCXX_RELEASE) || _GLIBCXX_RELEASE > 9)) || \ + (__cplusplus >= 201709L && FMT_GCC_VERSION >= 1002) +# define FMT_CONSTEXPR20 constexpr +#else +# define FMT_CONSTEXPR20 +#endif + +// Check if constexpr std::char_traits<>::compare,length is supported. +#if defined(__GLIBCXX__) +# if __cplusplus >= 201703L && defined(_GLIBCXX_RELEASE) && \ + _GLIBCXX_RELEASE >= 7 // GCC 7+ libstdc++ has _GLIBCXX_RELEASE. +# define FMT_CONSTEXPR_CHAR_TRAITS constexpr +# endif +#elif defined(_LIBCPP_VERSION) && __cplusplus >= 201703L && \ + _LIBCPP_VERSION >= 4000 +# define FMT_CONSTEXPR_CHAR_TRAITS constexpr +#elif FMT_MSC_VER >= 1914 && _MSVC_LANG >= 201703L +# define FMT_CONSTEXPR_CHAR_TRAITS constexpr +#endif +#ifndef FMT_CONSTEXPR_CHAR_TRAITS +# define FMT_CONSTEXPR_CHAR_TRAITS +#endif + +// Check if exceptions are disabled. +#ifndef FMT_EXCEPTIONS +# if (defined(__GNUC__) && !defined(__EXCEPTIONS)) || \ + FMT_MSC_VER && !_HAS_EXCEPTIONS +# define FMT_EXCEPTIONS 0 +# else +# define FMT_EXCEPTIONS 1 +# endif +#endif + +// Define FMT_USE_NOEXCEPT to make fmt use noexcept (C++11 feature). +#ifndef FMT_USE_NOEXCEPT +# define FMT_USE_NOEXCEPT 0 +#endif + +#if FMT_USE_NOEXCEPT || FMT_HAS_FEATURE(cxx_noexcept) || \ + FMT_GCC_VERSION >= 408 || FMT_MSC_VER >= 1900 +# define FMT_DETECTED_NOEXCEPT noexcept +# define FMT_HAS_CXX11_NOEXCEPT 1 +#else +# define FMT_DETECTED_NOEXCEPT throw() +# define FMT_HAS_CXX11_NOEXCEPT 0 +#endif + +#ifndef FMT_NOEXCEPT +# if FMT_EXCEPTIONS || FMT_HAS_CXX11_NOEXCEPT +# define FMT_NOEXCEPT FMT_DETECTED_NOEXCEPT +# else +# define FMT_NOEXCEPT +# endif +#endif + +// [[noreturn]] is disabled on MSVC and NVCC because of bogus unreachable code +// warnings. +#if FMT_EXCEPTIONS && FMT_HAS_CPP_ATTRIBUTE(noreturn) && !FMT_MSC_VER && \ + !FMT_NVCC +# define FMT_NORETURN [[noreturn]] +#else +# define FMT_NORETURN +#endif + +#if __cplusplus == 201103L || __cplusplus == 201402L +# if defined(__INTEL_COMPILER) || defined(__PGI) +# define FMT_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 +#elif FMT_HAS_CPP17_ATTRIBUTE(fallthrough) +# define FMT_FALLTHROUGH [[fallthrough]] +#else +# define FMT_FALLTHROUGH +#endif + +#ifndef FMT_NODISCARD +# if FMT_HAS_CPP17_ATTRIBUTE(nodiscard) +# define FMT_NODISCARD [[nodiscard]] +# else +# define FMT_NODISCARD +# endif +#endif + +#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 + +#ifndef FMT_INLINE +# if FMT_GCC_VERSION || FMT_CLANG_VERSION +# define FMT_INLINE inline __attribute__((always_inline)) +# else +# define FMT_INLINE inline +# endif +#endif + +#ifndef FMT_DEPRECATED +# if FMT_HAS_CPP14_ATTRIBUTE(deprecated) || FMT_MSC_VER >= 1900 +# define FMT_DEPRECATED [[deprecated]] +# else +# if (defined(__GNUC__) && !defined(__LCC__)) || defined(__clang__) +# define FMT_DEPRECATED __attribute__((deprecated)) +# elif FMT_MSC_VER +# define FMT_DEPRECATED __declspec(deprecated) +# else +# define FMT_DEPRECATED /* deprecated */ +# endif +# endif +#endif + +#ifndef FMT_BEGIN_NAMESPACE +# define FMT_BEGIN_NAMESPACE \ + namespace fmt { \ + inline namespace v8 { +# define FMT_END_NAMESPACE \ + } \ + } +#endif + +#ifndef FMT_MODULE_EXPORT +# define FMT_MODULE_EXPORT +# define FMT_MODULE_EXPORT_BEGIN +# define FMT_MODULE_EXPORT_END +# define FMT_BEGIN_DETAIL_NAMESPACE namespace detail { +# define FMT_END_DETAIL_NAMESPACE } +#endif + +#if !defined(FMT_HEADER_ONLY) && defined(_WIN32) +# define FMT_CLASS_API FMT_MSC_WARNING(suppress : 4275) +# ifdef FMT_EXPORT +# define FMT_API __declspec(dllexport) +# elif defined(FMT_SHARED) +# define FMT_API __declspec(dllimport) +# endif +#else +# define FMT_CLASS_API +# if defined(FMT_EXPORT) || defined(FMT_SHARED) +# if defined(__GNUC__) || defined(__clang__) +# define FMT_API __attribute__((visibility("default"))) +# endif +# endif +#endif +#ifndef FMT_API +# define FMT_API +#endif + +// libc++ supports string_view in pre-c++17. +#if (FMT_HAS_INCLUDE(<string_view>) && \ + (__cplusplus > 201402L || defined(_LIBCPP_VERSION))) || \ + (defined(_MSVC_LANG) && _MSVC_LANG > 201402L && _MSC_VER >= 1910) +# include <string_view> +# define FMT_USE_STRING_VIEW +#elif FMT_HAS_INCLUDE("experimental/string_view") && __cplusplus >= 201402L +# include <experimental/string_view> +# define FMT_USE_EXPERIMENTAL_STRING_VIEW +#endif + +#ifndef FMT_UNICODE +# define FMT_UNICODE !FMT_MSC_VER +#endif + +#ifndef FMT_CONSTEVAL +# if ((FMT_GCC_VERSION >= 1000 || FMT_CLANG_VERSION >= 1101) && \ + __cplusplus > 201703L && !defined(__apple_build_version__)) || \ + (defined(__cpp_consteval) && \ + (!FMT_MSC_VER || _MSC_FULL_VER >= 193030704)) +// consteval is broken in MSVC before VS2022 and Apple clang 13. +# define FMT_CONSTEVAL consteval +# define FMT_HAS_CONSTEVAL +# else +# define FMT_CONSTEVAL +# endif +#endif + +#ifndef FMT_USE_NONTYPE_TEMPLATE_PARAMETERS +# if defined(__cpp_nontype_template_args) && \ + ((FMT_GCC_VERSION >= 903 && __cplusplus >= 201709L) || \ + __cpp_nontype_template_args >= 201911L) +# define FMT_USE_NONTYPE_TEMPLATE_PARAMETERS 1 +# else +# define FMT_USE_NONTYPE_TEMPLATE_PARAMETERS 0 +# endif +#endif + +// Enable minimal optimizations for more compact code in debug mode. +FMT_GCC_PRAGMA("GCC push_options") +#ifndef __OPTIMIZE__ +FMT_GCC_PRAGMA("GCC optimize(\"Og\")") +#endif + +FMT_BEGIN_NAMESPACE +FMT_MODULE_EXPORT_BEGIN + +// Implementations of enable_if_t and other metafunctions for older systems. +template <bool B, typename T = void> +using enable_if_t = typename std::enable_if<B, T>::type; +template <bool B, typename T, typename F> +using conditional_t = typename std::conditional<B, T, F>::type; +template <bool B> using bool_constant = std::integral_constant<bool, B>; +template <typename T> +using remove_reference_t = typename std::remove_reference<T>::type; +template <typename T> +using remove_const_t = typename std::remove_const<T>::type; +template <typename T> +using remove_cvref_t = typename std::remove_cv<remove_reference_t<T>>::type; +template <typename T> struct type_identity { using type = T; }; +template <typename T> using type_identity_t = typename type_identity<T>::type; + +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(...) enable_if_t<(__VA_ARGS__), int> = 0 +#endif + +FMT_BEGIN_DETAIL_NAMESPACE + +// Suppress "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 <typename... T> FMT_CONSTEXPR void ignore_unused(const T&...) {} + +constexpr FMT_INLINE auto is_constant_evaluated(bool default_value = false) + FMT_NOEXCEPT -> bool { +#ifdef __cpp_lib_is_constant_evaluated + ignore_unused(default_value); + return std::is_constant_evaluated(); +#else + return default_value; +#endif +} + +// A function to suppress "conditional expression is constant" warnings. +template <typename T> constexpr FMT_INLINE auto const_check(T value) -> T { + return value; +} + +FMT_NORETURN FMT_API void assert_fail(const char* file, int line, + const char* message); + +#ifndef FMT_ASSERT +# ifdef NDEBUG +// FMT_ASSERT is not empty to avoid -Werror=empty-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 +#endif + +#ifdef __cpp_lib_byte +using byte = std::byte; +#else +enum class byte : unsigned char {}; +#endif + +#if defined(FMT_USE_STRING_VIEW) +template <typename Char> using std_string_view = std::basic_string_view<Char>; +#elif defined(FMT_USE_EXPERIMENTAL_STRING_VIEW) +template <typename Char> +using std_string_view = std::experimental::basic_string_view<Char>; +#else +template <typename T> struct std_string_view {}; +#endif + +#ifdef FMT_USE_INT128 +// Do nothing. +#elif defined(__SIZEOF_INT128__) && !FMT_NVCC && \ + !(FMT_CLANG_VERSION && FMT_MSC_VER) +# define FMT_USE_INT128 1 +using int128_t = __int128_t; +using uint128_t = __uint128_t; +template <typename T> inline auto convert_for_visit(T value) -> T { + return value; +} +#else +# define FMT_USE_INT128 0 +#endif +#if !FMT_USE_INT128 +enum class int128_t {}; +enum class uint128_t {}; +// Reduce template instantiations. +template <typename T> inline auto convert_for_visit(T) -> monostate { + return {}; +} +#endif + +// Casts a nonnegative integer to unsigned. +template <typename Int> +FMT_CONSTEXPR auto to_unsigned(Int value) -> + typename std::make_unsigned<Int>::type { + FMT_ASSERT(value >= 0, "negative value"); + return static_cast<typename std::make_unsigned<Int>::type>(value); +} + +FMT_MSC_WARNING(suppress : 4566) constexpr unsigned char micro[] = "\u00B5"; + +constexpr auto is_utf8() -> bool { + // Avoid buggy sign extensions in MSVC's constant evaluation mode. + // https://developercommunity.visualstudio.com/t/C-difference-in-behavior-for-unsigned/1233612 + using uchar = unsigned char; + return FMT_UNICODE || (sizeof(micro) == 3 && uchar(micro[0]) == 0xC2 && + uchar(micro[1]) == 0xB5); +} +FMT_END_DETAIL_NAMESPACE + +/** + 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::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). + */ +template <typename Char> class basic_string_view { + private: + const Char* data_; + size_t size_; + + public: + using value_type = Char; + using iterator = const Char*; + + constexpr basic_string_view() FMT_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) FMT_NOEXCEPT + : data_(s), + size_(count) {} + + /** + \rst + Constructs a string reference object from a C string computing + the size with ``std::char_traits<Char>::length``. + \endrst + */ + FMT_CONSTEXPR_CHAR_TRAITS + FMT_INLINE + basic_string_view(const Char* s) + : data_(s), + size_(detail::const_check(std::is_same<Char, char>::value && + !detail::is_constant_evaluated(true)) + ? std::strlen(reinterpret_cast<const char*>(s)) + : std::char_traits<Char>::length(s)) {} + + /** Constructs a string reference from a ``std::basic_string`` object. */ + template <typename Traits, typename Alloc> + FMT_CONSTEXPR basic_string_view( + const std::basic_string<Char, Traits, Alloc>& s) FMT_NOEXCEPT + : data_(s.data()), + size_(s.size()) {} + + template <typename S, FMT_ENABLE_IF(std::is_same< + S, detail::std_string_view<Char>>::value)> + FMT_CONSTEXPR basic_string_view(S s) FMT_NOEXCEPT : data_(s.data()), + size_(s.size()) {} + + /** Returns a pointer to the string data. */ + constexpr auto data() const FMT_NOEXCEPT -> const Char* { return data_; } + + /** Returns the string size. */ + constexpr auto size() const FMT_NOEXCEPT -> size_t { return size_; } + + constexpr auto begin() const FMT_NOEXCEPT -> iterator { return data_; } + constexpr auto end() const FMT_NOEXCEPT -> iterator { return data_ + size_; } + + constexpr auto operator[](size_t pos) const FMT_NOEXCEPT -> const Char& { + return data_[pos]; + } + + FMT_CONSTEXPR void remove_prefix(size_t n) FMT_NOEXCEPT { + data_ += n; + size_ -= n; + } + + // Lexicographically compare this string reference to other. + FMT_CONSTEXPR_CHAR_TRAITS auto compare(basic_string_view other) const -> int { + size_t str_size = size_ < other.size_ ? size_ : other.size_; + int result = std::char_traits<Char>::compare(data_, other.data_, str_size); + if (result == 0) + result = size_ == other.size_ ? 0 : (size_ < other.size_ ? -1 : 1); + return result; + } + + FMT_CONSTEXPR_CHAR_TRAITS 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; + } +}; + +using string_view = basic_string_view<char>; + +/** Specifies if ``T`` is a character type. Can be specialized by users. */ +template <typename T> struct is_char : std::false_type {}; +template <> struct is_char<char> : std::true_type {}; + +// Returns a string view of `s`. +template <typename Char, FMT_ENABLE_IF(is_char<Char>::value)> +FMT_INLINE auto to_string_view(const Char* s) -> basic_string_view<Char> { + return s; +} +template <typename Char, typename Traits, typename Alloc> +inline auto to_string_view(const std::basic_string<Char, Traits, Alloc>& s) + -> basic_string_view<Char> { + return s; +} +template <typename Char> +constexpr auto to_string_view(basic_string_view<Char> s) + -> basic_string_view<Char> { + return s; +} +template <typename Char, + FMT_ENABLE_IF(!std::is_empty<detail::std_string_view<Char>>::value)> +inline auto to_string_view(detail::std_string_view<Char> s) + -> basic_string_view<Char> { + return s; +} + +// A base class for compile-time strings. It is defined in the fmt namespace to +// make formatting functions visible via ADL, e.g. format(FMT_STRING("{}"), 42). +struct compile_string {}; + +template <typename S> +struct is_compile_string : std::is_base_of<compile_string, S> {}; + +template <typename S, FMT_ENABLE_IF(is_compile_string<S>::value)> +constexpr auto to_string_view(const S& s) + -> basic_string_view<typename S::char_type> { + return basic_string_view<typename S::char_type>(s); +} + +FMT_BEGIN_DETAIL_NAMESPACE + +void to_string_view(...); +using fmt::to_string_view; + +// Specifies whether S is a string type convertible to fmt::basic_string_view. +// It should be a constexpr function but MSVC 2017 fails to compile it in +// enable_if and MSVC 2015 fails to compile it as an alias template. +template <typename S> +struct is_string : std::is_class<decltype(to_string_view(std::declval<S>()))> { +}; + +template <typename S, typename = void> struct char_t_impl {}; +template <typename S> struct char_t_impl<S, enable_if_t<is_string<S>::value>> { + using result = decltype(to_string_view(std::declval<S>())); + using type = typename result::value_type; +}; + +// Reports a compile-time error if S is not a valid format string. +template <typename..., typename S, FMT_ENABLE_IF(!is_compile_string<S>::value)> +FMT_INLINE void check_format_string(const S&) { +#ifdef FMT_ENFORCE_COMPILE_STRING + static_assert(is_compile_string<S>::value, + "FMT_ENFORCE_COMPILE_STRING requires all format strings to use " + "FMT_STRING."); +#endif +} +template <typename..., typename S, FMT_ENABLE_IF(is_compile_string<S>::value)> +void check_format_string(S); + +FMT_NORETURN FMT_API void throw_format_error(const char* message); + +struct error_handler { + constexpr error_handler() = default; + constexpr error_handler(const error_handler&) = default; + + // This function is intentionally not constexpr to give a compile-time error. + FMT_NORETURN FMT_API void on_error(const char* message); +}; +FMT_END_DETAIL_NAMESPACE + +/** String's character type. */ +template <typename S> using char_t = typename detail::char_t_impl<S>::type; + +/** + \rst + 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. + \endrst + */ +template <typename Char, typename ErrorHandler = detail::error_handler> +class basic_format_parse_context : private ErrorHandler { + private: + basic_string_view<Char> format_str_; + int next_arg_id_; + + public: + using char_type = Char; + using iterator = typename basic_string_view<Char>::iterator; + + explicit constexpr basic_format_parse_context( + basic_string_view<Char> format_str, ErrorHandler eh = {}, + int next_arg_id = 0) + : ErrorHandler(eh), 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 FMT_NOEXCEPT -> iterator { + return format_str_.begin(); + } + + /** + Returns an iterator past the end of the format string range being parsed. + */ + constexpr auto end() const FMT_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 { + // Don't check if the argument id is valid to avoid overhead and because it + // will be checked during formatting anyway. + if (next_arg_id_ >= 0) return next_arg_id_++; + on_error("cannot switch from manual to automatic argument indexing"); + return 0; + } + + /** + Reports an error if using the automatic argument indexing; otherwise + switches to the manual indexing. + */ + FMT_CONSTEXPR void check_arg_id(int) { + if (next_arg_id_ > 0) + on_error("cannot switch from automatic to manual argument indexing"); + else + next_arg_id_ = -1; + } + + FMT_CONSTEXPR void check_arg_id(basic_string_view<Char>) {} + + FMT_CONSTEXPR void on_error(const char* message) { + ErrorHandler::on_error(message); + } + + constexpr auto error_handler() const -> ErrorHandler { return *this; } +}; + +using format_parse_context = basic_format_parse_context<char>; + +template <typename Context> class basic_format_arg; +template <typename Context> class basic_format_args; +template <typename Context> class dynamic_format_arg_store; + +// A formatter for objects of type T. +template <typename T, typename Char = char, typename Enable = void> +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 <typename T, typename Context> +using has_formatter = + std::is_constructible<typename Context::template formatter_type<T>>; + +// Checks whether T is a container with contiguous storage. +template <typename T> struct is_contiguous : std::false_type {}; +template <typename Char> +struct is_contiguous<std::basic_string<Char>> : std::true_type {}; + +class appender; + +FMT_BEGIN_DETAIL_NAMESPACE + +template <typename Context, typename T> +constexpr auto has_const_formatter_impl(T*) + -> decltype(typename Context::template formatter_type<T>().format( + std::declval<const T&>(), std::declval<Context&>()), + true) { + return true; +} +template <typename Context> +constexpr auto has_const_formatter_impl(...) -> bool { + return false; +} +template <typename T, typename Context> +constexpr auto has_const_formatter() -> bool { + return has_const_formatter_impl<Context>(static_cast<T*>(nullptr)); +} + +// Extracts a reference to the container from back_insert_iterator. +template <typename Container> +inline auto get_container(std::back_insert_iterator<Container> it) + -> Container& { + using bi_iterator = std::back_insert_iterator<Container>; + struct accessor : bi_iterator { + accessor(bi_iterator iter) : bi_iterator(iter) {} + using bi_iterator::container; + }; + return *accessor(it).container; +} + +template <typename Char, typename InputIt, typename OutputIt> +FMT_CONSTEXPR auto copy_str(InputIt begin, InputIt end, OutputIt out) + -> OutputIt { + while (begin != end) *out++ = static_cast<Char>(*begin++); + return out; +} + +template <typename Char, typename T, typename U, + FMT_ENABLE_IF( + std::is_same<remove_const_t<T>, U>::value&& is_char<U>::value)> +FMT_CONSTEXPR auto copy_str(T* begin, T* end, U* out) -> U* { + if (is_constant_evaluated()) return copy_str<Char, T*, U*>(begin, end, out); + auto size = to_unsigned(end - begin); + memcpy(out, begin, size * sizeof(U)); + return out + size; +} + +/** + \rst + A contiguous memory buffer with an optional growing ability. It is an internal + class and shouldn't be used directly, only via `~fmt::basic_memory_buffer`. + \endrst + */ +template <typename T> class buffer { + private: + T* ptr_; + size_t size_; + size_t capacity_; + + protected: + // Don't initialize ptr_ since it is not accessed to save a few cycles. + FMT_MSC_WARNING(suppress : 26495) + buffer(size_t sz) FMT_NOEXCEPT : size_(sz), capacity_(sz) {} + + FMT_CONSTEXPR20 buffer(T* p = nullptr, size_t sz = 0, + size_t cap = 0) FMT_NOEXCEPT : ptr_(p), + size_(sz), + capacity_(cap) {} + + FMT_CONSTEXPR20 ~buffer() = default; + buffer(buffer&&) = default; + + /** Sets the buffer data and capacity. */ + FMT_CONSTEXPR void set(T* buf_data, size_t buf_capacity) FMT_NOEXCEPT { + ptr_ = buf_data; + capacity_ = buf_capacity; + } + + /** Increases the buffer capacity to hold at least *capacity* elements. */ + virtual FMT_CONSTEXPR20 void grow(size_t capacity) = 0; + + public: + using value_type = T; + using const_reference = const T&; + + buffer(const buffer&) = delete; + void operator=(const buffer&) = delete; + + auto begin() FMT_NOEXCEPT -> T* { return ptr_; } + auto end() FMT_NOEXCEPT -> T* { return ptr_ + size_; } + + auto begin() const FMT_NOEXCEPT -> const T* { return ptr_; } + auto end() const FMT_NOEXCEPT -> const T* { return ptr_ + size_; } + + /** Returns the size of this buffer. */ + constexpr auto size() const FMT_NOEXCEPT -> size_t { return size_; } + + /** Returns the capacity of this buffer. */ + constexpr auto capacity() const FMT_NOEXCEPT -> size_t { return capacity_; } + + /** Returns a pointer to the buffer data. */ + FMT_CONSTEXPR auto data() FMT_NOEXCEPT -> T* { return ptr_; } + + /** Returns a pointer to the buffer data. */ + FMT_CONSTEXPR auto data() const FMT_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_CONSTEXPR20 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_CONSTEXPR20 void try_reserve(size_t new_capacity) { + if (new_capacity > capacity_) grow(new_capacity); + } + + FMT_CONSTEXPR20 void push_back(const T& value) { + try_reserve(size_ + 1); + ptr_[size_++] = value; + } + + /** Appends data to the end of the buffer. */ + template <typename U> void append(const U* begin, const U* end); + + template <typename I> FMT_CONSTEXPR auto operator[](I index) -> T& { + return ptr_[index]; + } + template <typename I> + FMT_CONSTEXPR auto operator[](I 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 <typename OutputIt, typename T, typename Traits = buffer_traits> +class iterator_buffer final : public Traits, public buffer<T> { + private: + OutputIt out_; + enum { buffer_size = 256 }; + T data_[buffer_size]; + + protected: + FMT_CONSTEXPR20 void grow(size_t) override { + if (this->size() == buffer_size) flush(); + } + + void flush() { + auto size = this->size(); + this->clear(); + out_ = copy_str<T>(data_, data_ + this->limit(size), out_); + } + + public: + explicit iterator_buffer(OutputIt out, size_t n = buffer_size) + : Traits(n), buffer<T>(data_, 0, buffer_size), out_(out) {} + iterator_buffer(iterator_buffer&& other) + : Traits(other), buffer<T>(data_, 0, buffer_size), out_(other.out_) {} + ~iterator_buffer() { flush(); } + + auto out() -> OutputIt { + flush(); + return out_; + } + auto count() const -> size_t { return Traits::count() + this->size(); } +}; + +template <typename T> +class iterator_buffer<T*, T, fixed_buffer_traits> final + : public fixed_buffer_traits, + public buffer<T> { + private: + T* out_; + enum { buffer_size = 256 }; + T data_[buffer_size]; + + protected: + FMT_CONSTEXPR20 void grow(size_t) override { + if (this->size() == this->capacity()) 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<T>(out, 0, n), out_(out) {} + iterator_buffer(iterator_buffer&& other) + : fixed_buffer_traits(other), + buffer<T>(std::move(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 <typename T> class iterator_buffer<T*, T> final : public buffer<T> { + protected: + FMT_CONSTEXPR20 void grow(size_t) override {} + + public: + explicit iterator_buffer(T* out, size_t = 0) : buffer<T>(out, 0, ~size_t()) {} + + auto out() -> T* { return &*this->end(); } +}; + +// A buffer that writes to a container with the contiguous storage. +template <typename Container> +class iterator_buffer<std::back_insert_iterator<Container>, + enable_if_t<is_contiguous<Container>::value, + typename Container::value_type>> + final : public buffer<typename Container::value_type> { + private: + Container& container_; + + protected: + FMT_CONSTEXPR20 void grow(size_t capacity) override { + container_.resize(capacity); + this->set(&container_[0], capacity); + } + + public: + explicit iterator_buffer(Container& c) + : buffer<typename Container::value_type>(c.size()), container_(c) {} + explicit iterator_buffer(std::back_insert_iterator<Container> out, size_t = 0) + : iterator_buffer(get_container(out)) {} + auto out() -> std::back_insert_iterator<Container> { + return std::back_inserter(container_); + } +}; + +// A buffer that counts the number of code units written discarding the output. +template <typename T = char> class counting_buffer final : public buffer<T> { + private: + enum { buffer_size = 256 }; + T data_[buffer_size]; + size_t count_ = 0; + + protected: + FMT_CONSTEXPR20 void grow(size_t) override { + if (this->size() != buffer_size) return; + count_ += this->size(); + this->clear(); + } + + public: + counting_buffer() : buffer<T>(data_, 0, buffer_size) {} + + auto count() -> size_t { return count_ + this->size(); } +}; + +template <typename T> +using buffer_appender = conditional_t<std::is_same<T, char>::value, appender, + std::back_insert_iterator<buffer<T>>>; + +// Maps an output iterator to a buffer. +template <typename T, typename OutputIt> +auto get_buffer(OutputIt out) -> iterator_buffer<OutputIt, T> { + return iterator_buffer<OutputIt, T>(out); +} + +template <typename Buffer> +auto get_iterator(Buffer& buf) -> decltype(buf.out()) { + return buf.out(); +} +template <typename T> auto get_iterator(buffer<T>& buf) -> buffer_appender<T> { + return buffer_appender<T>(buf); +} + +template <typename T, typename Char = char, typename Enable = void> +struct fallback_formatter { + fallback_formatter() = delete; +}; + +// Specifies if T has an enabled fallback_formatter specialization. +template <typename T, typename Char> +using has_fallback_formatter = + std::is_constructible<fallback_formatter<T, Char>>; + +struct view {}; + +template <typename Char, typename T> struct named_arg : view { + const Char* name; + const T& value; + named_arg(const Char* n, const T& v) : name(n), value(v) {} +}; + +template <typename Char> struct named_arg_info { + const Char* name; + int id; +}; + +template <typename T, typename Char, size_t NUM_ARGS, size_t NUM_NAMED_ARGS> +struct arg_data { + // 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. + T args_[1 + (NUM_ARGS != 0 ? NUM_ARGS : +1)]; + named_arg_info<Char> named_args_[NUM_NAMED_ARGS]; + + template <typename... U> + arg_data(const U&... init) : args_{T(named_args_, NUM_NAMED_ARGS), init...} {} + arg_data(const arg_data& other) = delete; + auto args() const -> const T* { return args_ + 1; } + auto named_args() -> named_arg_info<Char>* { return named_args_; } +}; + +template <typename T, typename Char, size_t NUM_ARGS> +struct arg_data<T, Char, NUM_ARGS, 0> { + // +1 to workaround a bug in gcc 7.5 that causes duplicated-branches warning. + T args_[NUM_ARGS != 0 ? NUM_ARGS : +1]; + + template <typename... U> + FMT_CONSTEXPR FMT_INLINE arg_data(const U&... init) : args_{init...} {} + FMT_CONSTEXPR FMT_INLINE auto args() const -> const T* { return args_; } + FMT_CONSTEXPR FMT_INLINE auto named_args() -> std::nullptr_t { + return nullptr; + } +}; + +template <typename Char> +inline void init_named_args(named_arg_info<Char>*, int, int) {} + +template <typename T> struct is_named_arg : std::false_type {}; +template <typename T> struct is_statically_named_arg : std::false_type {}; + +template <typename T, typename Char> +struct is_named_arg<named_arg<Char, T>> : std::true_type {}; + +template <typename Char, typename T, typename... Tail, + FMT_ENABLE_IF(!is_named_arg<T>::value)> +void init_named_args(named_arg_info<Char>* named_args, int arg_count, + int named_arg_count, const T&, const Tail&... args) { + init_named_args(named_args, arg_count + 1, named_arg_count, args...); +} + +template <typename Char, typename T, typename... Tail, + FMT_ENABLE_IF(is_named_arg<T>::value)> +void init_named_args(named_arg_info<Char>* named_args, int arg_count, + int named_arg_count, const T& arg, const Tail&... args) { + named_args[named_arg_count++] = {arg.name, arg_count}; + init_named_args(named_args, arg_count + 1, named_arg_count, args...); +} + +template <typename... Args> +FMT_CONSTEXPR FMT_INLINE void init_named_args(std::nullptr_t, int, int, + const Args&...) {} + +template <bool B = false> constexpr auto count() -> size_t { return B ? 1 : 0; } +template <bool B1, bool B2, bool... Tail> constexpr auto count() -> size_t { + return (B1 ? 1 : 0) + count<B2, Tail...>(); +} + +template <typename... Args> constexpr auto count_named_args() -> size_t { + return count<is_named_arg<Args>::value...>(); +} + +template <typename... Args> +constexpr auto count_statically_named_args() -> size_t { + return count<is_statically_named_arg<Args>::value...>(); +} + +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 <typename T, typename Char> +struct type_constant : std::integral_constant<type, type::custom_type> {}; + +#define FMT_TYPE_CONSTANT(Type, constant) \ + template <typename Char> \ + struct type_constant<Type, Char> \ + : std::integral_constant<type, type::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_t, int128_type); +FMT_TYPE_CONSTANT(uint128_t, 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<Char>, string_type); +FMT_TYPE_CONSTANT(const void*, pointer_type); + +constexpr bool is_integral_type(type t) { + return t > type::none_type && t <= type::last_integer_type; +} + +constexpr bool is_arithmetic_type(type t) { + return t > type::none_type && t <= type::last_numeric_type; +} + +struct unformattable {}; +struct unformattable_char : unformattable {}; +struct unformattable_const : unformattable {}; +struct unformattable_pointer : unformattable {}; + +template <typename Char> struct string_value { + const Char* data; + size_t size; +}; + +template <typename Char> struct named_arg_value { + const named_arg_info<Char>* data; + size_t size; +}; + +template <typename Context> 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 <typename Context> 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_t int128_value; + uint128_t 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<char_type> string; + custom_value<Context> custom; + named_arg_value<char_type> named_args; + }; + + constexpr FMT_INLINE value() : no_value() {} + constexpr FMT_INLINE value(int val) : int_value(val) {} + constexpr FMT_INLINE value(unsigned val) : uint_value(val) {} + constexpr FMT_INLINE value(long long val) : long_long_value(val) {} + constexpr FMT_INLINE value(unsigned long long val) : ulong_long_value(val) {} + FMT_INLINE value(int128_t val) : int128_value(val) {} + FMT_INLINE value(uint128_t val) : uint128_value(val) {} + constexpr FMT_INLINE value(float val) : float_value(val) {} + constexpr FMT_INLINE value(double val) : double_value(val) {} + FMT_INLINE value(long double val) : long_double_value(val) {} + constexpr FMT_INLINE value(bool val) : bool_value(val) {} + constexpr FMT_INLINE value(char_type val) : char_value(val) {} + FMT_CONSTEXPR FMT_INLINE value(const char_type* val) { + string.data = val; + if (is_constant_evaluated()) string.size = {}; + } + FMT_CONSTEXPR FMT_INLINE value(basic_string_view<char_type> val) { + string.data = val.data(); + string.size = val.size(); + } + FMT_INLINE value(const void* val) : pointer(val) {} + FMT_INLINE value(const named_arg_info<char_type>* args, size_t size) + : named_args{args, size} {} + + template <typename T> FMT_CONSTEXPR FMT_INLINE value(T& val) { + using value_type = remove_cvref_t<T>; + custom.value = const_cast<value_type*>(&val); + // Get the formatter type through the context to allow different contexts + // have different extension points, e.g. `formatter<T>` for `format` and + // `printf_formatter<T>` for `printf`. + custom.format = format_custom_arg< + value_type, + conditional_t<has_formatter<value_type, Context>::value, + typename Context::template formatter_type<value_type>, + fallback_formatter<value_type, char_type>>>; + } + value(unformattable); + value(unformattable_char); + value(unformattable_const); + value(unformattable_pointer); + + private: + // Formats an argument of a custom type, such as a user-defined class. + template <typename T, typename Formatter> + 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<has_const_formatter<T, Context>(), const T, T>; + ctx.advance_to(f.format(*static_cast<qualified_type*>(arg), ctx)); + } +}; + +template <typename Context, typename T> +FMT_CONSTEXPR auto make_arg(const T& value) -> basic_format_arg<Context>; + +// 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<long_short, int, long long>; +using ulong_type = conditional_t<long_short, unsigned, unsigned long long>; + +// 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 <typename Context> struct arg_mapper { + using char_type = typename Context::char_type; + + FMT_CONSTEXPR FMT_INLINE auto map(signed char val) -> int { return val; } + FMT_CONSTEXPR FMT_INLINE auto map(unsigned char val) -> unsigned { + return val; + } + FMT_CONSTEXPR FMT_INLINE auto map(short val) -> int { return val; } + FMT_CONSTEXPR FMT_INLINE auto map(unsigned short val) -> unsigned { + return val; + } + FMT_CONSTEXPR FMT_INLINE auto map(int val) -> int { return val; } + FMT_CONSTEXPR FMT_INLINE auto map(unsigned val) -> unsigned { return val; } + FMT_CONSTEXPR FMT_INLINE auto map(long val) -> long_type { return val; } + FMT_CONSTEXPR FMT_INLINE auto map(unsigned long val) -> ulong_type { + return val; + } + FMT_CONSTEXPR FMT_INLINE auto map(long long val) -> long long { return val; } + FMT_CONSTEXPR FMT_INLINE auto map(unsigned long long val) + -> unsigned long long { + return val; + } + FMT_CONSTEXPR FMT_INLINE auto map(int128_t val) -> int128_t { return val; } + FMT_CONSTEXPR FMT_INLINE auto map(uint128_t val) -> uint128_t { return val; } + FMT_CONSTEXPR FMT_INLINE auto map(bool val) -> bool { return val; } + + template <typename T, FMT_ENABLE_IF(std::is_same<T, char>::value || + std::is_same<T, char_type>::value)> + FMT_CONSTEXPR FMT_INLINE auto map(T val) -> char_type { + return val; + } + template <typename T, enable_if_t<(std::is_same<T, wchar_t>::value || +#ifdef __cpp_char8_t + std::is_same<T, char8_t>::value || +#endif + std::is_same<T, char16_t>::value || + std::is_same<T, char32_t>::value) && + !std::is_same<T, char_type>::value, + int> = 0> + FMT_CONSTEXPR FMT_INLINE auto map(T) -> unformattable_char { + return {}; + } + + FMT_CONSTEXPR FMT_INLINE auto map(float val) -> float { return val; } + FMT_CONSTEXPR FMT_INLINE auto map(double val) -> double { return val; } + FMT_CONSTEXPR FMT_INLINE auto map(long double val) -> long double { + return val; + } + + FMT_CONSTEXPR FMT_INLINE auto map(char_type* val) -> const char_type* { + return val; + } + FMT_CONSTEXPR FMT_INLINE auto map(const char_type* val) -> const char_type* { + return val; + } + template <typename T, + FMT_ENABLE_IF(is_string<T>::value && !std::is_pointer<T>::value && + std::is_same<char_type, char_t<T>>::value)> + FMT_CONSTEXPR FMT_INLINE auto map(const T& val) + -> basic_string_view<char_type> { + return to_string_view(val); + } + template <typename T, + FMT_ENABLE_IF(is_string<T>::value && !std::is_pointer<T>::value && + !std::is_same<char_type, char_t<T>>::value)> + FMT_CONSTEXPR FMT_INLINE auto map(const T&) -> unformattable_char { + return {}; + } + template <typename T, + FMT_ENABLE_IF( + std::is_constructible<basic_string_view<char_type>, T>::value && + !is_string<T>::value && !has_formatter<T, Context>::value && + !has_fallback_formatter<T, char_type>::value)> + FMT_CONSTEXPR FMT_INLINE auto map(const T& val) + -> basic_string_view<char_type> { + return basic_string_view<char_type>(val); + } + template < + typename T, + FMT_ENABLE_IF( + std::is_constructible<std_string_view<char_type>, T>::value && + !std::is_constructible<basic_string_view<char_type>, T>::value && + !is_string<T>::value && !has_formatter<T, Context>::value && + !has_fallback_formatter<T, char_type>::value)> + FMT_CONSTEXPR FMT_INLINE auto map(const T& val) + -> basic_string_view<char_type> { + return std_string_view<char_type>(val); + } + + using cstring_result = conditional_t<std::is_same<char_type, char>::value, + const char*, unformattable_pointer>; + + FMT_DEPRECATED FMT_CONSTEXPR FMT_INLINE auto map(const signed char* val) + -> cstring_result { + return map(reinterpret_cast<const char*>(val)); + } + FMT_DEPRECATED FMT_CONSTEXPR FMT_INLINE auto map(const unsigned char* val) + -> cstring_result { + return map(reinterpret_cast<const char*>(val)); + } + FMT_DEPRECATED FMT_CONSTEXPR FMT_INLINE auto map(signed char* val) + -> cstring_result { + return map(reinterpret_cast<const char*>(val)); + } + FMT_DEPRECATED FMT_CONSTEXPR FMT_INLINE auto map(unsigned char* val) + -> cstring_result { + return map(reinterpret_cast<const char*>(val)); + } + + FMT_CONSTEXPR FMT_INLINE auto map(void* val) -> const void* { return val; } + FMT_CONSTEXPR FMT_INLINE auto map(const void* val) -> const void* { + return val; + } + FMT_CONSTEXPR FMT_INLINE auto map(std::nullptr_t val) -> const void* { + return val; + } + + // We use SFINAE instead of a const T* parameter to avoid conflicting with + // the C array overload. + template < + typename T, + FMT_ENABLE_IF( + std::is_member_pointer<T>::value || + std::is_function<typename std::remove_pointer<T>::type>::value || + (std::is_convertible<const T&, const void*>::value && + !std::is_convertible<const T&, const char_type*>::value))> + FMT_CONSTEXPR auto map(const T&) -> unformattable_pointer { + return {}; + } + + template <typename T, std::size_t N, + FMT_ENABLE_IF(!std::is_same<T, wchar_t>::value)> + FMT_CONSTEXPR FMT_INLINE auto map(const T (&values)[N]) -> const T (&)[N] { + return values; + } + + template <typename T, + FMT_ENABLE_IF( + std::is_enum<T>::value&& std::is_convertible<T, int>::value && + !has_formatter<T, Context>::value && + !has_fallback_formatter<T, char_type>::value)> + FMT_CONSTEXPR FMT_INLINE auto map(const T& val) + -> decltype(std::declval<arg_mapper>().map( + static_cast<typename std::underlying_type<T>::type>(val))) { + return map(static_cast<typename std::underlying_type<T>::type>(val)); + } + + FMT_CONSTEXPR FMT_INLINE auto map(detail::byte val) -> unsigned { + return map(static_cast<unsigned char>(val)); + } + + template <typename T, typename U = remove_cvref_t<T>> + struct formattable + : bool_constant<has_const_formatter<U, Context>() || + !std::is_const<remove_reference_t<T>>::value || + has_fallback_formatter<U, char_type>::value> {}; + +#if FMT_MSC_VER != 0 && FMT_MSC_VER < 1910 + // Workaround a bug in MSVC. + template <typename T> FMT_CONSTEXPR FMT_INLINE auto do_map(T&& val) -> T& { + return val; + } +#else + template <typename T, FMT_ENABLE_IF(formattable<T>::value)> + FMT_CONSTEXPR FMT_INLINE auto do_map(T&& val) -> T& { + return val; + } + template <typename T, FMT_ENABLE_IF(!formattable<T>::value)> + FMT_CONSTEXPR FMT_INLINE auto do_map(T&&) -> unformattable_const { + return {}; + } +#endif + + template <typename T, typename U = remove_cvref_t<T>, + FMT_ENABLE_IF(!is_string<U>::value && !is_char<U>::value && + !std::is_array<U>::value && + (has_formatter<U, Context>::value || + has_fallback_formatter<U, char_type>::value))> + FMT_CONSTEXPR FMT_INLINE auto map(T&& val) + -> decltype(this->do_map(std::forward<T>(val))) { + return do_map(std::forward<T>(val)); + } + + template <typename T, FMT_ENABLE_IF(is_named_arg<T>::value)> + FMT_CONSTEXPR FMT_INLINE auto map(const T& named_arg) + -> decltype(std::declval<arg_mapper>().map(named_arg.value)) { + return map(named_arg.value); + } + + auto map(...) -> unformattable { return {}; } +}; + +// A type constant after applying arg_mapper<Context>. +template <typename T, typename Context> +using mapped_type_constant = + type_constant<decltype(arg_mapper<Context>().map(std::declval<const T&>())), + 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 }; + +FMT_END_DETAIL_NAMESPACE + +// An output iterator that appends to a buffer. +// It is used to reduce symbol sizes for the common case. +class appender : public std::back_insert_iterator<detail::buffer<char>> { + using base = std::back_insert_iterator<detail::buffer<char>>; + + template <typename T> + friend auto get_buffer(appender out) -> detail::buffer<char>& { + return detail::get_container(out); + } + + public: + using std::back_insert_iterator<detail::buffer<char>>::back_insert_iterator; + appender(base it) FMT_NOEXCEPT : base(it) {} + using _Unchecked_type = appender; // Mark iterator as checked. + + auto operator++() FMT_NOEXCEPT -> appender& { return *this; } + + auto operator++(int) FMT_NOEXCEPT -> appender { return *this; } +}; + +// A formatting argument. It is a trivially copyable/constructible type to +// allow storage in basic_memory_buffer. +template <typename Context> class basic_format_arg { + private: + detail::value<Context> value_; + detail::type type_; + + template <typename ContextType, typename T> + friend FMT_CONSTEXPR auto detail::make_arg(const T& value) + -> basic_format_arg<ContextType>; + + template <typename Visitor, typename Ctx> + friend FMT_CONSTEXPR auto visit_format_arg(Visitor&& vis, + const basic_format_arg<Ctx>& arg) + -> decltype(vis(0)); + + friend class basic_format_args<Context>; + friend class dynamic_format_arg_store<Context>; + + using char_type = typename Context::char_type; + + template <typename T, typename Char, size_t NUM_ARGS, size_t NUM_NAMED_ARGS> + friend struct detail::arg_data; + + basic_format_arg(const detail::named_arg_info<char_type>* args, size_t size) + : value_(args, size) {} + + public: + class handle { + public: + explicit handle(detail::custom_value<Context> 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<Context> custom_; + }; + + constexpr basic_format_arg() : type_(detail::type::none_type) {} + + constexpr explicit operator bool() const FMT_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_); + } +}; + +/** + \rst + 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``. + \endrst + */ +template <typename Visitor, typename Context> +FMT_CONSTEXPR FMT_INLINE auto visit_format_arg( + Visitor&& vis, const basic_format_arg<Context>& arg) -> decltype(vis(0)) { + switch (arg.type_) { + case detail::type::none_type: + break; + case detail::type::int_type: + return vis(arg.value_.int_value); + case detail::type::uint_type: + return vis(arg.value_.uint_value); + case detail::type::long_long_type: + return vis(arg.value_.long_long_value); + case detail::type::ulong_long_type: + return vis(arg.value_.ulong_long_value); + case detail::type::int128_type: + return vis(detail::convert_for_visit(arg.value_.int128_value)); + case detail::type::uint128_type: + return vis(detail::convert_for_visit(arg.value_.uint128_value)); + case detail::type::bool_type: + return vis(arg.value_.bool_value); + case detail::type::char_type: + return vis(arg.value_.char_value); + case detail::type::float_type: + return vis(arg.value_.float_value); + case detail::type::double_type: + return vis(arg.value_.double_value); + case detail::type::long_double_type: + return vis(arg.value_.long_double_value); + case detail::type::cstring_type: + return vis(arg.value_.string.data); + case detail::type::string_type: + using sv = basic_string_view<typename Context::char_type>; + return vis(sv(arg.value_.string.data, arg.value_.string.size)); + case detail::type::pointer_type: + return vis(arg.value_.pointer); + case detail::type::custom_type: + return vis(typename basic_format_arg<Context>::handle(arg.value_.custom)); + } + return vis(monostate()); +} + +FMT_BEGIN_DETAIL_NAMESPACE + +template <typename Char, typename InputIt> +auto copy_str(InputIt begin, InputIt end, appender out) -> appender { + get_container(out).append(begin, end); + return out; +} + +#if FMT_GCC_VERSION && FMT_GCC_VERSION < 500 +// A workaround for gcc 4.8 to make void_t work in a SFINAE context. +template <typename... Ts> struct void_t_impl { using type = void; }; +template <typename... Ts> +using void_t = typename detail::void_t_impl<Ts...>::type; +#else +template <typename...> using void_t = void; +#endif + +template <typename It, typename T, typename Enable = void> +struct is_output_iterator : std::false_type {}; + +template <typename It, typename T> +struct is_output_iterator< + It, T, + void_t<typename std::iterator_traits<It>::iterator_category, + decltype(*std::declval<It>() = std::declval<T>())>> + : std::true_type {}; + +template <typename OutputIt> +struct is_back_insert_iterator : std::false_type {}; +template <typename Container> +struct is_back_insert_iterator<std::back_insert_iterator<Container>> + : std::true_type {}; + +template <typename OutputIt> +struct is_contiguous_back_insert_iterator : std::false_type {}; +template <typename Container> +struct is_contiguous_back_insert_iterator<std::back_insert_iterator<Container>> + : is_contiguous<Container> {}; +template <> +struct is_contiguous_back_insert_iterator<appender> : std::true_type {}; + +// A type-erased reference to an std::locale to avoid heavy <locale> include. +class locale_ref { + private: + const void* locale_; // A type-erased pointer to std::locale. + + public: + constexpr locale_ref() : locale_(nullptr) {} + template <typename Locale> explicit locale_ref(const Locale& loc); + + explicit operator bool() const FMT_NOEXCEPT { return locale_ != nullptr; } + + template <typename Locale> auto get() const -> Locale; +}; + +template <typename> constexpr auto encode_types() -> unsigned long long { + return 0; +} + +template <typename Context, typename Arg, typename... Args> +constexpr auto encode_types() -> unsigned long long { + return static_cast<unsigned>(mapped_type_constant<Arg, Context>::value) | + (encode_types<Context, Args...>() << packed_arg_bits); +} + +template <typename Context, typename T> +FMT_CONSTEXPR auto make_arg(const T& value) -> basic_format_arg<Context> { + basic_format_arg<Context> arg; + arg.type_ = mapped_type_constant<T, Context>::value; + arg.value_ = arg_mapper<Context>().map(value); + return arg; +} + +// The type template parameter is there to avoid an ODR violation when using +// a fallback formatter in one translation unit and an implicit conversion in +// another (not recommended). +template <bool IS_PACKED, typename Context, type, typename T, + FMT_ENABLE_IF(IS_PACKED)> +FMT_CONSTEXPR FMT_INLINE auto make_arg(T&& val) -> value<Context> { + const auto& arg = arg_mapper<Context>().map(std::forward<T>(val)); + + constexpr bool formattable_char = + !std::is_same<decltype(arg), const unformattable_char&>::value; + static_assert(formattable_char, "Mixing character types is disallowed."); + + constexpr bool formattable_const = + !std::is_same<decltype(arg), const unformattable_const&>::value; + static_assert(formattable_const, "Cannot format a const argument."); + + // Formatting of arbitrary pointers is disallowed. If you want to output + // a pointer cast it to "void *" or "const void *". In particular, this + // forbids formatting of "[const] volatile char *" which is printed as bool + // by iostreams. + constexpr bool formattable_pointer = + !std::is_same<decltype(arg), const unformattable_pointer&>::value; + static_assert(formattable_pointer, + "Formatting of non-void pointers is disallowed."); + + constexpr bool formattable = + !std::is_same<decltype(arg), const unformattable&>::value; + static_assert( + formattable, + "Cannot format an argument. To make type T formattable provide a " + "formatter<T> specialization: https://fmt.dev/latest/api.html#udt"); + return {arg}; +} + +template <bool IS_PACKED, typename Context, type, typename T, + FMT_ENABLE_IF(!IS_PACKED)> +inline auto make_arg(const T& value) -> basic_format_arg<Context> { + return make_arg<Context>(value); +} +FMT_END_DETAIL_NAMESPACE + +// Formatting context. +template <typename OutputIt, typename Char> class basic_format_context { + public: + /** The character type for the output. */ + using char_type = Char; + + private: + OutputIt out_; + basic_format_args<basic_format_context> args_; + detail::locale_ref loc_; + + public: + using iterator = OutputIt; + using format_arg = basic_format_arg<basic_format_context>; + using parse_context_type = basic_format_parse_context<Char>; + template <typename T> using formatter_type = formatter<T, char_type>; + + basic_format_context(basic_format_context&&) = default; + basic_format_context(const basic_format_context&) = delete; + void operator=(const basic_format_context&) = delete; + /** + Constructs a ``basic_format_context`` object. References to the arguments are + stored in the object so make sure they have appropriate lifetimes. + */ + constexpr basic_format_context( + OutputIt out, basic_format_args<basic_format_context> ctx_args, + detail::locale_ref loc = detail::locale_ref()) + : out_(out), args_(ctx_args), loc_(loc) {} + + constexpr auto arg(int id) const -> format_arg { return args_.get(id); } + FMT_CONSTEXPR auto arg(basic_string_view<char_type> name) -> format_arg { + return args_.get(name); + } + FMT_CONSTEXPR auto arg_id(basic_string_view<char_type> name) -> int { + return args_.get_id(name); + } + auto args() const -> const basic_format_args<basic_format_context>& { + return args_; + } + + FMT_CONSTEXPR auto error_handler() -> detail::error_handler { return {}; } + void on_error(const char* message) { error_handler().on_error(message); } + + // 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 it) { + if (!detail::is_back_insert_iterator<iterator>()) out_ = it; + } + + FMT_CONSTEXPR auto locale() -> detail::locale_ref { return loc_; } +}; + +template <typename Char> +using buffer_context = + basic_format_context<detail::buffer_appender<Char>, Char>; +using format_context = buffer_context<char>; + +// Workaround an alias issue: https://stackoverflow.com/q/62767544/471164. +#define FMT_BUFFER_CONTEXT(Char) \ + basic_format_context<detail::buffer_appender<Char>, Char> + +template <typename T, typename Char = char> +using is_formattable = bool_constant< + !std::is_base_of<detail::unformattable, + decltype(detail::arg_mapper<buffer_context<Char>>().map( + std::declval<T>()))>::value && + !detail::has_fallback_formatter<T, Char>::value>; + +/** + \rst + An array of references to arguments. It can be implicitly converted into + `~fmt::basic_format_args` for passing into type-erased formatting functions + such as `~fmt::vformat`. + \endrst + */ +template <typename Context, typename... Args> +class format_arg_store +#if FMT_GCC_VERSION && FMT_GCC_VERSION < 409 + // Workaround a GCC template argument substitution bug. + : public basic_format_args<Context> +#endif +{ + private: + static const size_t num_args = sizeof...(Args); + static const size_t num_named_args = detail::count_named_args<Args...>(); + static const bool is_packed = num_args <= detail::max_packed_args; + + using value_type = conditional_t<is_packed, detail::value<Context>, + basic_format_arg<Context>>; + + detail::arg_data<value_type, typename Context::char_type, num_args, + num_named_args> + data_; + + friend class basic_format_args<Context>; + + static constexpr unsigned long long desc = + (is_packed ? detail::encode_types<Context, Args...>() + : detail::is_unpacked_bit | num_args) | + (num_named_args != 0 + ? static_cast<unsigned long long>(detail::has_named_args_bit) + : 0); + + public: + template <typename... T> + FMT_CONSTEXPR FMT_INLINE format_arg_store(T&&... args) + : +#if FMT_GCC_VERSION && FMT_GCC_VERSION < 409 + basic_format_args<Context>(*this), +#endif + data_{detail::make_arg< + is_packed, Context, + detail::mapped_type_constant<remove_cvref_t<T>, Context>::value>( + std::forward<T>(args))...} { + detail::init_named_args(data_.named_args(), 0, 0, args...); + } +}; + +/** + \rst + Constructs a `~fmt::format_arg_store` object that contains references to + arguments and can be implicitly converted to `~fmt::format_args`. `Context` + can be omitted in which case it defaults to `~fmt::context`. + See `~fmt::arg` for lifetime considerations. + \endrst + */ +template <typename Context = format_context, typename... Args> +constexpr auto make_format_args(Args&&... args) + -> format_arg_store<Context, remove_cvref_t<Args>...> { + return {std::forward<Args>(args)...}; +} + +/** + \rst + 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("Elapsed time: {s:.2f} seconds", fmt::arg("s", 1.23)); + \endrst + */ +template <typename Char, typename T> +inline auto arg(const Char* name, const T& arg) -> detail::named_arg<Char, T> { + static_assert(!detail::is_named_arg<T>(), "nested named arguments"); + return {name, arg}; +} + +/** + \rst + 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(string_view format_str, format_args args); // OK + format_args args = make_format_args(42); // Error: dangling reference + \endrst + */ +template <typename Context> class basic_format_args { + public: + using size_type = int; + using format_arg = basic_format_arg<Context>; + + 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<Context>* values_; + const format_arg* args_; + }; + + constexpr auto is_packed() const -> bool { + return (desc_ & detail::is_unpacked_bit) == 0; + } + 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<detail::type>((desc_ >> shift) & mask); + } + + constexpr FMT_INLINE basic_format_args(unsigned long long desc, + const detail::value<Context>* values) + : desc_(desc), values_(values) {} + constexpr basic_format_args(unsigned long long desc, const format_arg* args) + : desc_(desc), args_(args) {} + + public: + constexpr basic_format_args() : desc_(0), args_(nullptr) {} + + /** + \rst + Constructs a `basic_format_args` object from `~fmt::format_arg_store`. + \endrst + */ + template <typename... Args> + constexpr FMT_INLINE basic_format_args( + const format_arg_store<Context, Args...>& store) + : basic_format_args(format_arg_store<Context, Args...>::desc, + store.data_.args()) {} + + /** + \rst + Constructs a `basic_format_args` object from + `~fmt::dynamic_format_arg_store`. + \endrst + */ + constexpr FMT_INLINE basic_format_args( + const dynamic_format_arg_store<Context>& store) + : basic_format_args(store.get_types(), store.data()) {} + + /** + \rst + Constructs a `basic_format_args` object from a dynamic set of arguments. + \endrst + */ + constexpr basic_format_args(const format_arg* args, int count) + : basic_format_args(detail::is_unpacked_bit | detail::to_unsigned(count), + 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 (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 <typename Char> + auto get(basic_string_view<Char> name) const -> format_arg { + int id = get_id(name); + return id >= 0 ? get(id) : format_arg(); + } + + template <typename Char> + auto get_id(basic_string_view<Char> 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<int>(is_packed() ? max_packed + : desc_ & ~detail::is_unpacked_bit); + } +}; + +/** An alias to ``basic_format_args<format_context>``. */ +// A separate type would result in shorter symbols but break ABI compatibility +// between clang and gcc on ARM (#1919). +using format_args = basic_format_args<format_context>; + +// We cannot use enum classes as bit fields because of a gcc bug +// https://gcc.gnu.org/bugzilla/show_bug.cgi?id=61414. +namespace align { +enum type { none, left, right, center, numeric }; +} +using align_t = align::type; +namespace sign { +enum type { none, minus, plus, space }; +} +using sign_t = sign::type; + +FMT_BEGIN_DETAIL_NAMESPACE + +// Workaround an array initialization issue in gcc 4.8. +template <typename Char> struct fill_t { + private: + enum { max_size = 4 }; + Char data_[max_size] = {Char(' '), Char(0), Char(0), Char(0)}; + unsigned char size_ = 1; + + public: + FMT_CONSTEXPR void operator=(basic_string_view<Char> s) { + auto size = s.size(); + if (size > max_size) return throw_format_error("invalid fill"); + for (size_t i = 0; i < size; ++i) data_[i] = s[i]; + size_ = static_cast<unsigned char>(size); + } + + constexpr auto size() const -> size_t { return size_; } + constexpr auto data() const -> const Char* { return data_; } + + FMT_CONSTEXPR auto operator[](size_t index) -> Char& { return data_[index]; } + FMT_CONSTEXPR auto operator[](size_t index) const -> const Char& { + return data_[index]; + } +}; +FMT_END_DETAIL_NAMESPACE + +enum class presentation_type : unsigned char { + none, + // Integer types should go first, + dec, // 'd' + oct, // 'o' + hex_lower, // 'x' + hex_upper, // 'X' + bin_lower, // 'b' + bin_upper, // 'B' + hexfloat_lower, // 'a' + hexfloat_upper, // 'A' + exp_lower, // 'e' + exp_upper, // 'E' + fixed_lower, // 'f' + fixed_upper, // 'F' + general_lower, // 'g' + general_upper, // 'G' + chr, // 'c' + string, // 's' + pointer // 'p' +}; + +// Format specifiers for built-in and string types. +template <typename Char> struct basic_format_specs { + int width; + int precision; + presentation_type type; + align_t align : 4; + sign_t sign : 3; + bool alt : 1; // Alternate form ('#'). + bool localized : 1; + detail::fill_t<Char> fill; + + constexpr basic_format_specs() + : width(0), + precision(-1), + type(presentation_type::none), + align(align::none), + sign(sign::none), + alt(false), + localized(false) {} +}; + +using format_specs = basic_format_specs<char>; + +FMT_BEGIN_DETAIL_NAMESPACE + +enum class arg_id_kind { none, index, name }; + +// An argument reference. +template <typename Char> 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<Char> 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 id = 0) : index{id} {} + FMT_CONSTEXPR value(basic_string_view<Char> n) : name(n) {} + + int index; + basic_string_view<Char> name; + } val; +}; + +// Format specifiers with width and precision resolved at formatting rather +// than parsing time to allow re-using the same parsed specifiers with +// different sets of arguments (precompilation of format strings). +template <typename Char> +struct dynamic_format_specs : basic_format_specs<Char> { + arg_ref<Char> width_ref; + arg_ref<Char> precision_ref; +}; + +struct auto_id {}; + +// A format specifier handler that sets fields in basic_format_specs. +template <typename Char> class specs_setter { + protected: + basic_format_specs<Char>& specs_; + + public: + explicit FMT_CONSTEXPR specs_setter(basic_format_specs<Char>& specs) + : specs_(specs) {} + + FMT_CONSTEXPR specs_setter(const specs_setter& other) + : specs_(other.specs_) {} + + FMT_CONSTEXPR void on_align(align_t align) { specs_.align = align; } + FMT_CONSTEXPR void on_fill(basic_string_view<Char> fill) { + specs_.fill = fill; + } + FMT_CONSTEXPR void on_sign(sign_t s) { specs_.sign = s; } + FMT_CONSTEXPR void on_hash() { specs_.alt = true; } + FMT_CONSTEXPR void on_localized() { specs_.localized = true; } + + FMT_CONSTEXPR void on_zero() { + if (specs_.align == align::none) specs_.align = align::numeric; + specs_.fill[0] = Char('0'); + } + + FMT_CONSTEXPR void on_width(int width) { specs_.width = width; } + FMT_CONSTEXPR void on_precision(int precision) { + specs_.precision = precision; + } + FMT_CONSTEXPR void end_precision() {} + + FMT_CONSTEXPR void on_type(presentation_type type) { specs_.type = type; } +}; + +// Format spec handler that saves references to arguments representing dynamic +// width and precision to be resolved at formatting time. +template <typename ParseContext> +class dynamic_specs_handler + : public specs_setter<typename ParseContext::char_type> { + public: + using char_type = typename ParseContext::char_type; + + FMT_CONSTEXPR dynamic_specs_handler(dynamic_format_specs<char_type>& specs, + ParseContext& ctx) + : specs_setter<char_type>(specs), specs_(specs), context_(ctx) {} + + FMT_CONSTEXPR dynamic_specs_handler(const dynamic_specs_handler& other) + : specs_setter<char_type>(other), + specs_(other.specs_), + context_(other.context_) {} + + template <typename Id> FMT_CONSTEXPR void on_dynamic_width(Id arg_id) { + specs_.width_ref = make_arg_ref(arg_id); + } + + template <typename Id> FMT_CONSTEXPR void on_dynamic_precision(Id arg_id) { + specs_.precision_ref = make_arg_ref(arg_id); + } + + FMT_CONSTEXPR void on_error(const char* message) { + context_.on_error(message); + } + + private: + dynamic_format_specs<char_type>& specs_; + ParseContext& context_; + + using arg_ref_type = arg_ref<char_type>; + + FMT_CONSTEXPR auto make_arg_ref(int arg_id) -> arg_ref_type { + context_.check_arg_id(arg_id); + return arg_ref_type(arg_id); + } + + FMT_CONSTEXPR auto make_arg_ref(auto_id) -> arg_ref_type { + return arg_ref_type(context_.next_arg_id()); + } + + FMT_CONSTEXPR auto make_arg_ref(basic_string_view<char_type> arg_id) + -> arg_ref_type { + context_.check_arg_id(arg_id); + basic_string_view<char_type> format_str( + context_.begin(), to_unsigned(context_.end() - context_.begin())); + return arg_ref_type(arg_id); + } +}; + +template <typename Char> constexpr bool is_ascii_letter(Char c) { + return (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z'); +} + +// Converts a character to ASCII. Returns a number > 127 on conversion failure. +template <typename Char, FMT_ENABLE_IF(std::is_integral<Char>::value)> +constexpr auto to_ascii(Char value) -> Char { + return value; +} +template <typename Char, FMT_ENABLE_IF(std::is_enum<Char>::value)> +constexpr auto to_ascii(Char value) -> + typename std::underlying_type<Char>::type { + return value; +} + +template <typename Char> +FMT_CONSTEXPR auto code_point_length(const Char* begin) -> int { + if (const_check(sizeof(Char) != 1)) return 1; + auto lengths = + "\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"; + int len = lengths[static_cast<unsigned char>(*begin) >> 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. + return len + !len; +} + +// Return the result via the out param to workaround gcc bug 77539. +template <bool IS_CONSTEXPR, typename T, typename Ptr = const T*> +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<false, char>(const char* first, const char* last, char value, + const char*& out) -> bool { + out = static_cast<const char*>( + std::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 <typename Char> +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; + if (num_digits <= std::numeric_limits<int>::digits10) + return static_cast<int>(value); + // Check for overflow. + const unsigned max = to_unsigned((std::numeric_limits<int>::max)()); + return num_digits == std::numeric_limits<int>::digits10 + 1 && + prev * 10ull + unsigned(p[-1] - '0') <= max + ? static_cast<int>(value) + : error_value; +} + +// Parses fill and alignment. +template <typename Char, typename Handler> +FMT_CONSTEXPR auto parse_align(const Char* begin, const Char* end, + Handler&& handler) -> const Char* { + FMT_ASSERT(begin != end, ""); + auto align = align::none; + auto p = begin + code_point_length(begin); + if (p >= end) p = begin; + for (;;) { + switch (to_ascii(*p)) { + case '<': + align = align::left; + break; + case '>': + align = align::right; + break; + case '^': + align = align::center; + break; + default: + break; + } + if (align != align::none) { + if (p != begin) { + auto c = *begin; + if (c == '{') + return handler.on_error("invalid fill character '{'"), begin; + handler.on_fill(basic_string_view<Char>(begin, to_unsigned(p - begin))); + begin = p + 1; + } else + ++begin; + handler.on_align(align); + break; + } else if (p == begin) { + break; + } + p = begin; + } + return begin; +} + +template <typename Char> FMT_CONSTEXPR bool is_name_start(Char c) { + return ('a' <= c && c <= 'z') || ('A' <= c && c <= 'Z') || '_' == c; +} + +template <typename Char, typename IDHandler> +FMT_CONSTEXPR auto do_parse_arg_id(const Char* begin, const Char* end, + IDHandler&& handler) -> const Char* { + FMT_ASSERT(begin != end, ""); + Char c = *begin; + if (c >= '0' && c <= '9') { + int index = 0; + if (c != '0') + index = + parse_nonnegative_int(begin, end, (std::numeric_limits<int>::max)()); + else + ++begin; + if (begin == end || (*begin != '}' && *begin != ':')) + handler.on_error("invalid format string"); + else + handler(index); + return begin; + } + if (!is_name_start(c)) { + handler.on_error("invalid format string"); + return begin; + } + auto it = begin; + do { + ++it; + } while (it != end && (is_name_start(c = *it) || ('0' <= c && c <= '9'))); + handler(basic_string_view<Char>(begin, to_unsigned(it - begin))); + return it; +} + +template <typename Char, typename IDHandler> +FMT_CONSTEXPR FMT_INLINE auto parse_arg_id(const Char* begin, const Char* end, + IDHandler&& handler) -> const Char* { + Char c = *begin; + if (c != '}' && c != ':') return do_parse_arg_id(begin, end, handler); + handler(); + return begin; +} + +template <typename Char, typename Handler> +FMT_CONSTEXPR auto parse_width(const Char* begin, const Char* end, + Handler&& handler) -> const Char* { + using detail::auto_id; + struct width_adapter { + Handler& handler; + + FMT_CONSTEXPR void operator()() { handler.on_dynamic_width(auto_id()); } + FMT_CONSTEXPR void operator()(int id) { handler.on_dynamic_width(id); } + FMT_CONSTEXPR void operator()(basic_string_view<Char> id) { + handler.on_dynamic_width(id); + } + FMT_CONSTEXPR void on_error(const char* message) { + if (message) handler.on_error(message); + } + }; + + FMT_ASSERT(begin != end, ""); + if ('0' <= *begin && *begin <= '9') { + int width = parse_nonnegative_int(begin, end, -1); + if (width != -1) + handler.on_width(width); + else + handler.on_error("number is too big"); + } else if (*begin == '{') { + ++begin; + if (begin != end) begin = parse_arg_id(begin, end, width_adapter{handler}); + if (begin == end || *begin != '}') + return handler.on_error("invalid format string"), begin; + ++begin; + } + return begin; +} + +template <typename Char, typename Handler> +FMT_CONSTEXPR auto parse_precision(const Char* begin, const Char* end, + Handler&& handler) -> const Char* { + using detail::auto_id; + struct precision_adapter { + Handler& handler; + + FMT_CONSTEXPR void operator()() { handler.on_dynamic_precision(auto_id()); } + FMT_CONSTEXPR void operator()(int id) { handler.on_dynamic_precision(id); } + FMT_CONSTEXPR void operator()(basic_string_view<Char> id) { + handler.on_dynamic_precision(id); + } + FMT_CONSTEXPR void on_error(const char* message) { + if (message) handler.on_error(message); + } + }; + + ++begin; + auto c = begin != end ? *begin : Char(); + if ('0' <= c && c <= '9') { + auto precision = parse_nonnegative_int(begin, end, -1); + if (precision != -1) + handler.on_precision(precision); + else + handler.on_error("number is too big"); + } else if (c == '{') { + ++begin; + if (begin != end) + begin = parse_arg_id(begin, end, precision_adapter{handler}); + if (begin == end || *begin++ != '}') + return handler.on_error("invalid format string"), begin; + } else { + return handler.on_error("missing precision specifier"), begin; + } + handler.end_precision(); + return begin; +} + +template <typename Char> +FMT_CONSTEXPR auto parse_presentation_type(Char type) -> presentation_type { + switch (to_ascii(type)) { + case 'd': + return presentation_type::dec; + case 'o': + return presentation_type::oct; + case 'x': + return presentation_type::hex_lower; + case 'X': + return presentation_type::hex_upper; + case 'b': + return presentation_type::bin_lower; + case 'B': + return presentation_type::bin_upper; + case 'a': + return presentation_type::hexfloat_lower; + case 'A': + return presentation_type::hexfloat_upper; + case 'e': + return presentation_type::exp_lower; + case 'E': + return presentation_type::exp_upper; + case 'f': + return presentation_type::fixed_lower; + case 'F': + return presentation_type::fixed_upper; + case 'g': + return presentation_type::general_lower; + case 'G': + return presentation_type::general_upper; + case 'c': + return presentation_type::chr; + case 's': + return presentation_type::string; + case 'p': + return presentation_type::pointer; + default: + return presentation_type::none; + } +} + +// Parses standard format specifiers and sends notifications about parsed +// components to handler. +template <typename Char, typename SpecHandler> +FMT_CONSTEXPR FMT_INLINE auto parse_format_specs(const Char* begin, + const Char* end, + SpecHandler&& handler) + -> const Char* { + if (1 < end - begin && begin[1] == '}' && is_ascii_letter(*begin) && + *begin != 'L') { + presentation_type type = parse_presentation_type(*begin++); + if (type == presentation_type::none) + handler.on_error("invalid type specifier"); + handler.on_type(type); + return begin; + } + + if (begin == end) return begin; + + begin = parse_align(begin, end, handler); + if (begin == end) return begin; + + // Parse sign. + switch (to_ascii(*begin)) { + case '+': + handler.on_sign(sign::plus); + ++begin; + break; + case '-': + handler.on_sign(sign::minus); + ++begin; + break; + case ' ': + handler.on_sign(sign::space); + ++begin; + break; + default: + break; + } + if (begin == end) return begin; + + if (*begin == '#') { + handler.on_hash(); + if (++begin == end) return begin; + } + + // Parse zero flag. + if (*begin == '0') { + handler.on_zero(); + if (++begin == end) return begin; + } + + begin = parse_width(begin, end, handler); + if (begin == end) return begin; + + // Parse precision. + if (*begin == '.') { + begin = parse_precision(begin, end, handler); + if (begin == end) return begin; + } + + if (*begin == 'L') { + handler.on_localized(); + ++begin; + } + + // Parse type. + if (begin != end && *begin != '}') { + presentation_type type = parse_presentation_type(*begin++); + if (type == presentation_type::none) + handler.on_error("invalid type specifier"); + handler.on_type(type); + } + return begin; +} + +template <typename Char, typename Handler> +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 operator()() { arg_id = handler.on_arg_id(); } + FMT_CONSTEXPR void operator()(int id) { arg_id = handler.on_arg_id(id); } + FMT_CONSTEXPR void operator()(basic_string_view<Char> id) { + arg_id = handler.on_arg_id(id); + } + FMT_CONSTEXPR void on_error(const char* message) { + if (message) handler.on_error(message); + } + }; + + ++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 <bool IS_CONSTEXPR, typename Char, typename Handler> +FMT_CONSTEXPR FMT_INLINE void parse_format_string( + basic_string_view<Char> format_str, Handler&& handler) { + // Workaround a name-lookup bug in MSVC's modules implementation. + using detail::find; + + 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* pbegin, const Char* pend) { + if (pbegin == pend) return; + for (;;) { + const Char* p = nullptr; + if (!find<IS_CONSTEXPR>(pbegin, pend, Char('}'), p)) + return handler_.on_text(pbegin, pend); + ++p; + if (p == pend || *p != '}') + return handler_.on_error("unmatched '}' in format string"); + handler_.on_text(pbegin, p); + pbegin = 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<IS_CONSTEXPR>(begin + 1, end, Char('{'), p)) + return write(begin, end); + write(begin, p); + begin = parse_replacement_field(p, end, handler); + } +} + +template <typename T, typename ParseContext> +FMT_CONSTEXPR auto parse_format_specs(ParseContext& ctx) + -> decltype(ctx.begin()) { + using char_type = typename ParseContext::char_type; + using context = buffer_context<char_type>; + using mapped_type = conditional_t< + mapped_type_constant<T, context>::value != type::custom_type, + decltype(arg_mapper<context>().map(std::declval<const T&>())), T>; + auto f = conditional_t<has_formatter<mapped_type, context>::value, + formatter<mapped_type, char_type>, + fallback_formatter<T, char_type>>(); + return f.parse(ctx); +} + +// A parse context with extra argument id checks. It is only used at compile +// time because adding checks at runtime would introduce substantial overhead +// and would be redundant since argument ids are checked when arguments are +// retrieved anyway. +template <typename Char, typename ErrorHandler = error_handler> +class compile_parse_context + : public basic_format_parse_context<Char, ErrorHandler> { + private: + int num_args_; + using base = basic_format_parse_context<Char, ErrorHandler>; + + public: + explicit FMT_CONSTEXPR compile_parse_context( + basic_string_view<Char> format_str, + int num_args = (std::numeric_limits<int>::max)(), ErrorHandler eh = {}) + : base(format_str, eh), num_args_(num_args) {} + + FMT_CONSTEXPR auto next_arg_id() -> int { + int id = base::next_arg_id(); + if (id >= num_args_) this->on_error("argument not found"); + return id; + } + + FMT_CONSTEXPR void check_arg_id(int id) { + base::check_arg_id(id); + if (id >= num_args_) this->on_error("argument not found"); + } + using base::check_arg_id; +}; + +template <typename ErrorHandler> +FMT_CONSTEXPR void check_int_type_spec(presentation_type type, + ErrorHandler&& eh) { + if (type > presentation_type::bin_upper && type != presentation_type::chr) + eh.on_error("invalid type specifier"); +} + +// Checks char specs and returns true if the type spec is char (and not int). +template <typename Char, typename ErrorHandler = error_handler> +FMT_CONSTEXPR auto check_char_specs(const basic_format_specs<Char>& specs, + ErrorHandler&& eh = {}) -> bool { + if (specs.type != presentation_type::none && + specs.type != presentation_type::chr) { + check_int_type_spec(specs.type, eh); + return false; + } + if (specs.align == align::numeric || specs.sign != sign::none || specs.alt) + eh.on_error("invalid format specifier for char"); + return true; +} + +// 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. + hex +}; + +struct float_specs { + int precision; + float_format format : 8; + sign_t sign : 8; + bool upper : 1; + bool locale : 1; + bool binary32 : 1; + bool fallback : 1; + bool showpoint : 1; +}; + +template <typename ErrorHandler = error_handler, typename Char> +FMT_CONSTEXPR auto parse_float_type_spec(const basic_format_specs<Char>& specs, + ErrorHandler&& eh = {}) + -> float_specs { + auto result = float_specs(); + result.showpoint = specs.alt; + result.locale = specs.localized; + switch (specs.type) { + case presentation_type::none: + result.format = float_format::general; + break; + case presentation_type::general_upper: + result.upper = true; + FMT_FALLTHROUGH; + case presentation_type::general_lower: + result.format = float_format::general; + break; + case presentation_type::exp_upper: + result.upper = true; + FMT_FALLTHROUGH; + case presentation_type::exp_lower: + result.format = float_format::exp; + result.showpoint |= specs.precision != 0; + break; + case presentation_type::fixed_upper: + result.upper = true; + FMT_FALLTHROUGH; + case presentation_type::fixed_lower: + result.format = float_format::fixed; + result.showpoint |= specs.precision != 0; + break; + case presentation_type::hexfloat_upper: + result.upper = true; + FMT_FALLTHROUGH; + case presentation_type::hexfloat_lower: + result.format = float_format::hex; + break; + default: + eh.on_error("invalid type specifier"); + break; + } + return result; +} + +template <typename ErrorHandler = error_handler> +FMT_CONSTEXPR auto check_cstring_type_spec(presentation_type type, + ErrorHandler&& eh = {}) -> bool { + if (type == presentation_type::none || type == presentation_type::string) + return true; + if (type != presentation_type::pointer) eh.on_error("invalid type specifier"); + return false; +} + +template <typename ErrorHandler = error_handler> +FMT_CONSTEXPR void check_string_type_spec(presentation_type type, + ErrorHandler&& eh = {}) { + if (type != presentation_type::none && type != presentation_type::string) + eh.on_error("invalid type specifier"); +} + +template <typename ErrorHandler> +FMT_CONSTEXPR void check_pointer_type_spec(presentation_type type, + ErrorHandler&& eh) { + if (type != presentation_type::none && type != presentation_type::pointer) + eh.on_error("invalid type specifier"); +} + +// A parse_format_specs handler that checks if specifiers are consistent with +// the argument type. +template <typename Handler> class specs_checker : public Handler { + private: + detail::type arg_type_; + + FMT_CONSTEXPR void require_numeric_argument() { + if (!is_arithmetic_type(arg_type_)) + this->on_error("format specifier requires numeric argument"); + } + + public: + FMT_CONSTEXPR specs_checker(const Handler& handler, detail::type arg_type) + : Handler(handler), arg_type_(arg_type) {} + + FMT_CONSTEXPR void on_align(align_t align) { + if (align == align::numeric) require_numeric_argument(); + Handler::on_align(align); + } + + FMT_CONSTEXPR void on_sign(sign_t s) { + require_numeric_argument(); + if (is_integral_type(arg_type_) && arg_type_ != type::int_type && + arg_type_ != type::long_long_type && arg_type_ != type::char_type) { + this->on_error("format specifier requires signed argument"); + } + Handler::on_sign(s); + } + + FMT_CONSTEXPR void on_hash() { + require_numeric_argument(); + Handler::on_hash(); + } + + FMT_CONSTEXPR void on_localized() { + require_numeric_argument(); + Handler::on_localized(); + } + + FMT_CONSTEXPR void on_zero() { + require_numeric_argument(); + Handler::on_zero(); + } + + FMT_CONSTEXPR void end_precision() { + if (is_integral_type(arg_type_) || arg_type_ == type::pointer_type) + this->on_error("precision not allowed for this argument type"); + } +}; + +constexpr int invalid_arg_index = -1; + +#if FMT_USE_NONTYPE_TEMPLATE_PARAMETERS +template <int N, typename T, typename... Args, typename Char> +constexpr auto get_arg_index_by_name(basic_string_view<Char> name) -> int { + if constexpr (detail::is_statically_named_arg<T>()) { + if (name == T::name) return N; + } + if constexpr (sizeof...(Args) > 0) + return get_arg_index_by_name<N + 1, Args...>(name); + (void)name; // Workaround an MSVC bug about "unused" parameter. + return invalid_arg_index; +} +#endif + +template <typename... Args, typename Char> +FMT_CONSTEXPR auto get_arg_index_by_name(basic_string_view<Char> name) -> int { +#if FMT_USE_NONTYPE_TEMPLATE_PARAMETERS + if constexpr (sizeof...(Args) > 0) + return get_arg_index_by_name<0, Args...>(name); +#endif + (void)name; + return invalid_arg_index; +} + +template <typename Char, typename ErrorHandler, typename... Args> +class format_string_checker { + private: + using parse_context_type = compile_parse_context<Char, ErrorHandler>; + enum { num_args = sizeof...(Args) }; + + // Format specifier parsing function. + using parse_func = const Char* (*)(parse_context_type&); + + parse_context_type context_; + parse_func parse_funcs_[num_args > 0 ? num_args : 1]; + + public: + explicit FMT_CONSTEXPR format_string_checker( + basic_string_view<Char> format_str, ErrorHandler eh) + : context_(format_str, num_args, eh), + parse_funcs_{&parse_format_specs<Args, parse_context_type>...} {} + + 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<Char> id) -> int { +#if FMT_USE_NONTYPE_TEMPLATE_PARAMETERS + auto index = get_arg_index_by_name<Args...>(id); + if (index == invalid_arg_index) on_error("named argument is not found"); + return context_.check_arg_id(index), 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, const Char*) {} + + FMT_CONSTEXPR auto on_format_specs(int id, const Char* begin, const Char*) + -> const Char* { + context_.advance_to(context_.begin() + (begin - &*context_.begin())); + // id >= 0 check is a workaround for gcc 10 bug (#2065). + return id >= 0 && id < num_args ? parse_funcs_[id](context_) : begin; + } + + FMT_CONSTEXPR void on_error(const char* message) { + context_.on_error(message); + } +}; + +template <typename... Args, typename S, + enable_if_t<(is_compile_string<S>::value), int>> +void check_format_string(S format_str) { + FMT_CONSTEXPR auto s = to_string_view(format_str); + using checker = format_string_checker<typename S::char_type, error_handler, + remove_cvref_t<Args>...>; + FMT_CONSTEXPR bool invalid_format = + (parse_format_string<true>(s, checker(s, {})), true); + ignore_unused(invalid_format); +} + +template <typename Char> +void vformat_to( + buffer<Char>& buf, basic_string_view<Char> fmt, + basic_format_args<FMT_BUFFER_CONTEXT(type_identity_t<Char>)> args, + locale_ref loc = {}); + +FMT_API void vprint_mojibake(std::FILE*, string_view, format_args); +#ifndef _WIN32 +inline void vprint_mojibake(std::FILE*, string_view, format_args) {} +#endif +FMT_END_DETAIL_NAMESPACE + +// A formatter specialization for the core types corresponding to detail::type +// constants. +template <typename T, typename Char> +struct formatter<T, Char, + enable_if_t<detail::type_constant<T, Char>::value != + detail::type::custom_type>> { + private: + detail::dynamic_format_specs<Char> specs_; + + public: + // Parses format specifiers stopping either at the end of the range or at the + // terminating '}'. + template <typename ParseContext> + FMT_CONSTEXPR auto parse(ParseContext& ctx) -> decltype(ctx.begin()) { + auto begin = ctx.begin(), end = ctx.end(); + if (begin == end) return begin; + using handler_type = detail::dynamic_specs_handler<ParseContext>; + auto type = detail::type_constant<T, Char>::value; + auto checker = + detail::specs_checker<handler_type>(handler_type(specs_, ctx), type); + auto it = detail::parse_format_specs(begin, end, checker); + auto eh = ctx.error_handler(); + switch (type) { + case detail::type::none_type: + FMT_ASSERT(false, "invalid argument type"); + break; + case detail::type::bool_type: + if (specs_.type == presentation_type::none || + specs_.type == presentation_type::string) { + break; + } + FMT_FALLTHROUGH; + case detail::type::int_type: + case detail::type::uint_type: + case detail::type::long_long_type: + case detail::type::ulong_long_type: + case detail::type::int128_type: + case detail::type::uint128_type: + detail::check_int_type_spec(specs_.type, eh); + break; + case detail::type::char_type: + detail::check_char_specs(specs_, eh); + break; + case detail::type::float_type: + if (detail::const_check(FMT_USE_FLOAT)) + detail::parse_float_type_spec(specs_, eh); + else + FMT_ASSERT(false, "float support disabled"); + break; + case detail::type::double_type: + if (detail::const_check(FMT_USE_DOUBLE)) + detail::parse_float_type_spec(specs_, eh); + else + FMT_ASSERT(false, "double support disabled"); + break; + case detail::type::long_double_type: + if (detail::const_check(FMT_USE_LONG_DOUBLE)) + detail::parse_float_type_spec(specs_, eh); + else + FMT_ASSERT(false, "long double support disabled"); + break; + case detail::type::cstring_type: + detail::check_cstring_type_spec(specs_.type, eh); + break; + case detail::type::string_type: + detail::check_string_type_spec(specs_.type, eh); + break; + case detail::type::pointer_type: + detail::check_pointer_type_spec(specs_.type, eh); + break; + case detail::type::custom_type: + // Custom format specifiers are checked in parse functions of + // formatter specializations. + break; + } + return it; + } + + template <typename FormatContext> + FMT_CONSTEXPR auto format(const T& val, FormatContext& ctx) const + -> decltype(ctx.out()); +}; + +template <typename Char> struct basic_runtime { basic_string_view<Char> str; }; + +/** A compile-time format string. */ +template <typename Char, typename... Args> class basic_format_string { + private: + basic_string_view<Char> str_; + + public: + template <typename S, + FMT_ENABLE_IF( + std::is_convertible<const S&, basic_string_view<Char>>::value)> + FMT_CONSTEVAL FMT_INLINE basic_format_string(const S& s) : str_(s) { + static_assert( + detail::count< + (std::is_base_of<detail::view, remove_reference_t<Args>>::value && + std::is_reference<Args>::value)...>() == 0, + "passing views as lvalues is disallowed"); +#ifdef FMT_HAS_CONSTEVAL + if constexpr (detail::count_named_args<Args...>() == + detail::count_statically_named_args<Args...>()) { + using checker = detail::format_string_checker<Char, detail::error_handler, + remove_cvref_t<Args>...>; + detail::parse_format_string<true>(str_, checker(s, {})); + } +#else + detail::check_format_string<Args...>(s); +#endif + } + basic_format_string(basic_runtime<Char> r) : str_(r.str) {} + + FMT_INLINE operator basic_string_view<Char>() const { return str_; } +}; + +#if FMT_GCC_VERSION && FMT_GCC_VERSION < 409 +// Workaround broken conversion on older gcc. +template <typename... Args> using format_string = string_view; +template <typename S> auto runtime(const S& s) -> basic_string_view<char_t<S>> { + return s; +} +#else +template <typename... Args> +using format_string = basic_format_string<char, type_identity_t<Args>...>; +/** + \rst + 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"); + \endrst + */ +template <typename S> auto runtime(const S& s) -> basic_runtime<char_t<S>> { + return {{s}}; +} +#endif + +FMT_API auto vformat(string_view fmt, format_args args) -> std::string; + +/** + \rst + Formats ``args`` according to specifications in ``fmt`` and returns the result + as a string. + + **Example**:: + + #include <fmt/core.h> + std::string message = fmt::format("The answer is {}.", 42); + \endrst +*/ +template <typename... T> +FMT_NODISCARD FMT_INLINE auto format(format_string<T...> fmt, T&&... args) + -> std::string { + return vformat(fmt, fmt::make_format_args(args...)); +} + +/** Formats a string and writes the output to ``out``. */ +template <typename OutputIt, + FMT_ENABLE_IF(detail::is_output_iterator<OutputIt, char>::value)> +auto vformat_to(OutputIt out, string_view fmt, format_args args) -> OutputIt { + using detail::get_buffer; + auto&& buf = get_buffer<char>(out); + detail::vformat_to(buf, fmt, args, {}); + return detail::get_iterator(buf); +} + +/** + \rst + 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<char>(); + fmt::format_to(std::back_inserter(out), "{}", 42); + \endrst + */ +template <typename OutputIt, typename... T, + FMT_ENABLE_IF(detail::is_output_iterator<OutputIt, char>::value)> +FMT_INLINE auto format_to(OutputIt out, format_string<T...> fmt, T&&... args) + -> OutputIt { + return vformat_to(out, fmt, fmt::make_format_args(args...)); +} + +template <typename OutputIt> struct format_to_n_result { + /** Iterator past the end of the output range. */ + OutputIt out; + /** Total (not truncated) output size. */ + size_t size; +}; + +template <typename OutputIt, typename... T, + FMT_ENABLE_IF(detail::is_output_iterator<OutputIt, char>::value)> +auto vformat_to_n(OutputIt out, size_t n, string_view fmt, format_args args) + -> format_to_n_result<OutputIt> { + using traits = detail::fixed_buffer_traits; + auto buf = detail::iterator_buffer<OutputIt, char, traits>(out, n); + detail::vformat_to(buf, fmt, args, {}); + return {buf.out(), buf.count()}; +} + +/** + \rst + 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. + \endrst + */ +template <typename OutputIt, typename... T, + FMT_ENABLE_IF(detail::is_output_iterator<OutputIt, char>::value)> +FMT_INLINE auto format_to_n(OutputIt out, size_t n, format_string<T...> fmt, + T&&... args) -> format_to_n_result<OutputIt> { + return vformat_to_n(out, n, fmt, fmt::make_format_args(args...)); +} + +/** Returns the number of chars in the output of ``format(fmt, args...)``. */ +template <typename... T> +FMT_NODISCARD FMT_INLINE auto formatted_size(format_string<T...> fmt, + T&&... args) -> size_t { + auto buf = detail::counting_buffer<>(); + detail::vformat_to(buf, string_view(fmt), fmt::make_format_args(args...), {}); + return buf.count(); +} + +FMT_API void vprint(string_view fmt, format_args args); +FMT_API void vprint(std::FILE* f, string_view fmt, format_args args); + +/** + \rst + Formats ``args`` according to specifications in ``fmt`` and writes the output + to ``stdout``. + + **Example**:: + + fmt::print("Elapsed time: {0:.2f} seconds", 1.23); + \endrst + */ +template <typename... T> +FMT_INLINE void print(format_string<T...> fmt, T&&... args) { + const auto& vargs = fmt::make_format_args(args...); + return detail::is_utf8() ? vprint(fmt, vargs) + : detail::vprint_mojibake(stdout, fmt, vargs); +} + +/** + \rst + Formats ``args`` according to specifications in ``fmt`` and writes the + output to the file ``f``. + + **Example**:: + + fmt::print(stderr, "Don't {}!", "panic"); + \endrst + */ +template <typename... T> +FMT_INLINE void print(std::FILE* f, format_string<T...> fmt, T&&... args) { + const auto& vargs = fmt::make_format_args(args...); + return detail::is_utf8() ? vprint(f, fmt, vargs) + : detail::vprint_mojibake(f, fmt, vargs); +} + +FMT_MODULE_EXPORT_END +FMT_GCC_PRAGMA("GCC pop_options") +FMT_END_NAMESPACE + +#ifdef FMT_HEADER_ONLY +# include "format.h" +#endif +#endif // FMT_CORE_H_ diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/spdlog/fmt/bundled/fmt.license.rst b/Plugins/CesiumForUnreal/Source/ThirdParty/include/spdlog/fmt/bundled/fmt.license.rst new file mode 100644 index 0000000000000000000000000000000000000000..f0ec3db4d2a03368a9f1357b38e79486bdf41076 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/spdlog/fmt/bundled/fmt.license.rst @@ -0,0 +1,27 @@ +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. diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/spdlog/fmt/bundled/format-inl.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/spdlog/fmt/bundled/format-inl.h new file mode 100644 index 0000000000000000000000000000000000000000..2c51c50aeb2007706b56d8cba05a0785645dd642 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/spdlog/fmt/bundled/format-inl.h @@ -0,0 +1,2643 @@ +// 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_ + +#include <algorithm> +#include <cctype> +#include <cerrno> // errno +#include <climits> +#include <cmath> +#include <cstdarg> +#include <cstring> // std::memmove +#include <cwchar> +#include <exception> + +#ifndef FMT_STATIC_THOUSANDS_SEPARATOR +# include <locale> +#endif + +#ifdef _WIN32 +# include <io.h> // _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 throw_format_error(const char* message) { + FMT_THROW(format_error(message)); +} + +#ifndef _MSC_VER +# define FMT_SNPRINTF snprintf +#else // _MSC_VER +inline int fmt_snprintf(char* buffer, size_t size, const char* format, ...) { + va_list args; + va_start(args, format); + int result = vsnprintf_s(buffer, size, _TRUNCATE, format, args); + va_end(args); + return result; +} +# define FMT_SNPRINTF fmt_snprintf +#endif // _MSC_VER + +FMT_FUNC void format_error_code(detail::buffer<char>& out, int error_code, + string_view message) FMT_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<uint32_or_64_or_128_t<int>>(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 = buffer_appender<char>(out); + if (message.size() <= inline_buffer_size - error_code_size) + format_to(it, FMT_STRING("{}{}"), message, SEP); + 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) FMT_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 size, size_t count, + FILE* stream) { + size_t written = std::fwrite(ptr, size, count, stream); + if (written < count) FMT_THROW(system_error(errno, "cannot write to file")); +} + +#ifndef FMT_STATIC_THOUSANDS_SEPARATOR +template <typename Locale> +locale_ref::locale_ref(const Locale& loc) : locale_(&loc) { + static_assert(std::is_same<Locale, std::locale>::value, ""); +} + +template <typename Locale> Locale locale_ref::get() const { + static_assert(std::is_same<Locale, std::locale>::value, ""); + return locale_ ? *static_cast<const std::locale*>(locale_) : std::locale(); +} + +template <typename Char> +FMT_FUNC auto thousands_sep_impl(locale_ref loc) -> thousands_sep_result<Char> { + auto& facet = std::use_facet<std::numpunct<Char>>(loc.get<std::locale>()); + auto grouping = facet.grouping(); + auto thousands_sep = grouping.empty() ? Char() : facet.thousands_sep(); + return {std::move(grouping), thousands_sep}; +} +template <typename Char> FMT_FUNC Char decimal_point_impl(locale_ref loc) { + return std::use_facet<std::numpunct<Char>>(loc.get<std::locale>()) + .decimal_point(); +} +#else +template <typename Char> +FMT_FUNC auto thousands_sep_impl(locale_ref) -> thousands_sep_result<Char> { + return {"\03", FMT_STATIC_THOUSANDS_SEPARATOR}; +} +template <typename Char> FMT_FUNC Char decimal_point_impl(locale_ref) { + return '.'; +} +#endif +} // namespace detail + +#if !FMT_MSC_VER +FMT_API FMT_FUNC format_error::~format_error() FMT_NOEXCEPT = default; +#endif + +FMT_FUNC std::system_error vsystem_error(int error_code, string_view format_str, + format_args args) { + auto ec = std::error_code(error_code, std::generic_category()); + return std::system_error(ec, vformat(format_str, args)); +} + +namespace detail { + +template <> FMT_FUNC int count_digits<4>(detail::fallback_uintptr n) { + // fallback_uintptr is always stored in little endian. + int i = static_cast<int>(sizeof(void*)) - 1; + while (i > 0 && n.value[i] == 0) --i; + auto char_digits = std::numeric_limits<unsigned char>::digits / 4; + return i >= 0 ? i * char_digits + count_digits<4, unsigned>(n.value[i]) : 1; +} + +// log10(2) = 0x0.4d104d427de7fbcc... +static constexpr uint64_t log10_2_significand = 0x4d104d427de7fbcc; + +template <typename T = void> struct basic_impl_data { + // Normalized 64-bit significands of pow(10, k), for k = -348, -340, ..., 340. + // These are generated by support/compute-powers.py. + static constexpr uint64_t pow10_significands[87] = { + 0xfa8fd5a0081c0288, 0xbaaee17fa23ebf76, 0x8b16fb203055ac76, + 0xcf42894a5dce35ea, 0x9a6bb0aa55653b2d, 0xe61acf033d1a45df, + 0xab70fe17c79ac6ca, 0xff77b1fcbebcdc4f, 0xbe5691ef416bd60c, + 0x8dd01fad907ffc3c, 0xd3515c2831559a83, 0x9d71ac8fada6c9b5, + 0xea9c227723ee8bcb, 0xaecc49914078536d, 0x823c12795db6ce57, + 0xc21094364dfb5637, 0x9096ea6f3848984f, 0xd77485cb25823ac7, + 0xa086cfcd97bf97f4, 0xef340a98172aace5, 0xb23867fb2a35b28e, + 0x84c8d4dfd2c63f3b, 0xc5dd44271ad3cdba, 0x936b9fcebb25c996, + 0xdbac6c247d62a584, 0xa3ab66580d5fdaf6, 0xf3e2f893dec3f126, + 0xb5b5ada8aaff80b8, 0x87625f056c7c4a8b, 0xc9bcff6034c13053, + 0x964e858c91ba2655, 0xdff9772470297ebd, 0xa6dfbd9fb8e5b88f, + 0xf8a95fcf88747d94, 0xb94470938fa89bcf, 0x8a08f0f8bf0f156b, + 0xcdb02555653131b6, 0x993fe2c6d07b7fac, 0xe45c10c42a2b3b06, + 0xaa242499697392d3, 0xfd87b5f28300ca0e, 0xbce5086492111aeb, + 0x8cbccc096f5088cc, 0xd1b71758e219652c, 0x9c40000000000000, + 0xe8d4a51000000000, 0xad78ebc5ac620000, 0x813f3978f8940984, + 0xc097ce7bc90715b3, 0x8f7e32ce7bea5c70, 0xd5d238a4abe98068, + 0x9f4f2726179a2245, 0xed63a231d4c4fb27, 0xb0de65388cc8ada8, + 0x83c7088e1aab65db, 0xc45d1df942711d9a, 0x924d692ca61be758, + 0xda01ee641a708dea, 0xa26da3999aef774a, 0xf209787bb47d6b85, + 0xb454e4a179dd1877, 0x865b86925b9bc5c2, 0xc83553c5c8965d3d, + 0x952ab45cfa97a0b3, 0xde469fbd99a05fe3, 0xa59bc234db398c25, + 0xf6c69a72a3989f5c, 0xb7dcbf5354e9bece, 0x88fcf317f22241e2, + 0xcc20ce9bd35c78a5, 0x98165af37b2153df, 0xe2a0b5dc971f303a, + 0xa8d9d1535ce3b396, 0xfb9b7cd9a4a7443c, 0xbb764c4ca7a44410, + 0x8bab8eefb6409c1a, 0xd01fef10a657842c, 0x9b10a4e5e9913129, + 0xe7109bfba19c0c9d, 0xac2820d9623bf429, 0x80444b5e7aa7cf85, + 0xbf21e44003acdd2d, 0x8e679c2f5e44ff8f, 0xd433179d9c8cb841, + 0x9e19db92b4e31ba9, 0xeb96bf6ebadf77d9, 0xaf87023b9bf0ee6b, + }; + +#if FMT_GCC_VERSION && FMT_GCC_VERSION < 409 +# pragma GCC diagnostic push +# pragma GCC diagnostic ignored "-Wnarrowing" +#endif + // Binary exponents of pow(10, k), for k = -348, -340, ..., 340, corresponding + // to significands above. + static constexpr int16_t pow10_exponents[87] = { + -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}; +#if FMT_GCC_VERSION && FMT_GCC_VERSION < 409 +# pragma GCC diagnostic pop +#endif + + static constexpr uint64_t power_of_10_64[20] = { + 1, FMT_POWERS_OF_10(1ULL), FMT_POWERS_OF_10(1000000000ULL), + 10000000000000000000ULL}; +}; + +// This is a struct rather than an alias to avoid shadowing warnings in gcc. +struct impl_data : basic_impl_data<> {}; + +#if __cplusplus < 201703L +template <typename T> +constexpr uint64_t basic_impl_data<T>::pow10_significands[]; +template <typename T> constexpr int16_t basic_impl_data<T>::pow10_exponents[]; +template <typename T> constexpr uint64_t basic_impl_data<T>::power_of_10_64[]; +#endif + +template <typename T> struct bits { + static FMT_CONSTEXPR_DECL const int value = + static_cast<int>(sizeof(T) * std::numeric_limits<unsigned char>::digits); +}; + +// Returns the number of significand bits in Float excluding the implicit bit. +template <typename Float> constexpr int num_significand_bits() { + // Subtract 1 to account for an implicit most significant bit in the + // normalized form. + return std::numeric_limits<Float>::digits - 1; +} + +// A floating-point number f * pow(2, e). +struct fp { + uint64_t f; + int e; + + static constexpr const int num_significand_bits = bits<decltype(f)>::value; + + constexpr fp() : f(0), e(0) {} + constexpr fp(uint64_t f_val, int e_val) : f(f_val), e(e_val) {} + + // Constructs fp from an IEEE754 floating-point number. It is a template to + // prevent compile errors on systems where n is not IEEE754. + template <typename Float> explicit FMT_CONSTEXPR fp(Float n) { assign(n); } + + template <typename Float> + using is_supported = bool_constant<sizeof(Float) == sizeof(uint64_t) || + sizeof(Float) == sizeof(uint32_t)>; + + // Assigns d to this and return true iff predecessor is closer than successor. + template <typename Float, FMT_ENABLE_IF(is_supported<Float>::value)> + FMT_CONSTEXPR bool assign(Float n) { + // Assume float is in the format [sign][exponent][significand]. + const int num_float_significand_bits = + detail::num_significand_bits<Float>(); + const uint64_t implicit_bit = 1ULL << num_float_significand_bits; + const uint64_t significand_mask = implicit_bit - 1; + constexpr bool is_double = sizeof(Float) == sizeof(uint64_t); + auto u = bit_cast<conditional_t<is_double, uint64_t, uint32_t>>(n); + f = u & significand_mask; + const uint64_t exponent_mask = (~0ULL >> 1) & ~significand_mask; + int biased_e = + static_cast<int>((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). + bool is_predecessor_closer = f == 0 && biased_e > 1; + if (biased_e != 0) + f += implicit_bit; + else + biased_e = 1; // Subnormals use biased exponent 1 (min exponent). + const int exponent_bias = std::numeric_limits<Float>::max_exponent - 1; + e = biased_e - exponent_bias - num_float_significand_bits; + return is_predecessor_closer; + } + + template <typename Float, FMT_ENABLE_IF(!is_supported<Float>::value)> + bool assign(Float) { + FMT_ASSERT(false, ""); + return false; + } +}; + +// Normalizes the value converted from double and multiplied by (1 << SHIFT). +template <int SHIFT = 0> FMT_CONSTEXPR fp normalize(fp value) { + // Handle subnormals. + const uint64_t implicit_bit = 1ULL << num_significand_bits<double>(); + 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 = + fp::num_significand_bits - num_significand_bits<double>() - SHIFT - 1; + value.f <<= offset; + value.e -= offset; + return value; +} + +inline bool operator==(fp x, fp y) { return x.f == y.f && x.e == y.e; } + +// Computes lhs * rhs / pow(2, 64) rounded to nearest with half-up tie breaking. +FMT_CONSTEXPR inline uint64_t multiply(uint64_t lhs, uint64_t rhs) { +#if FMT_USE_INT128 + auto product = static_cast<__uint128_t>(lhs) * rhs; + auto f = static_cast<uint64_t>(product >> 64); + return (static_cast<uint64_t>(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 fp operator*(fp x, fp y) { + return {multiply(x.f, y.f), x.e + y.e + 64}; +} + +// Returns a cached power of 10 `c_k = c_k.f * pow(2, c_k.e)` such that its +// (binary) exponent satisfies `min_exponent <= c_k.e <= min_exponent + 28`. +FMT_CONSTEXPR inline fp get_cached_power(int min_exponent, + int& pow10_exponent) { + const int shift = 32; + const auto significand = static_cast<int64_t>(log10_2_significand); + int index = static_cast<int>( + ((min_exponent + fp::num_significand_bits - 1) * (significand >> shift) + + ((int64_t(1) << shift) - 1)) // ceil + >> 32 // arithmetic shift + ); + // Decimal exponent of the first (smallest) cached power of 10. + const int first_dec_exp = -348; + // Difference between 2 consecutive decimal exponents in cached powers of 10. + const int dec_exp_step = 8; + index = (index - first_dec_exp - 1) / dec_exp_step + 1; + pow10_exponent = first_dec_exp + index * dec_exp_step; + return {impl_data::pow10_significands[index], + impl_data::pow10_exponents[index]}; +} + +// A simple accumulator to hold the sums of terms in bigint::square if uint128_t +// is not available. +struct accumulator { + uint64_t lower; + uint64_t upper; + + constexpr accumulator() : lower(0), upper(0) {} + constexpr explicit operator uint32_t() const { + return static_cast<uint32_t>(lower); + } + + FMT_CONSTEXPR void operator+=(uint64_t n) { + lower += n; + if (lower < n) ++upper; + } + FMT_CONSTEXPR void operator>>=(int shift) { + FMT_ASSERT(shift == 32, ""); + (void)shift; + lower = (upper << 32) | (lower >> 32); + upper >>= 32; + } +}; + +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<bigit, bigits_capacity> bigits_; + int exp_; + + FMT_CONSTEXPR20 bigit operator[](int index) const { + return bigits_[to_unsigned(index)]; + } + FMT_CONSTEXPR20 bigit& operator[](int index) { + return bigits_[to_unsigned(index)]; + } + + static FMT_CONSTEXPR_DECL const int bigit_bits = bits<bigit>::value; + + friend struct formatter<bigint>; + + FMT_CONSTEXPR20 void subtract_bigits(int index, bigit other, bigit& borrow) { + auto result = static_cast<double_bigit>((*this)[index]) - other - borrow; + (*this)[index] = static_cast<bigit>(result); + borrow = static_cast<bigit>(result >> (bigit_bits * 2 - 1)); + } + + FMT_CONSTEXPR20 void remove_leading_zeros() { + int num_bigits = static_cast<int>(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<bigit>(result); + carry = static_cast<bigit>(result >> bigit_bits); + } + if (carry != 0) bigits_.push_back(carry); + } + + FMT_CONSTEXPR20 void multiply(uint64_t value) { + const bigit mask = ~bigit(0); + const double_bigit lower = value & mask; + const double_bigit upper = value >> bigit_bits; + double_bigit carry = 0; + for (size_t i = 0, n = bigits_.size(); i < n; ++i) { + double_bigit result = bigits_[i] * lower + (carry & mask); + carry = + bigits_[i] * upper + (result >> bigit_bits) + (carry >> bigit_bits); + bigits_[i] = static_cast<bigit>(result); + } + while (carry != 0) { + bigits_.push_back(carry & mask); + carry >>= bigit_bits; + } + } + + public: + FMT_CONSTEXPR20 bigint() : exp_(0) {} + explicit bigint(uint64_t n) { assign(n); } + FMT_CONSTEXPR20 ~bigint() { + FMT_ASSERT(bigits_.capacity() <= bigits_capacity, ""); + } + + 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(); + std::copy(data, data + size, make_checked(bigits_.data(), size)); + exp_ = other.exp_; + } + + FMT_CONSTEXPR20 void assign(uint64_t n) { + size_t num_bigits = 0; + do { + bigits_[num_bigits++] = n & ~bigit(0); + n >>= bigit_bits; + } while (n != 0); + bigits_.resize(num_bigits); + exp_ = 0; + } + + FMT_CONSTEXPR20 int num_bigits() const { + return static_cast<int>(bigits_.size()) + exp_; + } + + FMT_NOINLINE FMT_CONSTEXPR20 bigint& operator<<=(int shift) { + 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 <typename Int> FMT_CONSTEXPR20 bigint& operator*=(Int value) { + FMT_ASSERT(value > 0, ""); + multiply(uint32_or_64_or_128_t<Int>(value)); + return *this; + } + + friend FMT_CONSTEXPR20 int compare(const bigint& lhs, const bigint& rhs) { + 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<int>(lhs.bigits_.size()) - 1; + int j = static_cast<int>(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 int add_compare(const bigint& lhs1, const bigint& lhs2, + const bigint& rhs) { + int max_lhs_bigits = (std::max)(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 = (std::min)((std::min)(lhs1.exp_, lhs2.exp_), rhs.exp_); + for (int i = num_rhs_bigits - 1; i >= min_exp; --i) { + double_bigit sum = + static_cast<double_bigit>(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 assign(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. + assign(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<int>(bigits_.size()); + int num_result_bigits = 2 * num_bigits; + basic_memory_buffer<bigit, bigits_capacity> n(std::move(bigits_)); + bigits_.resize(to_unsigned(num_result_bigits)); + using accumulator_t = conditional_t<FMT_USE_INT128, uint128_t, accumulator>; + auto sum = accumulator_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<double_bigit>(n[i]) * n[j]; + } + (*this)[bigit_index] = static_cast<bigit>(sum); + sum >>= bits<bigit>::value; // 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<double_bigit>(n[i++]) * n[j--]; + (*this)[bigit_index] = static_cast<bigit>(sum); + sum >>= bits<bigit>::value; + } + 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<int>(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]; + std::uninitialized_fill_n(bigits_.data(), exp_difference, 0); + exp_ -= exp_difference; + } + + // Divides this bignum by divisor, assigning the remainder to this and + // returning the quotient. + FMT_CONSTEXPR20 int divmod_assign(const bigint& divisor) { + 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; + } +}; + +enum class round_direction { unknown, up, down }; + +// Given the divisor (normally a power of 10), the remainder = v % divisor for +// some number v and the error, returns whether v should be rounded up, down, or +// whether the rounding direction can't be determined due to error. +// error should be less than divisor / 2. +FMT_CONSTEXPR inline round_direction get_round_direction(uint64_t divisor, + uint64_t remainder, + uint64_t error) { + FMT_ASSERT(remainder < divisor, ""); // divisor - remainder won't overflow. + FMT_ASSERT(error < divisor, ""); // divisor - error won't overflow. + FMT_ASSERT(error < divisor - error, ""); // error * 2 won't overflow. + // Round down if (remainder + error) * 2 <= divisor. + if (remainder <= divisor - remainder && error * 2 <= divisor - remainder * 2) + return round_direction::down; + // Round up if (remainder - error) * 2 >= divisor. + if (remainder >= error && + remainder - error >= divisor - (remainder - error)) { + return round_direction::up; + } + return round_direction::unknown; +} + +namespace digits { +enum result { + more, // Generate more digits. + done, // Done generating digits. + error // Digit generation cancelled due to an error. +}; +} + +struct gen_digits_handler { + char* buf; + int size; + int precision; + int exp10; + bool fixed; + + FMT_CONSTEXPR digits::result on_digit(char digit, uint64_t divisor, + uint64_t remainder, uint64_t error, + bool integral) { + FMT_ASSERT(remainder < divisor, ""); + buf[size++] = digit; + if (!integral && error >= remainder) return digits::error; + if (size < precision) return digits::more; + if (!integral) { + // Check if error * 2 < divisor with overflow prevention. + // The check is not needed for the integral part because error = 1 + // and divisor > (1 << 32) there. + if (error >= divisor || error >= divisor - error) return digits::error; + } else { + FMT_ASSERT(error == 1 && divisor > 2, ""); + } + auto dir = get_round_direction(divisor, remainder, error); + if (dir != round_direction::up) + return dir == round_direction::down ? digits::done : digits::error; + ++buf[size - 1]; + for (int i = size - 1; i > 0 && buf[i] > '9'; --i) { + buf[i] = '0'; + ++buf[i - 1]; + } + if (buf[0] > '9') { + buf[0] = '1'; + if (fixed) + buf[size++] = '0'; + else + ++exp10; + } + return digits::done; + } +}; + +// Generates output using the Grisu digit-gen algorithm. +// error: the size of the region (lower, upper) outside of which numbers +// definitely do not round to value (Delta in Grisu3). +FMT_INLINE FMT_CONSTEXPR20 digits::result grisu_gen_digits( + fp value, uint64_t error, int& exp, gen_digits_handler& handler) { + const fp one(1ULL << -value.e, value.e); + // The integral part of scaled value (p1 in Grisu) = value / one. It cannot be + // zero because it contains a product of two 64-bit numbers with MSB set (due + // to normalization) - 1, shifted right by at most 60 bits. + auto integral = static_cast<uint32_t>(value.f >> -one.e); + FMT_ASSERT(integral != 0, ""); + FMT_ASSERT(integral == value.f >> -one.e, ""); + // The fractional part of scaled value (p2 in Grisu) c = value % one. + uint64_t fractional = value.f & (one.f - 1); + exp = count_digits(integral); // kappa in Grisu. + // Non-fixed formats require at least one digit and no precision adjustment. + if (handler.fixed) { + // Adjust fixed precision by exponent because it is relative to decimal + // point. + int precision_offset = exp + handler.exp10; + if (precision_offset > 0 && + handler.precision > max_value<int>() - precision_offset) { + FMT_THROW(format_error("number is too big")); + } + handler.precision += precision_offset; + // Check if precision is satisfied just by leading zeros, e.g. + // format("{:.2f}", 0.001) gives "0.00" without generating any digits. + if (handler.precision <= 0) { + if (handler.precision < 0) return digits::done; + // Divide by 10 to prevent overflow. + uint64_t divisor = impl_data::power_of_10_64[exp - 1] << -one.e; + auto dir = get_round_direction(divisor, value.f / 10, error * 10); + if (dir == round_direction::unknown) return digits::error; + handler.buf[handler.size++] = dir == round_direction::up ? '1' : '0'; + return digits::done; + } + } + // Generate digits for the integral part. This can produce up to 10 digits. + do { + uint32_t digit = 0; + auto divmod_integral = [&](uint32_t divisor) { + digit = integral / divisor; + integral %= divisor; + }; + // This optimization by Milo Yip reduces the number of integer divisions by + // one per iteration. + switch (exp) { + case 10: + divmod_integral(1000000000); + break; + case 9: + divmod_integral(100000000); + break; + case 8: + divmod_integral(10000000); + break; + case 7: + divmod_integral(1000000); + break; + case 6: + divmod_integral(100000); + break; + case 5: + divmod_integral(10000); + break; + case 4: + divmod_integral(1000); + break; + case 3: + divmod_integral(100); + break; + case 2: + divmod_integral(10); + break; + case 1: + digit = integral; + integral = 0; + break; + default: + FMT_ASSERT(false, "invalid number of digits"); + } + --exp; + auto remainder = (static_cast<uint64_t>(integral) << -one.e) + fractional; + auto result = handler.on_digit(static_cast<char>('0' + digit), + impl_data::power_of_10_64[exp] << -one.e, + remainder, error, true); + if (result != digits::more) return result; + } while (exp > 0); + // Generate digits for the fractional part. + for (;;) { + fractional *= 10; + error *= 10; + char digit = static_cast<char>('0' + (fractional >> -one.e)); + fractional &= one.f - 1; + --exp; + auto result = handler.on_digit(digit, one.f, fractional, error, false); + if (result != digits::more) return result; + } +} + +// A 128-bit integer type used internally, +struct uint128_wrapper { + uint128_wrapper() = default; + +#if FMT_USE_INT128 + uint128_t internal_; + + constexpr uint128_wrapper(uint64_t high, uint64_t low) FMT_NOEXCEPT + : internal_{static_cast<uint128_t>(low) | + (static_cast<uint128_t>(high) << 64)} {} + + constexpr uint128_wrapper(uint128_t u) : internal_{u} {} + + constexpr uint64_t high() const FMT_NOEXCEPT { + return uint64_t(internal_ >> 64); + } + constexpr uint64_t low() const FMT_NOEXCEPT { return uint64_t(internal_); } + + uint128_wrapper& operator+=(uint64_t n) FMT_NOEXCEPT { + internal_ += n; + return *this; + } +#else + uint64_t high_; + uint64_t low_; + + constexpr uint128_wrapper(uint64_t high, uint64_t low) FMT_NOEXCEPT + : high_{high}, + low_{low} {} + + constexpr uint64_t high() const FMT_NOEXCEPT { return high_; } + constexpr uint64_t low() const FMT_NOEXCEPT { return low_; } + + uint128_wrapper& operator+=(uint64_t n) FMT_NOEXCEPT { +# if defined(_MSC_VER) && defined(_M_X64) + unsigned char carry = _addcarry_u64(0, low_, n, &low_); + _addcarry_u64(carry, high_, 0, &high_); + return *this; +# else + uint64_t sum = low_ + n; + high_ += (sum < low_ ? 1 : 0); + low_ = sum; + return *this; +# endif + } +#endif +}; + +// Implementation of Dragonbox algorithm: https://github.com/jk-jeon/dragonbox. +namespace dragonbox { +// Computes 128-bit result of multiplication of two 64-bit unsigned integers. +inline uint128_wrapper umul128(uint64_t x, uint64_t y) FMT_NOEXCEPT { +#if FMT_USE_INT128 + return static_cast<uint128_t>(x) * static_cast<uint128_t>(y); +#elif defined(_MSC_VER) && defined(_M_X64) + uint128_wrapper result; + result.low_ = _umul128(x, y, &result.high_); + return result; +#else + const uint64_t mask = (uint64_t(1) << 32) - uint64_t(1); + + 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 +} + +// Computes upper 64 bits of multiplication of two 64-bit unsigned integers. +inline uint64_t umul128_upper64(uint64_t x, uint64_t y) FMT_NOEXCEPT { +#if FMT_USE_INT128 + auto p = static_cast<uint128_t>(x) * static_cast<uint128_t>(y); + return static_cast<uint64_t>(p >> 64); +#elif defined(_MSC_VER) && defined(_M_X64) + return __umulh(x, y); +#else + return umul128(x, y).high(); +#endif +} + +// Computes upper 64 bits of multiplication of a 64-bit unsigned integer and a +// 128-bit unsigned integer. +inline uint64_t umul192_upper64(uint64_t x, uint128_wrapper y) FMT_NOEXCEPT { + uint128_wrapper g0 = umul128(x, y.high()); + g0 += umul128_upper64(x, y.low()); + return g0.high(); +} + +// Computes upper 32 bits of multiplication of a 32-bit unsigned integer and a +// 64-bit unsigned integer. +inline uint32_t umul96_upper32(uint32_t x, uint64_t y) FMT_NOEXCEPT { + return static_cast<uint32_t>(umul128_upper64(x, y)); +} + +// Computes middle 64 bits of multiplication of a 64-bit unsigned integer and a +// 128-bit unsigned integer. +inline uint64_t umul192_middle64(uint64_t x, uint128_wrapper y) FMT_NOEXCEPT { + uint64_t g01 = x * y.high(); + uint64_t g10 = umul128_upper64(x, y.low()); + return g01 + g10; +} + +// Computes lower 64 bits of multiplication of a 32-bit unsigned integer and a +// 64-bit unsigned integer. +inline uint64_t umul96_lower64(uint32_t x, uint64_t y) FMT_NOEXCEPT { + return x * y; +} + +// Computes floor(log10(pow(2, e))) for e in [-1700, 1700] using the method from +// https://fmt.dev/papers/Grisu-Exact.pdf#page=5, section 3.4. +inline int floor_log10_pow2(int e) FMT_NOEXCEPT { + FMT_ASSERT(e <= 1700 && e >= -1700, "too large exponent"); + const int shift = 22; + return (e * static_cast<int>(log10_2_significand >> (64 - shift))) >> shift; +} + +// Various fast log computations. +inline int floor_log2_pow10(int e) FMT_NOEXCEPT { + FMT_ASSERT(e <= 1233 && e >= -1233, "too large exponent"); + const uint64_t log2_10_integer_part = 3; + const uint64_t log2_10_fractional_digits = 0x5269e12f346e2bf9; + const int shift_amount = 19; + return (e * static_cast<int>( + (log2_10_integer_part << shift_amount) | + (log2_10_fractional_digits >> (64 - shift_amount)))) >> + shift_amount; +} +inline int floor_log10_pow2_minus_log10_4_over_3(int e) FMT_NOEXCEPT { + FMT_ASSERT(e <= 1700 && e >= -1700, "too large exponent"); + const uint64_t log10_4_over_3_fractional_digits = 0x1ffbfc2bbc780375; + const int shift_amount = 22; + return (e * static_cast<int>(log10_2_significand >> (64 - shift_amount)) - + static_cast<int>(log10_4_over_3_fractional_digits >> + (64 - shift_amount))) >> + shift_amount; +} + +// Returns true iff x is divisible by pow(2, exp). +inline bool divisible_by_power_of_2(uint32_t x, int exp) FMT_NOEXCEPT { + FMT_ASSERT(exp >= 1, ""); + FMT_ASSERT(x != 0, ""); +#ifdef FMT_BUILTIN_CTZ + return FMT_BUILTIN_CTZ(x) >= exp; +#else + return exp < num_bits<uint32_t>() && x == ((x >> exp) << exp); +#endif +} +inline bool divisible_by_power_of_2(uint64_t x, int exp) FMT_NOEXCEPT { + FMT_ASSERT(exp >= 1, ""); + FMT_ASSERT(x != 0, ""); +#ifdef FMT_BUILTIN_CTZLL + return FMT_BUILTIN_CTZLL(x) >= exp; +#else + return exp < num_bits<uint64_t>() && x == ((x >> exp) << exp); +#endif +} + +// Table entry type for divisibility test. +template <typename T> struct divtest_table_entry { + T mod_inv; + T max_quotient; +}; + +// Returns true iff x is divisible by pow(5, exp). +inline bool divisible_by_power_of_5(uint32_t x, int exp) FMT_NOEXCEPT { + FMT_ASSERT(exp <= 10, "too large exponent"); + static constexpr const divtest_table_entry<uint32_t> divtest_table[] = { + {0x00000001, 0xffffffff}, {0xcccccccd, 0x33333333}, + {0xc28f5c29, 0x0a3d70a3}, {0x26e978d5, 0x020c49ba}, + {0x3afb7e91, 0x0068db8b}, {0x0bcbe61d, 0x0014f8b5}, + {0x68c26139, 0x000431bd}, {0xae8d46a5, 0x0000d6bf}, + {0x22e90e21, 0x00002af3}, {0x3a2e9c6d, 0x00000897}, + {0x3ed61f49, 0x000001b7}}; + return x * divtest_table[exp].mod_inv <= divtest_table[exp].max_quotient; +} +inline bool divisible_by_power_of_5(uint64_t x, int exp) FMT_NOEXCEPT { + FMT_ASSERT(exp <= 23, "too large exponent"); + static constexpr const divtest_table_entry<uint64_t> divtest_table[] = { + {0x0000000000000001, 0xffffffffffffffff}, + {0xcccccccccccccccd, 0x3333333333333333}, + {0x8f5c28f5c28f5c29, 0x0a3d70a3d70a3d70}, + {0x1cac083126e978d5, 0x020c49ba5e353f7c}, + {0xd288ce703afb7e91, 0x0068db8bac710cb2}, + {0x5d4e8fb00bcbe61d, 0x0014f8b588e368f0}, + {0x790fb65668c26139, 0x000431bde82d7b63}, + {0xe5032477ae8d46a5, 0x0000d6bf94d5e57a}, + {0xc767074b22e90e21, 0x00002af31dc46118}, + {0x8e47ce423a2e9c6d, 0x0000089705f4136b}, + {0x4fa7f60d3ed61f49, 0x000001b7cdfd9d7b}, + {0x0fee64690c913975, 0x00000057f5ff85e5}, + {0x3662e0e1cf503eb1, 0x000000119799812d}, + {0xa47a2cf9f6433fbd, 0x0000000384b84d09}, + {0x54186f653140a659, 0x00000000b424dc35}, + {0x7738164770402145, 0x0000000024075f3d}, + {0xe4a4d1417cd9a041, 0x000000000734aca5}, + {0xc75429d9e5c5200d, 0x000000000170ef54}, + {0xc1773b91fac10669, 0x000000000049c977}, + {0x26b172506559ce15, 0x00000000000ec1e4}, + {0xd489e3a9addec2d1, 0x000000000002f394}, + {0x90e860bb892c8d5d, 0x000000000000971d}, + {0x502e79bf1b6f4f79, 0x0000000000001e39}, + {0xdcd618596be30fe5, 0x000000000000060b}}; + return x * divtest_table[exp].mod_inv <= divtest_table[exp].max_quotient; +} + +// Replaces n by floor(n / pow(5, N)) returning true if and only if n is +// divisible by pow(5, N). +// Precondition: n <= 2 * pow(5, N + 1). +template <int N> +bool check_divisibility_and_divide_by_pow5(uint32_t& n) FMT_NOEXCEPT { + static constexpr struct { + uint32_t magic_number; + int bits_for_comparison; + uint32_t threshold; + int shift_amount; + } infos[] = {{0xcccd, 16, 0x3333, 18}, {0xa429, 8, 0x0a, 20}}; + constexpr auto info = infos[N - 1]; + n *= info.magic_number; + const uint32_t comparison_mask = (1u << info.bits_for_comparison) - 1; + bool result = (n & comparison_mask) <= info.threshold; + n >>= info.shift_amount; + return result; +} + +// Computes floor(n / pow(10, N)) for small n and N. +// Precondition: n <= pow(10, N + 1). +template <int N> uint32_t small_division_by_pow10(uint32_t n) FMT_NOEXCEPT { + static constexpr struct { + uint32_t magic_number; + int shift_amount; + uint32_t divisor_times_10; + } infos[] = {{0xcccd, 19, 100}, {0xa3d8, 22, 1000}}; + constexpr auto info = infos[N - 1]; + FMT_ASSERT(n <= info.divisor_times_10, "n is too large"); + return n * info.magic_number >> info.shift_amount; +} + +// Computes floor(n / 10^(kappa + 1)) (float) +inline uint32_t divide_by_10_to_kappa_plus_1(uint32_t n) FMT_NOEXCEPT { + return n / float_info<float>::big_divisor; +} +// Computes floor(n / 10^(kappa + 1)) (double) +inline uint64_t divide_by_10_to_kappa_plus_1(uint64_t n) FMT_NOEXCEPT { + return umul128_upper64(n, 0x83126e978d4fdf3c) >> 9; +} + +// Various subroutines using pow10 cache +template <class T> struct cache_accessor; + +template <> struct cache_accessor<float> { + using carrier_uint = float_info<float>::carrier_uint; + using cache_entry_type = uint64_t; + + static uint64_t get_cached_power(int k) FMT_NOEXCEPT { + FMT_ASSERT(k >= float_info<float>::min_k && k <= float_info<float>::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, 0x813f3978f8940984, + 0xa18f07d736b90be5, 0xc9f2c9cd04674ede, 0xfc6f7c4045812296, + 0x9dc5ada82b70b59d, 0xc5371912364ce305, 0xf684df56c3e01bc6, + 0x9a130b963a6c115c, 0xc097ce7bc90715b3, 0xf0bdc21abb48db20, + 0x96769950b50d88f4, 0xbc143fa4e250eb31, 0xeb194f8e1ae525fd, + 0x92efd1b8d0cf37be, 0xb7abc627050305ad, 0xe596b7b0c643c719, + 0x8f7e32ce7bea5c6f, 0xb35dbf821ae4f38b, 0xe0352f62a19e306e}; + return pow10_significands[k - float_info<float>::min_k]; + } + + static carrier_uint compute_mul(carrier_uint u, + const cache_entry_type& cache) FMT_NOEXCEPT { + return umul96_upper32(u, cache); + } + + static uint32_t compute_delta(const cache_entry_type& cache, + int beta_minus_1) FMT_NOEXCEPT { + return static_cast<uint32_t>(cache >> (64 - 1 - beta_minus_1)); + } + + static bool compute_mul_parity(carrier_uint two_f, + const cache_entry_type& cache, + int beta_minus_1) FMT_NOEXCEPT { + FMT_ASSERT(beta_minus_1 >= 1, ""); + FMT_ASSERT(beta_minus_1 < 64, ""); + + return ((umul96_lower64(two_f, cache) >> (64 - beta_minus_1)) & 1) != 0; + } + + static carrier_uint compute_left_endpoint_for_shorter_interval_case( + const cache_entry_type& cache, int beta_minus_1) FMT_NOEXCEPT { + return static_cast<carrier_uint>( + (cache - (cache >> (float_info<float>::significand_bits + 2))) >> + (64 - float_info<float>::significand_bits - 1 - beta_minus_1)); + } + + static carrier_uint compute_right_endpoint_for_shorter_interval_case( + const cache_entry_type& cache, int beta_minus_1) FMT_NOEXCEPT { + return static_cast<carrier_uint>( + (cache + (cache >> (float_info<float>::significand_bits + 1))) >> + (64 - float_info<float>::significand_bits - 1 - beta_minus_1)); + } + + static carrier_uint compute_round_up_for_shorter_interval_case( + const cache_entry_type& cache, int beta_minus_1) FMT_NOEXCEPT { + return (static_cast<carrier_uint>( + cache >> + (64 - float_info<float>::significand_bits - 2 - beta_minus_1)) + + 1) / + 2; + } +}; + +template <> struct cache_accessor<double> { + using carrier_uint = float_info<double>::carrier_uint; + using cache_entry_type = uint128_wrapper; + + static uint128_wrapper get_cached_power(int k) FMT_NOEXCEPT { + FMT_ASSERT(k >= float_info<double>::min_k && k <= float_info<double>::max_k, + "k is out of range"); + + static constexpr const uint128_wrapper 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, 0xbff8f10e7a8921a4}, + {0xa321f2d7226895c7, 0xaff72d52192b6a0d}, + {0xcbea6f8ceb02bb39, 0x9bf4f8a69f764490}, + {0xfee50b7025c36a08, 0x02f236d04753d5b4}, + {0x9f4f2726179a2245, 0x01d762422c946590}, + {0xc722f0ef9d80aad6, 0x424d3ad2b7b97ef5}, + {0xf8ebad2b84e0d58b, 0xd2e0898765a7deb2}, + {0x9b934c3b330c8577, 0x63cc55f49f88eb2f}, + {0xc2781f49ffcfa6d5, 0x3cbf6b71c76b25fb}, + {0xf316271c7fc3908a, 0x8bef464e3945ef7a}, + {0x97edd871cfda3a56, 0x97758bf0e3cbb5ac}, + {0xbde94e8e43d0c8ec, 0x3d52eeed1cbea317}, + {0xed63a231d4c4fb27, 0x4ca7aaa863ee4bdd}, + {0x945e455f24fb1cf8, 0x8fe8caa93e74ef6a}, + {0xb975d6b6ee39e436, 0xb3e2fd538e122b44}, + {0xe7d34c64a9c85d44, 0x60dbbca87196b616}, + {0x90e40fbeea1d3a4a, 0xbc8955e946fe31cd}, + {0xb51d13aea4a488dd, 0x6babab6398bdbe41}, + {0xe264589a4dcdab14, 0xc696963c7eed2dd1}, + {0x8d7eb76070a08aec, 0xfc1e1de5cf543ca2}, + {0xb0de65388cc8ada8, 0x3b25a55f43294bcb}, + {0xdd15fe86affad912, 0x49ef0eb713f39ebe}, + {0x8a2dbf142dfcc7ab, 0x6e3569326c784337}, + {0xacb92ed9397bf996, 0x49c2c37f07965404}, + {0xd7e77a8f87daf7fb, 0xdc33745ec97be906}, + {0x86f0ac99b4e8dafd, 0x69a028bb3ded71a3}, + {0xa8acd7c0222311bc, 0xc40832ea0d68ce0c}, + {0xd2d80db02aabd62b, 0xf50a3fa490c30190}, + {0x83c7088e1aab65db, 0x792667c6da79e0fa}, + {0xa4b8cab1a1563f52, 0x577001b891185938}, + {0xcde6fd5e09abcf26, 0xed4c0226b55e6f86}, + {0x80b05e5ac60b6178, 0x544f8158315b05b4}, + {0xa0dc75f1778e39d6, 0x696361ae3db1c721}, + {0xc913936dd571c84c, 0x03bc3a19cd1e38e9}, + {0xfb5878494ace3a5f, 0x04ab48a04065c723}, + {0x9d174b2dcec0e47b, 0x62eb0d64283f9c76}, + {0xc45d1df942711d9a, 0x3ba5d0bd324f8394}, + {0xf5746577930d6500, 0xca8f44ec7ee36479}, + {0x9968bf6abbe85f20, 0x7e998b13cf4e1ecb}, + {0xbfc2ef456ae276e8, 0x9e3fedd8c321a67e}, + {0xefb3ab16c59b14a2, 0xc5cfe94ef3ea101e}, + {0x95d04aee3b80ece5, 0xbba1f1d158724a12}, + {0xbb445da9ca61281f, 0x2a8a6e45ae8edc97}, + {0xea1575143cf97226, 0xf52d09d71a3293bd}, + {0x924d692ca61be758, 0x593c2626705f9c56}, + {0xb6e0c377cfa2e12e, 0x6f8b2fb00c77836c}, + {0xe498f455c38b997a, 0x0b6dfb9c0f956447}, + {0x8edf98b59a373fec, 0x4724bd4189bd5eac}, + {0xb2977ee300c50fe7, 0x58edec91ec2cb657}, + {0xdf3d5e9bc0f653e1, 0x2f2967b66737e3ed}, + {0x8b865b215899f46c, 0xbd79e0d20082ee74}, + {0xae67f1e9aec07187, 0xecd8590680a3aa11}, + {0xda01ee641a708de9, 0xe80e6f4820cc9495}, + {0x884134fe908658b2, 0x3109058d147fdcdd}, + {0xaa51823e34a7eede, 0xbd4b46f0599fd415}, + {0xd4e5e2cdc1d1ea96, 0x6c9e18ac7007c91a}, + {0x850fadc09923329e, 0x03e2cf6bc604ddb0}, + {0xa6539930bf6bff45, 0x84db8346b786151c}, + {0xcfe87f7cef46ff16, 0xe612641865679a63}, + {0x81f14fae158c5f6e, 0x4fcb7e8f3f60c07e}, + {0xa26da3999aef7749, 0xe3be5e330f38f09d}, + {0xcb090c8001ab551c, 0x5cadf5bfd3072cc5}, + {0xfdcb4fa002162a63, 0x73d9732fc7c8f7f6}, + {0x9e9f11c4014dda7e, 0x2867e7fddcdd9afa}, + {0xc646d63501a1511d, 0xb281e1fd541501b8}, + {0xf7d88bc24209a565, 0x1f225a7ca91a4226}, + {0x9ae757596946075f, 0x3375788de9b06958}, + {0xc1a12d2fc3978937, 0x0052d6b1641c83ae}, + {0xf209787bb47d6b84, 0xc0678c5dbd23a49a}, + {0x9745eb4d50ce6332, 0xf840b7ba963646e0}, + {0xbd176620a501fbff, 0xb650e5a93bc3d898}, + {0xec5d3fa8ce427aff, 0xa3e51f138ab4cebe}, + {0x93ba47c980e98cdf, 0xc66f336c36b10137}, + {0xb8a8d9bbe123f017, 0xb80b0047445d4184}, + {0xe6d3102ad96cec1d, 0xa60dc059157491e5}, + {0x9043ea1ac7e41392, 0x87c89837ad68db2f}, + {0xb454e4a179dd1877, 0x29babe4598c311fb}, + {0xe16a1dc9d8545e94, 0xf4296dd6fef3d67a}, + {0x8ce2529e2734bb1d, 0x1899e4a65f58660c}, + {0xb01ae745b101e9e4, 0x5ec05dcff72e7f8f}, + {0xdc21a1171d42645d, 0x76707543f4fa1f73}, + {0x899504ae72497eba, 0x6a06494a791c53a8}, + {0xabfa45da0edbde69, 0x0487db9d17636892}, + {0xd6f8d7509292d603, 0x45a9d2845d3c42b6}, + {0x865b86925b9bc5c2, 0x0b8a2392ba45a9b2}, + {0xa7f26836f282b732, 0x8e6cac7768d7141e}, + {0xd1ef0244af2364ff, 0x3207d795430cd926}, + {0x8335616aed761f1f, 0x7f44e6bd49e807b8}, + {0xa402b9c5a8d3a6e7, 0x5f16206c9c6209a6}, + {0xcd036837130890a1, 0x36dba887c37a8c0f}, + {0x802221226be55a64, 0xc2494954da2c9789}, + {0xa02aa96b06deb0fd, 0xf2db9baa10b7bd6c}, + {0xc83553c5c8965d3d, 0x6f92829494e5acc7}, + {0xfa42a8b73abbf48c, 0xcb772339ba1f17f9}, + {0x9c69a97284b578d7, 0xff2a760414536efb}, + {0xc38413cf25e2d70d, 0xfef5138519684aba}, + {0xf46518c2ef5b8cd1, 0x7eb258665fc25d69}, + {0x98bf2f79d5993802, 0xef2f773ffbd97a61}, + {0xbeeefb584aff8603, 0xaafb550ffacfd8fa}, + {0xeeaaba2e5dbf6784, 0x95ba2a53f983cf38}, + {0x952ab45cfa97a0b2, 0xdd945a747bf26183}, + {0xba756174393d88df, 0x94f971119aeef9e4}, + {0xe912b9d1478ceb17, 0x7a37cd5601aab85d}, + {0x91abb422ccb812ee, 0xac62e055c10ab33a}, + {0xb616a12b7fe617aa, 0x577b986b314d6009}, + {0xe39c49765fdf9d94, 0xed5a7e85fda0b80b}, + {0x8e41ade9fbebc27d, 0x14588f13be847307}, + {0xb1d219647ae6b31c, 0x596eb2d8ae258fc8}, + {0xde469fbd99a05fe3, 0x6fca5f8ed9aef3bb}, + {0x8aec23d680043bee, 0x25de7bb9480d5854}, + {0xada72ccc20054ae9, 0xaf561aa79a10ae6a}, + {0xd910f7ff28069da4, 0x1b2ba1518094da04}, + {0x87aa9aff79042286, 0x90fb44d2f05d0842}, + {0xa99541bf57452b28, 0x353a1607ac744a53}, + {0xd3fa922f2d1675f2, 0x42889b8997915ce8}, + {0x847c9b5d7c2e09b7, 0x69956135febada11}, + {0xa59bc234db398c25, 0x43fab9837e699095}, + {0xcf02b2c21207ef2e, 0x94f967e45e03f4bb}, + {0x8161afb94b44f57d, 0x1d1be0eebac278f5}, + {0xa1ba1ba79e1632dc, 0x6462d92a69731732}, + {0xca28a291859bbf93, 0x7d7b8f7503cfdcfe}, + {0xfcb2cb35e702af78, 0x5cda735244c3d43e}, + {0x9defbf01b061adab, 0x3a0888136afa64a7}, + {0xc56baec21c7a1916, 0x088aaa1845b8fdd0}, + {0xf6c69a72a3989f5b, 0x8aad549e57273d45}, + {0x9a3c2087a63f6399, 0x36ac54e2f678864b}, + {0xc0cb28a98fcf3c7f, 0x84576a1bb416a7dd}, + {0xf0fdf2d3f3c30b9f, 0x656d44a2a11c51d5}, + {0x969eb7c47859e743, 0x9f644ae5a4b1b325}, + {0xbc4665b596706114, 0x873d5d9f0dde1fee}, + {0xeb57ff22fc0c7959, 0xa90cb506d155a7ea}, + {0x9316ff75dd87cbd8, 0x09a7f12442d588f2}, + {0xb7dcbf5354e9bece, 0x0c11ed6d538aeb2f}, + {0xe5d3ef282a242e81, 0x8f1668c8a86da5fa}, + {0x8fa475791a569d10, 0xf96e017d694487bc}, + {0xb38d92d760ec4455, 0x37c981dcc395a9ac}, + {0xe070f78d3927556a, 0x85bbe253f47b1417}, + {0x8c469ab843b89562, 0x93956d7478ccec8e}, + {0xaf58416654a6babb, 0x387ac8d1970027b2}, + {0xdb2e51bfe9d0696a, 0x06997b05fcc0319e}, + {0x88fcf317f22241e2, 0x441fece3bdf81f03}, + {0xab3c2fddeeaad25a, 0xd527e81cad7626c3}, + {0xd60b3bd56a5586f1, 0x8a71e223d8d3b074}, + {0x85c7056562757456, 0xf6872d5667844e49}, + {0xa738c6bebb12d16c, 0xb428f8ac016561db}, + {0xd106f86e69d785c7, 0xe13336d701beba52}, + {0x82a45b450226b39c, 0xecc0024661173473}, + {0xa34d721642b06084, 0x27f002d7f95d0190}, + {0xcc20ce9bd35c78a5, 0x31ec038df7b441f4}, + {0xff290242c83396ce, 0x7e67047175a15271}, + {0x9f79a169bd203e41, 0x0f0062c6e984d386}, + {0xc75809c42c684dd1, 0x52c07b78a3e60868}, + {0xf92e0c3537826145, 0xa7709a56ccdf8a82}, + {0x9bbcc7a142b17ccb, 0x88a66076400bb691}, + {0xc2abf989935ddbfe, 0x6acff893d00ea435}, + {0xf356f7ebf83552fe, 0x0583f6b8c4124d43}, + {0x98165af37b2153de, 0xc3727a337a8b704a}, + {0xbe1bf1b059e9a8d6, 0x744f18c0592e4c5c}, + {0xeda2ee1c7064130c, 0x1162def06f79df73}, + {0x9485d4d1c63e8be7, 0x8addcb5645ac2ba8}, + {0xb9a74a0637ce2ee1, 0x6d953e2bd7173692}, + {0xe8111c87c5c1ba99, 0xc8fa8db6ccdd0437}, + {0x910ab1d4db9914a0, 0x1d9c9892400a22a2}, + {0xb54d5e4a127f59c8, 0x2503beb6d00cab4b}, + {0xe2a0b5dc971f303a, 0x2e44ae64840fd61d}, + {0x8da471a9de737e24, 0x5ceaecfed289e5d2}, + {0xb10d8e1456105dad, 0x7425a83e872c5f47}, + {0xdd50f1996b947518, 0xd12f124e28f77719}, + {0x8a5296ffe33cc92f, 0x82bd6b70d99aaa6f}, + {0xace73cbfdc0bfb7b, 0x636cc64d1001550b}, + {0xd8210befd30efa5a, 0x3c47f7e05401aa4e}, + {0x8714a775e3e95c78, 0x65acfaec34810a71}, + {0xa8d9d1535ce3b396, 0x7f1839a741a14d0d}, + {0xd31045a8341ca07c, 0x1ede48111209a050}, + {0x83ea2b892091e44d, 0x934aed0aab460432}, + {0xa4e4b66b68b65d60, 0xf81da84d5617853f}, + {0xce1de40642e3f4b9, 0x36251260ab9d668e}, + {0x80d2ae83e9ce78f3, 0xc1d72b7c6b426019}, + {0xa1075a24e4421730, 0xb24cf65b8612f81f}, + {0xc94930ae1d529cfc, 0xdee033f26797b627}, + {0xfb9b7cd9a4a7443c, 0x169840ef017da3b1}, + {0x9d412e0806e88aa5, 0x8e1f289560ee864e}, + {0xc491798a08a2ad4e, 0xf1a6f2bab92a27e2}, + {0xf5b5d7ec8acb58a2, 0xae10af696774b1db}, + {0x9991a6f3d6bf1765, 0xacca6da1e0a8ef29}, + {0xbff610b0cc6edd3f, 0x17fd090a58d32af3}, + {0xeff394dcff8a948e, 0xddfc4b4cef07f5b0}, + {0x95f83d0a1fb69cd9, 0x4abdaf101564f98e}, + {0xbb764c4ca7a4440f, 0x9d6d1ad41abe37f1}, + {0xea53df5fd18d5513, 0x84c86189216dc5ed}, + {0x92746b9be2f8552c, 0x32fd3cf5b4e49bb4}, + {0xb7118682dbb66a77, 0x3fbc8c33221dc2a1}, + {0xe4d5e82392a40515, 0x0fabaf3feaa5334a}, + {0x8f05b1163ba6832d, 0x29cb4d87f2a7400e}, + {0xb2c71d5bca9023f8, 0x743e20e9ef511012}, + {0xdf78e4b2bd342cf6, 0x914da9246b255416}, + {0x8bab8eefb6409c1a, 0x1ad089b6c2f7548e}, + {0xae9672aba3d0c320, 0xa184ac2473b529b1}, + {0xda3c0f568cc4f3e8, 0xc9e5d72d90a2741e}, + {0x8865899617fb1871, 0x7e2fa67c7a658892}, + {0xaa7eebfb9df9de8d, 0xddbb901b98feeab7}, + {0xd51ea6fa85785631, 0x552a74227f3ea565}, + {0x8533285c936b35de, 0xd53a88958f87275f}, + {0xa67ff273b8460356, 0x8a892abaf368f137}, + {0xd01fef10a657842c, 0x2d2b7569b0432d85}, + {0x8213f56a67f6b29b, 0x9c3b29620e29fc73}, + {0xa298f2c501f45f42, 0x8349f3ba91b47b8f}, + {0xcb3f2f7642717713, 0x241c70a936219a73}, + {0xfe0efb53d30dd4d7, 0xed238cd383aa0110}, + {0x9ec95d1463e8a506, 0xf4363804324a40aa}, + {0xc67bb4597ce2ce48, 0xb143c6053edcd0d5}, + {0xf81aa16fdc1b81da, 0xdd94b7868e94050a}, + {0x9b10a4e5e9913128, 0xca7cf2b4191c8326}, + {0xc1d4ce1f63f57d72, 0xfd1c2f611f63a3f0}, + {0xf24a01a73cf2dccf, 0xbc633b39673c8cec}, + {0x976e41088617ca01, 0xd5be0503e085d813}, + {0xbd49d14aa79dbc82, 0x4b2d8644d8a74e18}, + {0xec9c459d51852ba2, 0xddf8e7d60ed1219e}, + {0x93e1ab8252f33b45, 0xcabb90e5c942b503}, + {0xb8da1662e7b00a17, 0x3d6a751f3b936243}, + {0xe7109bfba19c0c9d, 0x0cc512670a783ad4}, + {0x906a617d450187e2, 0x27fb2b80668b24c5}, + {0xb484f9dc9641e9da, 0xb1f9f660802dedf6}, + {0xe1a63853bbd26451, 0x5e7873f8a0396973}, + {0x8d07e33455637eb2, 0xdb0b487b6423e1e8}, + {0xb049dc016abc5e5f, 0x91ce1a9a3d2cda62}, + {0xdc5c5301c56b75f7, 0x7641a140cc7810fb}, + {0x89b9b3e11b6329ba, 0xa9e904c87fcb0a9d}, + {0xac2820d9623bf429, 0x546345fa9fbdcd44}, + {0xd732290fbacaf133, 0xa97c177947ad4095}, + {0x867f59a9d4bed6c0, 0x49ed8eabcccc485d}, + {0xa81f301449ee8c70, 0x5c68f256bfff5a74}, + {0xd226fc195c6a2f8c, 0x73832eec6fff3111}, + {0x83585d8fd9c25db7, 0xc831fd53c5ff7eab}, + {0xa42e74f3d032f525, 0xba3e7ca8b77f5e55}, + {0xcd3a1230c43fb26f, 0x28ce1bd2e55f35eb}, + {0x80444b5e7aa7cf85, 0x7980d163cf5b81b3}, + {0xa0555e361951c366, 0xd7e105bcc332621f}, + {0xc86ab5c39fa63440, 0x8dd9472bf3fefaa7}, + {0xfa856334878fc150, 0xb14f98f6f0feb951}, + {0x9c935e00d4b9d8d2, 0x6ed1bf9a569f33d3}, + {0xc3b8358109e84f07, 0x0a862f80ec4700c8}, + {0xf4a642e14c6262c8, 0xcd27bb612758c0fa}, + {0x98e7e9cccfbd7dbd, 0x8038d51cb897789c}, + {0xbf21e44003acdd2c, 0xe0470a63e6bd56c3}, + {0xeeea5d5004981478, 0x1858ccfce06cac74}, + {0x95527a5202df0ccb, 0x0f37801e0c43ebc8}, + {0xbaa718e68396cffd, 0xd30560258f54e6ba}, + {0xe950df20247c83fd, 0x47c6b82ef32a2069}, + {0x91d28b7416cdd27e, 0x4cdc331d57fa5441}, + {0xb6472e511c81471d, 0xe0133fe4adf8e952}, + {0xe3d8f9e563a198e5, 0x58180fddd97723a6}, + {0x8e679c2f5e44ff8f, 0x570f09eaa7ea7648}, + {0xb201833b35d63f73, 0x2cd2cc6551e513da}, + {0xde81e40a034bcf4f, 0xf8077f7ea65e58d1}, + {0x8b112e86420f6191, 0xfb04afaf27faf782}, + {0xadd57a27d29339f6, 0x79c5db9af1f9b563}, + {0xd94ad8b1c7380874, 0x18375281ae7822bc}, + {0x87cec76f1c830548, 0x8f2293910d0b15b5}, + {0xa9c2794ae3a3c69a, 0xb2eb3875504ddb22}, + {0xd433179d9c8cb841, 0x5fa60692a46151eb}, + {0x849feec281d7f328, 0xdbc7c41ba6bcd333}, + {0xa5c7ea73224deff3, 0x12b9b522906c0800}, + {0xcf39e50feae16bef, 0xd768226b34870a00}, + {0x81842f29f2cce375, 0xe6a1158300d46640}, + {0xa1e53af46f801c53, 0x60495ae3c1097fd0}, + {0xca5e89b18b602368, 0x385bb19cb14bdfc4}, + {0xfcf62c1dee382c42, 0x46729e03dd9ed7b5}, + {0x9e19db92b4e31ba9, 0x6c07a2c26a8346d1}, + {0xc5a05277621be293, 0xc7098b7305241885}, + { 0xf70867153aa2db38, + 0xb8cbee4fc66d1ea7 } +#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, 0x02f236d04753d5b4}, + {0xcde6fd5e09abcf26, 0xed4c0226b55e6f86}, + {0xa6539930bf6bff45, 0x84db8346b786151c}, + {0x865b86925b9bc5c2, 0x0b8a2392ba45a9b2}, + {0xd910f7ff28069da4, 0x1b2ba1518094da04}, + {0xaf58416654a6babb, 0x387ac8d1970027b2}, + {0x8da471a9de737e24, 0x5ceaecfed289e5d2}, + {0xe4d5e82392a40515, 0x0fabaf3feaa5334a}, + {0xb8da1662e7b00a17, 0x3d6a751f3b936243}, + { 0x95527a5202df0ccb, + 0x0f37801e0c43ebc8 } +#endif + }; + +#if FMT_USE_FULL_CACHE_DRAGONBOX + return pow10_significands[k - float_info<double>::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 constexpr const uint32_t pow10_recovery_errors[] = { + 0x50001400, 0x54044100, 0x54014555, 0x55954415, 0x54115555, 0x00000001, + 0x50000000, 0x00104000, 0x54010004, 0x05004001, 0x55555544, 0x41545555, + 0x54040551, 0x15445545, 0x51555514, 0x10000015, 0x00101100, 0x01100015, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x04450514, 0x45414110, + 0x55555145, 0x50544050, 0x15040155, 0x11054140, 0x50111514, 0x11451454, + 0x00400541, 0x00000000, 0x55555450, 0x10056551, 0x10054011, 0x55551014, + 0x69514555, 0x05151109, 0x00155555}; + + static const int compression_ratio = 27; + + // Compute base index. + int cache_index = (k - float_info<double>::min_k) / compression_ratio; + int kb = cache_index * compression_ratio + float_info<double>::min_k; + int offset = k - kb; + + // Get base cache. + uint128_wrapper 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_wrapper recovered_cache = umul128(base_cache.high(), pow5); + uint128_wrapper middle_low = + umul128(base_cache.low() - (kb < 0 ? 1u : 0u), 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_wrapper{(recovered_cache.low() >> alpha) | high_to_middle, + ((middle_low.low() >> alpha) | middle_to_low)}; + + if (kb < 0) recovered_cache += 1; + + // Get error. + int error_idx = (k - float_info<double>::min_k) / 16; + uint32_t error = (pow10_recovery_errors[error_idx] >> + ((k - float_info<double>::min_k) % 16) * 2) & + 0x3; + + // Add the error back. + FMT_ASSERT(recovered_cache.low() + error >= recovered_cache.low(), ""); + return {recovered_cache.high(), recovered_cache.low() + error}; +#endif + } + + static carrier_uint compute_mul(carrier_uint u, + const cache_entry_type& cache) FMT_NOEXCEPT { + return umul192_upper64(u, cache); + } + + static uint32_t compute_delta(cache_entry_type const& cache, + int beta_minus_1) FMT_NOEXCEPT { + return static_cast<uint32_t>(cache.high() >> (64 - 1 - beta_minus_1)); + } + + static bool compute_mul_parity(carrier_uint two_f, + const cache_entry_type& cache, + int beta_minus_1) FMT_NOEXCEPT { + FMT_ASSERT(beta_minus_1 >= 1, ""); + FMT_ASSERT(beta_minus_1 < 64, ""); + + return ((umul192_middle64(two_f, cache) >> (64 - beta_minus_1)) & 1) != 0; + } + + static carrier_uint compute_left_endpoint_for_shorter_interval_case( + const cache_entry_type& cache, int beta_minus_1) FMT_NOEXCEPT { + return (cache.high() - + (cache.high() >> (float_info<double>::significand_bits + 2))) >> + (64 - float_info<double>::significand_bits - 1 - beta_minus_1); + } + + static carrier_uint compute_right_endpoint_for_shorter_interval_case( + const cache_entry_type& cache, int beta_minus_1) FMT_NOEXCEPT { + return (cache.high() + + (cache.high() >> (float_info<double>::significand_bits + 1))) >> + (64 - float_info<double>::significand_bits - 1 - beta_minus_1); + } + + static carrier_uint compute_round_up_for_shorter_interval_case( + const cache_entry_type& cache, int beta_minus_1) FMT_NOEXCEPT { + return ((cache.high() >> + (64 - float_info<double>::significand_bits - 2 - beta_minus_1)) + + 1) / + 2; + } +}; + +// Various integer checks +template <class T> +bool is_left_endpoint_integer_shorter_interval(int exponent) FMT_NOEXCEPT { + return exponent >= + float_info< + T>::case_shorter_interval_left_endpoint_lower_threshold && + exponent <= + float_info<T>::case_shorter_interval_left_endpoint_upper_threshold; +} +template <class T> +bool is_endpoint_integer(typename float_info<T>::carrier_uint two_f, + int exponent, int minus_k) FMT_NOEXCEPT { + if (exponent < float_info<T>::case_fc_pm_half_lower_threshold) return false; + // For k >= 0. + if (exponent <= float_info<T>::case_fc_pm_half_upper_threshold) return true; + // For k < 0. + if (exponent > float_info<T>::divisibility_check_by_5_threshold) return false; + return divisible_by_power_of_5(two_f, minus_k); +} + +template <class T> +bool is_center_integer(typename float_info<T>::carrier_uint two_f, int exponent, + int minus_k) FMT_NOEXCEPT { + // Exponent for 5 is negative. + if (exponent > float_info<T>::divisibility_check_by_5_threshold) return false; + if (exponent > float_info<T>::case_fc_upper_threshold) + return divisible_by_power_of_5(two_f, minus_k); + // Both exponents are nonnegative. + if (exponent >= float_info<T>::case_fc_lower_threshold) return true; + // Exponent for 2 is negative. + return divisible_by_power_of_2(two_f, minus_k - exponent + 1); +} + +// Remove trailing zeros from n and return the number of zeros removed (float) +FMT_INLINE int remove_trailing_zeros(uint32_t& n) FMT_NOEXCEPT { +#ifdef FMT_BUILTIN_CTZ + int t = FMT_BUILTIN_CTZ(n); +#else + int t = ctz(n); +#endif + if (t > float_info<float>::max_trailing_zeros) + t = float_info<float>::max_trailing_zeros; + + const uint32_t mod_inv1 = 0xcccccccd; + const uint32_t max_quotient1 = 0x33333333; + const uint32_t mod_inv2 = 0xc28f5c29; + const uint32_t max_quotient2 = 0x0a3d70a3; + + int s = 0; + for (; s < t - 1; s += 2) { + if (n * mod_inv2 > max_quotient2) break; + n *= mod_inv2; + } + if (s < t && n * mod_inv1 <= max_quotient1) { + n *= mod_inv1; + ++s; + } + n >>= s; + return s; +} + +// Removes trailing zeros and returns the number of zeros removed (double) +FMT_INLINE int remove_trailing_zeros(uint64_t& n) FMT_NOEXCEPT { +#ifdef FMT_BUILTIN_CTZLL + int t = FMT_BUILTIN_CTZLL(n); +#else + int t = ctzll(n); +#endif + if (t > float_info<double>::max_trailing_zeros) + t = float_info<double>::max_trailing_zeros; + // Divide by 10^8 and reduce to 32-bits + // Since ret_value.significand <= (2^64 - 1) / 1000 < 10^17, + // both of the quotient and the r should fit in 32-bits + + const uint32_t mod_inv1 = 0xcccccccd; + const uint32_t max_quotient1 = 0x33333333; + const uint64_t mod_inv8 = 0xc767074b22e90e21; + const uint64_t max_quotient8 = 0x00002af31dc46118; + + // If the number is divisible by 1'0000'0000, work with the quotient + if (t >= 8) { + auto quotient_candidate = n * mod_inv8; + + if (quotient_candidate <= max_quotient8) { + auto quotient = static_cast<uint32_t>(quotient_candidate >> 8); + + int s = 8; + for (; s < t; ++s) { + if (quotient * mod_inv1 > max_quotient1) break; + quotient *= mod_inv1; + } + quotient >>= (s - 8); + n = quotient; + return s; + } + } + + // Otherwise, work with the remainder + auto quotient = static_cast<uint32_t>(n / 100000000); + auto remainder = static_cast<uint32_t>(n - 100000000 * quotient); + + if (t == 0 || remainder * mod_inv1 > max_quotient1) { + return 0; + } + remainder *= mod_inv1; + + if (t == 1 || remainder * mod_inv1 > max_quotient1) { + n = (remainder >> 1) + quotient * 10000000ull; + return 1; + } + remainder *= mod_inv1; + + if (t == 2 || remainder * mod_inv1 > max_quotient1) { + n = (remainder >> 2) + quotient * 1000000ull; + return 2; + } + remainder *= mod_inv1; + + if (t == 3 || remainder * mod_inv1 > max_quotient1) { + n = (remainder >> 3) + quotient * 100000ull; + return 3; + } + remainder *= mod_inv1; + + if (t == 4 || remainder * mod_inv1 > max_quotient1) { + n = (remainder >> 4) + quotient * 10000ull; + return 4; + } + remainder *= mod_inv1; + + if (t == 5 || remainder * mod_inv1 > max_quotient1) { + n = (remainder >> 5) + quotient * 1000ull; + return 5; + } + remainder *= mod_inv1; + + if (t == 6 || remainder * mod_inv1 > max_quotient1) { + n = (remainder >> 6) + quotient * 100ull; + return 6; + } + remainder *= mod_inv1; + + n = (remainder >> 7) + quotient * 10ull; + return 7; +} + +// The main algorithm for shorter interval case +template <class T> +FMT_INLINE decimal_fp<T> shorter_interval_case(int exponent) FMT_NOEXCEPT { + decimal_fp<T> ret_value; + // Compute k and beta + const int minus_k = floor_log10_pow2_minus_log10_4_over_3(exponent); + const int beta_minus_1 = exponent + floor_log2_pow10(-minus_k); + + // Compute xi and zi + using cache_entry_type = typename cache_accessor<T>::cache_entry_type; + const cache_entry_type cache = cache_accessor<T>::get_cached_power(-minus_k); + + auto xi = cache_accessor<T>::compute_left_endpoint_for_shorter_interval_case( + cache, beta_minus_1); + auto zi = cache_accessor<T>::compute_right_endpoint_for_shorter_interval_case( + cache, beta_minus_1); + + // If the left endpoint is not an integer, increase it + if (!is_left_endpoint_integer_shorter_interval<T>(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<T>::compute_round_up_for_shorter_interval_case( + cache, beta_minus_1); + ret_value.exponent = minus_k; + + // When tie occurs, choose one of them according to the rule + if (exponent >= float_info<T>::shorter_interval_tie_lower_threshold && + exponent <= float_info<T>::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 <typename T> decimal_fp<T> to_decimal(T x) FMT_NOEXCEPT { + // Step 1: integer promotion & Schubfach multiplier calculation. + + using carrier_uint = typename float_info<T>::carrier_uint; + using cache_entry_type = typename cache_accessor<T>::cache_entry_type; + auto br = bit_cast<carrier_uint>(x); + + // Extract significand bits and exponent bits. + const carrier_uint significand_mask = + (static_cast<carrier_uint>(1) << float_info<T>::significand_bits) - 1; + carrier_uint significand = (br & significand_mask); + int exponent = static_cast<int>((br & exponent_mask<T>()) >> + float_info<T>::significand_bits); + + if (exponent != 0) { // Check if normal. + exponent += float_info<T>::exponent_bias - float_info<T>::significand_bits; + + // Shorter interval case; proceed like Schubfach. + if (significand == 0) return shorter_interval_case<T>(exponent); + + significand |= + (static_cast<carrier_uint>(1) << float_info<T>::significand_bits); + } else { + // Subnormal case; the interval is always regular. + if (significand == 0) return {0, 0}; + exponent = float_info<T>::min_exponent - float_info<T>::significand_bits; + } + + 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<T>::kappa; + const cache_entry_type cache = cache_accessor<T>::get_cached_power(-minus_k); + const int beta_minus_1 = exponent + floor_log2_pow10(-minus_k); + + // Compute zi and deltai + // 10^kappa <= deltai < 10^(kappa + 1) + const uint32_t deltai = cache_accessor<T>::compute_delta(cache, beta_minus_1); + const carrier_uint two_fc = significand << 1; + const carrier_uint two_fr = two_fc | 1; + const carrier_uint zi = + cache_accessor<T>::compute_mul(two_fr << beta_minus_1, 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<T> ret_value; + ret_value.significand = divide_by_10_to_kappa_plus_1(zi); + uint32_t r = static_cast<uint32_t>(zi - float_info<T>::big_divisor * + ret_value.significand); + + if (r > deltai) { + goto small_divisor_case_label; + } else if (r < deltai) { + // Exclude the right endpoint if necessary + if (r == 0 && !include_right_endpoint && + is_endpoint_integer<T>(two_fr, exponent, minus_k)) { + --ret_value.significand; + r = float_info<T>::big_divisor; + goto small_divisor_case_label; + } + } else { + // r == deltai; compare fractional parts + // Check conditions in the order different from the paper + // to take advantage of short-circuiting + const carrier_uint two_fl = two_fc - 1; + if ((!include_left_endpoint || + !is_endpoint_integer<T>(two_fl, exponent, minus_k)) && + !cache_accessor<T>::compute_mul_parity(two_fl, cache, beta_minus_1)) { + goto small_divisor_case_label; + } + } + ret_value.exponent = minus_k + float_info<T>::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<T>::kappa; + + const uint32_t mask = (1u << float_info<T>::kappa) - 1; + auto dist = r - (deltai / 2) + (float_info<T>::small_divisor / 2); + + // Is dist divisible by 2^kappa? + if ((dist & mask) == 0) { + const bool approx_y_parity = + ((dist ^ (float_info<T>::small_divisor / 2)) & 1) != 0; + dist >>= float_info<T>::kappa; + + // Is dist divisible by 5^kappa? + if (check_divisibility_and_divide_by_pow5<float_info<T>::kappa>(dist)) { + ret_value.significand += dist; + + // 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 + if (cache_accessor<T>::compute_mul_parity(two_fc, cache, beta_minus_1) != + approx_y_parity) { + --ret_value.significand; + } else { + // If z^(f) >= epsilon^(f), we might have a tie + // when z^(f) == epsilon^(f), or equivalently, when y is an integer + if (is_center_integer<T>(two_fc, exponent, minus_k)) { + ret_value.significand = ret_value.significand % 2 == 0 + ? ret_value.significand + : ret_value.significand - 1; + } + } + } + // Is dist not divisible by 5^kappa? + else { + ret_value.significand += dist; + } + } + // Is dist not divisible by 2^kappa? + else { + // Since we know dist is small, we might be able to optimize the division + // better than the compiler; we are computing dist / small_divisor here + ret_value.significand += + small_division_by_pow10<float_info<T>::kappa>(dist); + } + return ret_value; +} +} // namespace dragonbox + +// 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(fp value, bool is_predecessor_closer, + int num_digits, buffer<char>& 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. + int shift = is_predecessor_closer ? 2 : 1; + uint64_t significand = value.f << shift; + if (value.e >= 0) { + numerator.assign(significand); + numerator <<= value.e; + lower.assign(1); + lower <<= value.e; + if (shift != 1) { + upper_store.assign(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 (shift != 1) { + upper_store.assign(numerator); + upper_store <<= 1; + upper = &upper_store; + } + numerator *= significand; + denominator.assign(1); + denominator <<= shift - value.e; + } else { + numerator.assign(significand); + denominator.assign_pow10(exp10); + denominator <<= shift - value.e; + lower.assign(1); + if (shift != 1) { + upper_store.assign(1ULL << 1); + upper = &upper_store; + } + } + // Invariant: value == (numerator / denominator) * pow(10, exp10). + if (num_digits < 0) { + // Generate the shortest representation. + if (!upper) upper = &lower; + bool even = (value.f & 1) == 0; + 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<char>('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) { + denominator *= 10; + auto 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<char>('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'; + ++exp10; + } + return; + } + ++digit; + } + buf[num_digits - 1] = static_cast<char>('0' + digit); +} + +template <typename Float> +FMT_HEADER_ONLY_CONSTEXPR20 int format_float(Float value, int precision, + float_specs specs, + buffer<char>& buf) { + // float is passed as double to reduce the number of instantiations. + static_assert(!std::is_same<Float, float>::value, ""); + FMT_ASSERT(value >= 0, "value is negative"); + + 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; + } + + if (specs.fallback) return snprintf_float(value, precision, specs, buf); + + if (!is_constant_evaluated() && precision < 0) { + // Use Dragonbox for the shortest format. + if (specs.binary32) { + auto dec = dragonbox::to_decimal(static_cast<float>(value)); + write<char>(buffer_appender<char>(buf), dec.significand); + return dec.exponent; + } + auto dec = dragonbox::to_decimal(static_cast<double>(value)); + write<char>(buffer_appender<char>(buf), dec.significand); + return dec.exponent; + } + + int exp = 0; + bool use_dragon = true; + if (is_fast_float<Float>()) { + // Use Grisu + Dragon4 for the given precision: + // https://www.cs.tufts.edu/~nr/cs257/archive/florian-loitsch/printf.pdf. + const int min_exp = -60; // alpha in Grisu. + int cached_exp10 = 0; // K in Grisu. + fp normalized = normalize(fp(value)); + const auto cached_pow = get_cached_power( + min_exp - (normalized.e + fp::num_significand_bits), cached_exp10); + normalized = normalized * cached_pow; + gen_digits_handler handler{buf.data(), 0, precision, -cached_exp10, fixed}; + if (grisu_gen_digits(normalized, 1, exp, handler) != digits::error && + !is_constant_evaluated()) { + exp += handler.exp10; + buf.try_resize(to_unsigned(handler.size)); + use_dragon = false; + } else { + exp += handler.size - cached_exp10 - 1; + precision = handler.precision; + } + } + if (use_dragon) { + auto f = fp(); + bool is_predecessor_closer = + specs.binary32 ? f.assign(static_cast<float>(value)) : f.assign(value); + // 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, is_predecessor_closer, 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 <typename T> +int snprintf_float(T value, int precision, float_specs specs, + buffer<char>& buf) { + // Buffer capacity must be non-zero, otherwise MSVC's vsnprintf_s will fail. + FMT_ASSERT(buf.capacity() > buf.size(), "empty buffer"); + static_assert(!std::is_same<T, float>::value, ""); + + // Subtract 1 to account for the difference in precision since we use %e for + // both general and exponent format. + if (specs.format == float_format::general || + specs.format == float_format::exp) + precision = (precision >= 0 ? precision : 6) - 1; + + // Build the format string. + enum { max_format_size = 7 }; // The longest format is "%#.*Le". + char format[max_format_size]; + char* format_ptr = format; + *format_ptr++ = '%'; + if (specs.showpoint && specs.format == float_format::hex) *format_ptr++ = '#'; + if (precision >= 0) { + *format_ptr++ = '.'; + *format_ptr++ = '*'; + } + if (std::is_same<T, long double>()) *format_ptr++ = 'L'; + *format_ptr++ = specs.format != float_format::hex + ? (specs.format == float_format::fixed ? 'f' : 'e') + : (specs.upper ? 'A' : 'a'); + *format_ptr = '\0'; + + // Format using snprintf. + auto offset = buf.size(); + for (;;) { + auto begin = buf.data() + offset; + auto capacity = buf.capacity() - offset; +#ifdef FMT_FUZZ + if (precision > 100000) + throw std::runtime_error( + "fuzz mode - avoid large allocation inside snprintf"); +#endif + // Suppress the warning about a nonliteral format string. + // Cannot use auto because of a bug in MinGW (#1532). + int (*snprintf_ptr)(char*, size_t, const char*, ...) = FMT_SNPRINTF; + int result = precision >= 0 + ? snprintf_ptr(begin, capacity, format, precision, value) + : snprintf_ptr(begin, capacity, format, value); + if (result < 0) { + // The buffer will grow exponentially. + buf.try_reserve(buf.capacity() + 1); + continue; + } + auto size = to_unsigned(result); + // Size equal to capacity means that the last character was truncated. + if (size >= capacity) { + buf.try_reserve(size + offset + 1); // Add 1 for the terminating '\0'. + continue; + } + auto is_digit = [](char c) { return c >= '0' && c <= '9'; }; + if (specs.format == float_format::fixed) { + if (precision == 0) { + buf.try_resize(size); + return 0; + } + // Find and remove the decimal point. + auto end = begin + size, p = end; + do { + --p; + } while (is_digit(*p)); + int fraction_size = static_cast<int>(end - p - 1); + std::memmove(p, p + 1, to_unsigned(fraction_size)); + buf.try_resize(size - 1); + return -fraction_size; + } + if (specs.format == float_format::hex) { + buf.try_resize(size + offset); + return 0; + } + // Find and parse the exponent. + auto end = begin + size, exp_pos = end; + do { + --exp_pos; + } while (*exp_pos != 'e'); + char sign = exp_pos[1]; + FMT_ASSERT(sign == '+' || sign == '-', ""); + int exp = 0; + auto p = exp_pos + 2; // Skip 'e' and sign. + do { + FMT_ASSERT(is_digit(*p), ""); + exp = exp * 10 + (*p++ - '0'); + } while (p != end); + if (sign == '-') exp = -exp; + int fraction_size = 0; + if (exp_pos != begin + 1) { + // Remove trailing zeros. + auto fraction_end = exp_pos - 1; + while (*fraction_end == '0') --fraction_end; + // Move the fractional part left to get rid of the decimal point. + fraction_size = static_cast<int>(fraction_end - begin - 1); + std::memmove(begin + 1, begin + 2, to_unsigned(fraction_size)); + } + buf.try_resize(to_unsigned(fraction_size) + offset + 1); + return exp - fraction_size; + } +} +} // namespace detail + +template <> struct formatter<detail::bigint> { + FMT_CONSTEXPR format_parse_context::iterator parse( + format_parse_context& ctx) { + return ctx.begin(); + } + + format_context::iterator format(const detail::bigint& n, + format_context& ctx) { + 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 = format_to(out, FMT_STRING("{:x}"), value); + first = false; + continue; + } + out = format_to(out, FMT_STRING("{:08x}"), value); + } + if (n.exp_ > 0) + out = 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<wchar_t>(cp)); + } else { + cp -= 0x10000; + buffer_.push_back(static_cast<wchar_t>(0xD800 + (cp >> 10))); + buffer_.push_back(static_cast<wchar_t>(0xDC00 + (cp & 0x3FF))); + } + return true; + }); + buffer_.push_back(0); +} + +FMT_FUNC void format_system_error(detail::buffer<char>& out, int error_code, + const char* message) FMT_NOEXCEPT { + FMT_TRY { + auto ec = std::error_code(error_code, std::generic_category()); + write(std::back_inserter(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) FMT_NOEXCEPT { + report_error(format_system_error, error_code, message); +} + +// DEPRECATED! +// This function is defined here and not inline for ABI compatiblity. +FMT_FUNC void detail::error_handler::on_error(const char* message) { + throw_format_error(message); +} + +FMT_FUNC std::string vformat(string_view fmt, format_args args) { + // 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); +} + +#ifdef _WIN32 +namespace detail { +using dword = conditional_t<sizeof(long) == 4, unsigned long, unsigned>; +extern "C" __declspec(dllimport) int __stdcall WriteConsoleW( // + void*, const void*, dword, dword*, void*); +} // namespace detail +#endif + +namespace detail { +FMT_FUNC void print(std::FILE* f, string_view text) { +#ifdef _WIN32 + auto fd = _fileno(f); + if (_isatty(fd)) { + detail::utf8_to_utf16 u16(string_view(text.data(), text.size())); + auto written = detail::dword(); + if (detail::WriteConsoleW(reinterpret_cast<void*>(_get_osfhandle(fd)), + u16.c_str(), static_cast<uint32_t>(u16.size()), + &written, nullptr)) { + return; + } + // Fallback to fwrite on failure. It can happen if the output has been + // redirected to NUL. + } +#endif + detail::fwrite_fully(text.data(), 1, text.size(), f); +} +} // namespace detail + +FMT_FUNC void vprint(std::FILE* f, string_view format_str, format_args args) { + memory_buffer buffer; + detail::vformat_to(buffer, format_str, args); + detail::print(f, {buffer.data(), buffer.size()}); +} + +#ifdef _WIN32 +// Print assuming legacy (non-Unicode) encoding. +FMT_FUNC void detail::vprint_mojibake(std::FILE* f, string_view format_str, + format_args args) { + memory_buffer buffer; + detail::vformat_to(buffer, format_str, + basic_format_args<buffer_context<char>>(args)); + fwrite_fully(buffer.data(), 1, buffer.size(), f); +} +#endif + +FMT_FUNC void vprint(string_view format_str, format_args args) { + vprint(stdout, format_str, args); +} + +FMT_END_NAMESPACE + +#endif // FMT_FORMAT_INL_H_ diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/spdlog/fmt/bundled/format.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/spdlog/fmt/bundled/format.h new file mode 100644 index 0000000000000000000000000000000000000000..ee69651ca54fef5b30945992c36b5b291515a462 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/spdlog/fmt/bundled/format.h @@ -0,0 +1,3104 @@ +/* + 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_ + +#include <cmath> // std::signbit +#include <cstdint> // uint32_t +#include <limits> // std::numeric_limits +#include <memory> // std::uninitialized_copy +#include <stdexcept> // std::runtime_error +#include <system_error> // std::system_error +#include <utility> // std::swap + +#ifdef __cpp_lib_bit_cast +# include <bit> // std::bitcast +#endif + +#include "core.h" + +#if FMT_GCC_VERSION +# define FMT_GCC_VISIBILITY_HIDDEN __attribute__((visibility("hidden"))) +#else +# define FMT_GCC_VISIBILITY_HIDDEN +#endif + +#ifdef __NVCC__ +# define FMT_CUDA_VERSION (__CUDACC_VER_MAJOR__ * 100 + __CUDACC_VER_MINOR__) +#else +# define FMT_CUDA_VERSION 0 +#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 + +#if FMT_MSC_VER +# define FMT_MSC_DEFAULT = default +#else +# define FMT_MSC_DEFAULT +#endif + +#ifndef FMT_THROW +# if FMT_EXCEPTIONS +# if FMT_MSC_VER || FMT_NVCC +FMT_BEGIN_NAMESPACE +namespace detail { +template <typename Exception> 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) \ + do { \ + FMT_ASSERT(false, (x).what()); \ + } while (false) +# endif +#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 + +#ifndef FMT_MAYBE_UNUSED +# if FMT_HAS_CPP17_ATTRIBUTE(maybe_unused) +# define FMT_MAYBE_UNUSED [[maybe_unused]] +# else +# define FMT_MAYBE_UNUSED +# endif +#endif + +// Workaround broken [[deprecated]] in the Intel, PGI and NVCC compilers. +#if FMT_ICC_VERSION || defined(__PGI) || FMT_NVCC +# define FMT_DEPRECATED_ALIAS +#else +# define FMT_DEPRECATED_ALIAS FMT_DEPRECATED +#endif + +#ifndef FMT_USE_USER_DEFINED_LITERALS +// EDG based compilers (Intel, NVIDIA, Elbrus, etc), GCC and MSVC support UDLs. +# if (FMT_HAS_FEATURE(cxx_user_literals) || FMT_GCC_VERSION >= 407 || \ + FMT_MSC_VER >= 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_VER +# 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 +# define FMT_BUILTIN_CTZ(n) __builtin_ctz(n) +# endif +# if FMT_HAS_BUILTIN(__builtin_ctzll) || FMT_GCC_VERSION || FMT_ICC_VERSION +# define FMT_BUILTIN_CTZLL(n) __builtin_ctzll(n) +# endif +#endif + +#if FMT_MSC_VER +# include <intrin.h> // _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_VER && !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<int>(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<uint32_t>(x >> 32))) return 63 ^ (r + 32); + // Scan the low 32 bits. + _BitScanReverse(&r, static_cast<uint32_t>(x)); +# endif + FMT_ASSERT(x != 0, ""); + FMT_MSC_WARNING(suppress : 6102) // Suppress a bogus static analysis warning. + return 63 ^ static_cast<int>(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<int>(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<uint32_t>(x))) return static_cast<int>(r); + // Scan the high 32 bits. + _BitScanForward(&r, static_cast<uint32_t>(x >> 32)); + r += 32; +# endif + return static_cast<int>(r); +} +# define FMT_BUILTIN_CTZLL(n) detail::ctzll(n) +} // namespace detail +FMT_END_NAMESPACE +#endif + +#ifdef FMT_HEADER_ONLY +# define FMT_HEADER_ONLY_CONSTEXPR20 FMT_CONSTEXPR20 +#else +# define FMT_HEADER_ONLY_CONSTEXPR20 +#endif + +FMT_BEGIN_NAMESPACE +namespace detail { + +template <typename Streambuf> class formatbuf : public Streambuf { + private: + using char_type = typename Streambuf::char_type; + using streamsize = decltype(std::declval<Streambuf>().sputn(nullptr, 0)); + using int_type = typename Streambuf::int_type; + using traits_type = typename Streambuf::traits_type; + + buffer<char_type>& buffer_; + + public: + explicit formatbuf(buffer<char_type>& 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<char_type>(ch)); + return ch; + } + + auto xsputn(const char_type* s, streamsize count) -> streamsize override { + buffer_.append(s, s + count); + return count; + } +}; + +// Implementation of std::bit_cast for pre-C++20. +template <typename To, typename From> +FMT_CONSTEXPR20 auto bit_cast(const From& from) -> To { + static_assert(sizeof(To) == sizeof(From), "size mismatch"); +#ifdef __cpp_lib_bit_cast + if (is_constant_evaluated()) return std::bit_cast<To>(from); +#endif + auto to = To(); + std::memcpy(&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<bytes>(1).data[0] == 0; +#endif +} + +// A fallback implementation of uintptr_t for systems that lack it. +struct fallback_uintptr { + unsigned char value[sizeof(void*)]; + + fallback_uintptr() = default; + explicit fallback_uintptr(const void* p) { + *this = bit_cast<fallback_uintptr>(p); + if (const_check(is_big_endian())) { + for (size_t i = 0, j = sizeof(void*) - 1; i < j; ++i, --j) + std::swap(value[i], value[j]); + } + } +}; +#ifdef UINTPTR_MAX +using uintptr_t = ::uintptr_t; +inline auto to_uintptr(const void* p) -> uintptr_t { + return bit_cast<uintptr_t>(p); +} +#else +using uintptr_t = fallback_uintptr; +inline auto to_uintptr(const void* p) -> fallback_uintptr { + return fallback_uintptr(p); +} +#endif + +// Returns the largest possible value for type T. Same as +// std::numeric_limits<T>::max() but shorter and not affected by the max macro. +template <typename T> constexpr auto max_value() -> T { + return (std::numeric_limits<T>::max)(); +} +template <typename T> constexpr auto num_bits() -> int { + return std::numeric_limits<T>::digits; +} +// std::numeric_limits<T>::digits may return 0 for 128-bit ints. +template <> constexpr auto num_bits<int128_t>() -> int { return 128; } +template <> constexpr auto num_bits<uint128_t>() -> int { return 128; } +template <> constexpr auto num_bits<fallback_uintptr>() -> int { + return static_cast<int>(sizeof(void*) * + std::numeric_limits<unsigned char>::digits); +} + +FMT_INLINE void assume(bool condition) { + (void)condition; +#if FMT_HAS_BUILTIN(__builtin_assume) + __builtin_assume(condition); +#endif +} + +// An approximation of iterator_t for pre-C++20 systems. +template <typename T> +using iterator_t = decltype(std::begin(std::declval<T&>())); +template <typename T> using sentinel_t = decltype(std::end(std::declval<T&>())); + +// A workaround for std::string not having mutable data() until C++17. +template <typename Char> +inline auto get_data(std::basic_string<Char>& s) -> Char* { + return &s[0]; +} +template <typename Container> +inline auto get_data(Container& c) -> typename Container::value_type* { + return c.data(); +} + +#if defined(_SECURE_SCL) && _SECURE_SCL +// Make a checked iterator to avoid MSVC warnings. +template <typename T> using checked_ptr = stdext::checked_array_iterator<T*>; +template <typename T> +constexpr auto make_checked(T* p, size_t size) -> checked_ptr<T> { + return {p, size}; +} +#else +template <typename T> using checked_ptr = T*; +template <typename T> constexpr auto make_checked(T* p, size_t) -> T* { + return p; +} +#endif + +// 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 <typename Container, FMT_ENABLE_IF(is_contiguous<Container>::value)> +#if FMT_CLANG_VERSION >= 307 && !FMT_ICC_VERSION +__attribute__((no_sanitize("undefined"))) +#endif +inline auto +reserve(std::back_insert_iterator<Container> it, size_t n) + -> checked_ptr<typename Container::value_type> { + Container& c = get_container(it); + size_t size = c.size(); + c.resize(size + n); + return make_checked(get_data(c) + size, n); +} + +template <typename T> +inline auto reserve(buffer_appender<T> it, size_t n) -> buffer_appender<T> { + buffer<T>& buf = get_container(it); + buf.try_reserve(buf.size() + n); + return it; +} + +template <typename Iterator> +constexpr auto reserve(Iterator& it, size_t) -> Iterator& { + return it; +} + +template <typename OutputIt> +using reserve_iterator = + remove_reference_t<decltype(reserve(std::declval<OutputIt&>(), 0))>; + +template <typename T, typename OutputIt> +constexpr auto to_pointer(OutputIt, size_t) -> T* { + return nullptr; +} +template <typename T> auto to_pointer(buffer_appender<T> it, size_t n) -> T* { + buffer<T>& buf = get_container(it); + auto size = buf.size(); + if (buf.capacity() < size + n) return nullptr; + buf.try_resize(size + n); + return buf.data() + size; +} + +template <typename Container, FMT_ENABLE_IF(is_contiguous<Container>::value)> +inline auto base_iterator(std::back_insert_iterator<Container>& it, + checked_ptr<typename Container::value_type>) + -> std::back_insert_iterator<Container> { + return it; +} + +template <typename Iterator> +constexpr auto base_iterator(Iterator, Iterator it) -> Iterator { + return it; +} + +// <algorithm> is spectacularly slow to compile in C++20 so use a simple fill_n +// instead (#1998). +template <typename OutputIt, typename Size, typename T> +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 <typename T, typename Size> +FMT_CONSTEXPR20 auto fill_n(T* out, Size count, char value) -> T* { + if (is_constant_evaluated()) { + return fill_n<T*, Size, T>(out, count, value); + } + std::memset(out, value, to_unsigned(count)); + return out + count; +} + +#ifdef __cpp_char8_t +using char8_type = char8_t; +#else +enum char8_type : unsigned char {}; +#endif + +template <typename OutChar, typename InputIt, typename OutputIt> +FMT_CONSTEXPR FMT_NOINLINE auto copy_str_noinline(InputIt begin, InputIt end, + OutputIt out) -> OutputIt { + return copy_str<OutChar>(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 = code_point_length(s); + const char* next = s + len; + + // Assume a four-byte character and load four bytes. Unused bits are + // shifted out. + *c = uint32_t(s[0] & masks[len]) << 18; + *c |= uint32_t(s[1] & 0x3f) << 12; + *c |= uint32_t(s[2] & 0x3f) << 6; + *c |= uint32_t(s[3] & 0x3f) << 0; + *c >>= shiftc[len]; + + // Accumulate the various error conditions. + using uchar = unsigned char; + *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 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 <typename F> +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, to_unsigned(end - buf_ptr))); + return result ? 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_str<char>(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 <typename Char> +inline auto compute_width(basic_string_view<Char> s) -> size_t { + return s.size(); +} + +// Computes approximate display width of a UTF-8 string. +FMT_CONSTEXPR inline size_t compute_width(string_view s) { + 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; + } + }; + for_each_codepoint(s, count_code_points{&num_code_points}); + return num_code_points; +} + +inline auto compute_width(basic_string_view<char8_type> s) -> size_t { + return compute_width(basic_string_view<char>( + reinterpret_cast<const char*>(s.data()), s.size())); +} + +template <typename Char> +inline auto code_point_index(basic_string_view<Char> 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(basic_string_view<char8_type> s, size_t n) + -> size_t { + const char8_type* data = s.data(); + size_t num_code_points = 0; + for (size_t i = 0, size = s.size(); i != size; ++i) { + if ((data[i] & 0xc0) != 0x80 && ++num_code_points > n) return i; + } + return s.size(); +} + +template <typename T, bool = std::is_floating_point<T>::value> +struct is_fast_float : bool_constant<std::numeric_limits<T>::is_iec559 && + sizeof(T) <= sizeof(double)> {}; +template <typename T> struct is_fast_float<T, false> : std::false_type {}; + +#ifndef FMT_USE_FULL_CACHE_DRAGONBOX +# define FMT_USE_FULL_CACHE_DRAGONBOX 0 +#endif + +template <typename T> +template <typename U> +void buffer<T>::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; + std::uninitialized_copy_n(begin, count, make_checked(ptr_ + size_, count)); + size_ += count; + begin += count; + } +} + +template <typename T, typename Enable = void> +struct is_locale : std::false_type {}; +template <typename T> +struct is_locale<T, void_t<decltype(T::classic())>> : std::true_type {}; +} // namespace detail + +FMT_MODULE_EXPORT_BEGIN + +// The number of characters to store in the basic_memory_buffer object itself +// to avoid dynamic memory allocation. +enum { inline_buffer_size = 500 }; + +/** + \rst + A dynamically growing memory buffer for trivially copyable/constructible types + with the first ``SIZE`` elements stored in the object itself. + + You can use the ``memory_buffer`` type alias for ``char`` instead. + + **Example**:: + + auto out = fmt::memory_buffer(); + format_to(std::back_inserter(out), "The answer is {}.", 42); + + This will append the following output to the ``out`` object: + + .. code-block:: none + + The answer is 42. + + The output can be converted to an ``std::string`` with ``to_string(out)``. + \endrst + */ +template <typename T, size_t SIZE = inline_buffer_size, + typename Allocator = std::allocator<T>> +class basic_memory_buffer final : public detail::buffer<T> { + private: + T store_[SIZE]; + + // Don't inherit from Allocator avoid generating type_info for it. + Allocator alloc_; + + // Deallocate memory allocated by the buffer. + FMT_CONSTEXPR20 void deallocate() { + T* data = this->data(); + if (data != store_) alloc_.deallocate(data, this->capacity()); + } + + protected: + FMT_CONSTEXPR20 void grow(size_t size) override; + + public: + using value_type = T; + using const_reference = const T&; + + FMT_CONSTEXPR20 explicit basic_memory_buffer( + const Allocator& alloc = Allocator()) + : 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); + if (detail::is_constant_evaluated()) { + detail::copy_str<T>(other.store_, other.store_ + size, + detail::make_checked(store_, capacity)); + } else { + std::uninitialized_copy(other.store_, other.store_ + size, + detail::make_checked(store_, capacity)); + } + } else { + this->set(data, capacity); + // Set pointer to the inline array so that delete is not called + // when deallocating. + other.set(other.store_, 0); + } + this->resize(size); + } + + public: + /** + \rst + Constructs a :class:`fmt::basic_memory_buffer` object moving the content + of the other object to it. + \endrst + */ + FMT_CONSTEXPR20 basic_memory_buffer(basic_memory_buffer&& other) + FMT_NOEXCEPT { + move(other); + } + + /** + \rst + Moves the content of the other ``basic_memory_buffer`` object to this one. + \endrst + */ + auto operator=(basic_memory_buffer&& other) FMT_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); } + + // Directly append data into the buffer + using detail::buffer<T>::append; + template <typename ContiguousRange> + void append(const ContiguousRange& range) { + append(range.data(), range.data() + range.size()); + } +}; + +template <typename T, size_t SIZE, typename Allocator> +FMT_CONSTEXPR20 void basic_memory_buffer<T, SIZE, Allocator>::grow( + size_t size) { +#ifdef FMT_FUZZ + if (size > 5000) throw std::runtime_error("fuzz mode - won't grow that much"); +#endif + const size_t max_size = std::allocator_traits<Allocator>::max_size(alloc_); + size_t old_capacity = this->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 = this->data(); + T* new_data = + std::allocator_traits<Allocator>::allocate(alloc_, new_capacity); + // The following code doesn't throw, so the raw pointer above doesn't leak. + std::uninitialized_copy(old_data, old_data + this->size(), + detail::make_checked(new_data, new_capacity)); + this->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 != store_) alloc_.deallocate(old_data, old_capacity); +} + +using memory_buffer = basic_memory_buffer<char>; + +template <typename T, size_t SIZE, typename Allocator> +struct is_contiguous<basic_memory_buffer<T, SIZE, Allocator>> : std::true_type { +}; + +namespace detail { +FMT_API void print(std::FILE*, string_view); +} + +/** A formatting error such as invalid format string. */ +FMT_CLASS_API +class FMT_API format_error : public std::runtime_error { + public: + explicit format_error(const char* message) : std::runtime_error(message) {} + explicit format_error(const std::string& message) + : std::runtime_error(message) {} + format_error(const format_error&) = default; + format_error& operator=(const format_error&) = default; + format_error(format_error&&) = default; + format_error& operator=(format_error&&) = default; + ~format_error() FMT_NOEXCEPT override FMT_MSC_DEFAULT; +}; + +/** + \rst + Constructs a `~fmt::format_arg_store` object that contains references + to arguments and can be implicitly converted to `~fmt::format_args`. + If ``fmt`` is a compile-time string then `make_args_checked` checks + its validity at compile time. + \endrst + */ +template <typename... Args, typename S, typename Char = char_t<S>> +FMT_INLINE auto make_args_checked(const S& fmt, + const remove_reference_t<Args>&... args) + -> format_arg_store<buffer_context<Char>, remove_reference_t<Args>...> { + static_assert( + detail::count<( + std::is_base_of<detail::view, remove_reference_t<Args>>::value && + std::is_reference<Args>::value)...>() == 0, + "passing views as lvalues is disallowed"); + detail::check_format_string<Args...>(fmt); + return {args...}; +} + +// compile-time support +namespace detail_exported { +#if FMT_USE_NONTYPE_TEMPLATE_PARAMETERS +template <typename Char, size_t N> struct fixed_string { + constexpr fixed_string(const Char (&str)[N]) { + detail::copy_str<Char, const Char*, Char*>(static_cast<const Char*>(str), + str + N, data); + } + Char data[N]{}; +}; +#endif + +// Converts a compile-time string to basic_string_view. +template <typename Char, size_t N> +constexpr auto compile_string_to_view(const Char (&s)[N]) + -> basic_string_view<Char> { + // 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<Char>::to_int_type(s[N - 1]) == 0 ? 1 : 0)}; +} +template <typename Char> +constexpr auto compile_string_to_view(detail::std_string_view<Char> s) + -> basic_string_view<Char> { + return {s.data(), s.size()}; +} +} // namespace detail_exported + +FMT_BEGIN_DETAIL_NAMESPACE + +template <typename T> struct is_integral : std::is_integral<T> {}; +template <> struct is_integral<int128_t> : std::true_type {}; +template <> struct is_integral<uint128_t> : std::true_type {}; + +template <typename T> +using is_signed = + std::integral_constant<bool, std::numeric_limits<T>::is_signed || + std::is_same<T, int128_t>::value>; + +// Returns true if value is negative, false otherwise. +// Same as `value < 0` but doesn't produce warnings if T is an unsigned type. +template <typename T, FMT_ENABLE_IF(is_signed<T>::value)> +FMT_CONSTEXPR auto is_negative(T value) -> bool { + return value < 0; +} +template <typename T, FMT_ENABLE_IF(!is_signed<T>::value)> +FMT_CONSTEXPR auto is_negative(T) -> bool { + return false; +} + +template <typename T, FMT_ENABLE_IF(std::is_floating_point<T>::value)> +FMT_CONSTEXPR auto is_supported_floating_point(T) -> uint16_t { + return (std::is_same<T, float>::value && FMT_USE_FLOAT) || + (std::is_same<T, double>::value && FMT_USE_DOUBLE) || + (std::is_same<T, long double>::value && FMT_USE_LONG_DOUBLE); +} + +// Smallest of uint32_t, uint64_t, uint128_t that is large enough to +// represent all values of an integral type T. +template <typename T> +using uint32_or_64_or_128_t = + conditional_t<num_bits<T>() <= 32 && !FMT_REDUCE_INT_INSTANTIATIONS, + uint32_t, + conditional_t<num_bits<T>() <= 64, uint64_t, uint128_t>>; +template <typename T> +using uint64_or_128_t = conditional_t<num_bits<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 const char* digits2(size_t value) { + // 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 <typename Char, typename Sign> constexpr Char sign(Sign s) { +#if !FMT_GCC_VERSION || FMT_GCC_VERSION >= 604 + static_assert(std::is_same<Sign, sign_t>::value, ""); +#endif + return static_cast<Char>("\0-+ "[s]); +} + +template <typename T> 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_t 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 <int BITS, typename UInt> +FMT_CONSTEXPR auto count_digits(UInt n) -> int { +#ifdef FMT_BUILTIN_CLZ + if (num_bits<UInt>() == 32) + return (FMT_BUILTIN_CLZ(static_cast<uint32_t>(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); +} + +template <> auto count_digits<4>(detail::fallback_uintptr n) -> int; + +#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<int>((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 <typename Int> constexpr auto digits10() FMT_NOEXCEPT -> int { + return std::numeric_limits<Int>::digits10; +} +template <> constexpr auto digits10<int128_t>() FMT_NOEXCEPT -> int { + return 38; +} +template <> constexpr auto digits10<uint128_t>() FMT_NOEXCEPT -> int { + return 38; +} + +template <typename Char> struct thousands_sep_result { + std::string grouping; + Char thousands_sep; +}; + +template <typename Char> +FMT_API auto thousands_sep_impl(locale_ref loc) -> thousands_sep_result<Char>; +template <typename Char> +inline auto thousands_sep(locale_ref loc) -> thousands_sep_result<Char> { + auto result = thousands_sep_impl<char>(loc); + return {result.grouping, Char(result.thousands_sep)}; +} +template <> +inline auto thousands_sep(locale_ref loc) -> thousands_sep_result<wchar_t> { + return thousands_sep_impl<wchar_t>(loc); +} + +template <typename Char> +FMT_API auto decimal_point_impl(locale_ref loc) -> Char; +template <typename Char> inline auto decimal_point(locale_ref loc) -> Char { + return Char(decimal_point_impl<char>(loc)); +} +template <> inline auto decimal_point(locale_ref loc) -> wchar_t { + return decimal_point_impl<wchar_t>(loc); +} + +// Compares two characters for equality. +template <typename Char> 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 <typename Char> +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<Char>(*src++); + *dst = static_cast<Char>(*src); +} + +template <typename Iterator> 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 <typename Char, typename UInt> +FMT_CONSTEXPR20 auto format_decimal(Char* out, UInt value, int size) + -> format_decimal_result<Char*> { + 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<size_t>(value % 100))); + value /= 100; + } + if (value < 10) { + *--out = static_cast<Char>('0' + value); + return {out, end}; + } + out -= 2; + copy2(out, digits2(static_cast<size_t>(value))); + return {out, end}; +} + +template <typename Char, typename UInt, typename Iterator, + FMT_ENABLE_IF(!std::is_pointer<remove_cvref_t<Iterator>>::value)> +inline auto format_decimal(Iterator out, UInt value, int size) + -> format_decimal_result<Iterator> { + // Buffer is large enough to hold all digits (digits10 + 1). + Char buffer[digits10<UInt>() + 1]; + auto end = format_decimal(buffer, value, size).end; + return {out, detail::copy_str_noinline<Char>(buffer, end, out)}; +} + +template <unsigned BASE_BITS, typename Char, typename UInt> +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 = (value & ((1 << BASE_BITS) - 1)); + *--buffer = static_cast<Char>(BASE_BITS < 4 ? static_cast<char>('0' + digit) + : digits[digit]); + } while ((value >>= BASE_BITS) != 0); + return end; +} + +template <unsigned BASE_BITS, typename Char> +auto format_uint(Char* buffer, detail::fallback_uintptr n, int num_digits, + bool = false) -> Char* { + auto char_digits = std::numeric_limits<unsigned char>::digits / 4; + int start = (num_digits + char_digits - 1) / char_digits - 1; + if (int start_digits = num_digits % char_digits) { + unsigned value = n.value[start--]; + buffer = format_uint<BASE_BITS>(buffer, value, start_digits); + } + for (; start >= 0; --start) { + unsigned value = n.value[start]; + buffer += char_digits; + auto p = buffer; + for (int i = 0; i < char_digits; ++i) { + unsigned digit = (value & ((1 << BASE_BITS) - 1)); + *--p = static_cast<Char>("0123456789abcdef"[digit]); + value >>= BASE_BITS; + } + } + return buffer; +} + +template <unsigned BASE_BITS, typename Char, typename It, typename UInt> +inline auto format_uint(It out, UInt value, int num_digits, bool upper = false) + -> It { + if (auto ptr = to_pointer<Char>(out, to_unsigned(num_digits))) { + format_uint<BASE_BITS>(ptr, value, num_digits, upper); + return out; + } + // Buffer should be large enough to hold all digits (digits / BASE_BITS + 1). + char buffer[num_bits<UInt>() / BASE_BITS + 1]; + format_uint<BASE_BITS>(buffer, value, num_digits, upper); + return detail::copy_str_noinline<Char>(buffer, buffer + num_digits, out); +} + +// A converter from UTF-8 to UTF-16. +class utf8_to_utf16 { + private: + basic_memory_buffer<wchar_t> buffer_; + + public: + FMT_API explicit utf8_to_utf16(string_view s); + operator basic_string_view<wchar_t>() 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()}; } +}; + +namespace dragonbox { + +// Type-specific information that Dragonbox uses. +template <class T> struct float_info; + +template <> struct float_info<float> { + using carrier_uint = uint32_t; + static const int significand_bits = 23; + static const int exponent_bits = 8; + static const int min_exponent = -126; + static const int max_exponent = 127; + static const int exponent_bias = -127; + static const int decimal_digits = 9; + 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 cache_bits = 64; + static const int divisibility_check_by_5_threshold = 39; + static const int case_fc_pm_half_lower_threshold = -1; + static const int case_fc_pm_half_upper_threshold = 6; + static const int case_fc_lower_threshold = -2; + static const int case_fc_upper_threshold = 6; + static const int case_shorter_interval_left_endpoint_lower_threshold = 2; + static const int case_shorter_interval_left_endpoint_upper_threshold = 3; + static const int shorter_interval_tie_lower_threshold = -35; + static const int shorter_interval_tie_upper_threshold = -35; + static const int max_trailing_zeros = 7; +}; + +template <> struct float_info<double> { + using carrier_uint = uint64_t; + static const int significand_bits = 52; + static const int exponent_bits = 11; + static const int min_exponent = -1022; + static const int max_exponent = 1023; + static const int exponent_bias = -1023; + static const int decimal_digits = 17; + 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 = 326; + static const int cache_bits = 128; + static const int divisibility_check_by_5_threshold = 86; + static const int case_fc_pm_half_lower_threshold = -2; + static const int case_fc_pm_half_upper_threshold = 9; + static const int case_fc_lower_threshold = -4; + static const int case_fc_upper_threshold = 9; + static const int case_shorter_interval_left_endpoint_lower_threshold = 2; + static const int case_shorter_interval_left_endpoint_upper_threshold = 3; + static const int shorter_interval_tie_lower_threshold = -77; + static const int shorter_interval_tie_upper_threshold = -77; + static const int max_trailing_zeros = 16; +}; + +template <typename T> struct decimal_fp { + using significand_type = typename float_info<T>::carrier_uint; + significand_type significand; + int exponent; +}; + +template <typename T> +FMT_API auto to_decimal(T x) FMT_NOEXCEPT -> decimal_fp<T>; +} // namespace dragonbox + +template <typename T> +constexpr auto exponent_mask() -> + typename dragonbox::float_info<T>::carrier_uint { + using uint = typename dragonbox::float_info<T>::carrier_uint; + return ((uint(1) << dragonbox::float_info<T>::exponent_bits) - 1) + << dragonbox::float_info<T>::significand_bits; +} + +// Writes the exponent exp in the form "[+-]d{2,3}" to buffer. +template <typename Char, typename It> +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<Char>('-'); + exp = -exp; + } else { + *it++ = static_cast<Char>('+'); + } + if (exp >= 100) { + const char* top = digits2(to_unsigned(exp / 100)); + if (exp >= 1000) *it++ = static_cast<Char>(top[0]); + *it++ = static_cast<Char>(top[1]); + exp %= 100; + } + const char* d = digits2(to_unsigned(exp)); + *it++ = static_cast<Char>(d[0]); + *it++ = static_cast<Char>(d[1]); + return it; +} + +template <typename T> +FMT_HEADER_ONLY_CONSTEXPR20 auto format_float(T value, int precision, + float_specs specs, + buffer<char>& buf) -> int; + +// Formats a floating-point number with snprintf. +template <typename T> +auto snprintf_float(T value, int precision, float_specs specs, + buffer<char>& buf) -> int; + +template <typename T> constexpr auto promote_float(T value) -> T { + return value; +} +constexpr auto promote_float(float value) -> double { + return static_cast<double>(value); +} + +template <typename OutputIt, typename Char> +FMT_NOINLINE FMT_CONSTEXPR auto fill(OutputIt it, size_t n, + const fill_t<Char>& fill) -> OutputIt { + auto fill_size = fill.size(); + if (fill_size == 1) return detail::fill_n(it, n, fill[0]); + auto data = fill.data(); + for (size_t i = 0; i < n; ++i) + it = copy_str<Char>(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 <align::type align = align::left, typename OutputIt, typename Char, + typename F> +FMT_CONSTEXPR auto write_padded(OutputIt out, + const basic_format_specs<Char>& 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 <align::type align = align::left, typename OutputIt, typename Char, + typename F> +constexpr auto write_padded(OutputIt out, const basic_format_specs<Char>& specs, + size_t size, F&& f) -> OutputIt { + return write_padded<align>(out, specs, size, size, f); +} + +template <align::type align = align::left, typename Char, typename OutputIt> +FMT_CONSTEXPR auto write_bytes(OutputIt out, string_view bytes, + const basic_format_specs<Char>& specs) + -> OutputIt { + return write_padded<align>( + out, specs, bytes.size(), [bytes](reserve_iterator<OutputIt> it) { + const char* data = bytes.data(); + return copy_str<Char>(data, data + bytes.size(), it); + }); +} + +template <typename Char, typename OutputIt, typename UIntPtr> +auto write_ptr(OutputIt out, UIntPtr value, + const basic_format_specs<Char>* specs) -> OutputIt { + int num_digits = count_digits<4>(value); + auto size = to_unsigned(num_digits) + size_t(2); + auto write = [=](reserve_iterator<OutputIt> it) { + *it++ = static_cast<Char>('0'); + *it++ = static_cast<Char>('x'); + return format_uint<4, Char>(it, value, num_digits); + }; + return specs ? write_padded<align::right>(out, *specs, size, write) + : base_iterator(out, write(reserve(out, size))); +} + +template <typename Char, typename OutputIt> +FMT_CONSTEXPR auto write_char(OutputIt out, Char value, + const basic_format_specs<Char>& specs) + -> OutputIt { + return write_padded(out, specs, 1, [=](reserve_iterator<OutputIt> it) { + *it++ = value; + return it; + }); +} +template <typename Char, typename OutputIt> +FMT_CONSTEXPR auto write(OutputIt out, Char value, + const basic_format_specs<Char>& specs, + locale_ref loc = {}) -> OutputIt { + return check_char_specs(specs) + ? write_char(out, value, specs) + : write(out, static_cast<int>(value), specs, loc); +} + +// Data for write_int that doesn't depend on output iterator type. It is used to +// avoid template code bloat. +template <typename Char> struct write_int_data { + size_t size; + size_t padding; + + FMT_CONSTEXPR write_int_data(int num_digits, unsigned prefix, + const basic_format_specs<Char>& 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 +// <left-padding><prefix><numeric-padding><digits><right-padding> +// where <digits> are written by write_digits(it). +// prefix contains chars in three lower bytes and the size in the fourth byte. +template <typename OutputIt, typename Char, typename W> +FMT_CONSTEXPR FMT_INLINE auto write_int(OutputIt out, int num_digits, + unsigned prefix, + const basic_format_specs<Char>& 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<Char>(p & 0xff); + } + return base_iterator(out, write_digits(it)); + } + auto data = write_int_data<Char>(num_digits, prefix, specs); + return write_padded<align::right>( + out, specs, data.size, [=](reserve_iterator<OutputIt> it) { + for (unsigned p = prefix & 0xffffff; p != 0; p >>= 8) + *it++ = static_cast<Char>(p & 0xff); + it = detail::fill_n(it, data.padding, static_cast<Char>('0')); + return write_digits(it); + }); +} + +template <typename Char> class digit_grouping { + private: + thousands_sep_result<Char> sep_; + + struct next_state { + std::string::const_iterator group; + int pos; + }; + next_state initial_state() const { return {sep_.grouping.begin(), 0}; } + + // Returns the next digit group separator position. + int next(next_state& state) const { + if (!sep_.thousands_sep) return max_value<int>(); + if (state.group == sep_.grouping.end()) + return state.pos += sep_.grouping.back(); + if (*state.group <= 0 || *state.group == max_value<char>()) + return max_value<int>(); + state.pos += *state.group++; + return state.pos; + } + + public: + explicit digit_grouping(locale_ref loc, bool localized = true) { + if (localized) + sep_ = thousands_sep<Char>(loc); + else + sep_.thousands_sep = Char(); + } + explicit digit_grouping(thousands_sep_result<Char> sep) : sep_(sep) {} + + Char separator() const { return sep_.thousands_sep; } + + int count_separators(int num_digits) const { + 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 <typename Out, typename C> + Out apply(Out out, basic_string_view<C> digits) const { + auto num_digits = static_cast<int>(digits.size()); + auto separators = basic_memory_buffer<int>(); + 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<int>(separators.size() - 1); + i < num_digits; ++i) { + if (num_digits - i == separators[sep_index]) { + *out++ = separator(); + --sep_index; + } + *out++ = static_cast<Char>(digits[to_unsigned(i)]); + } + return out; + } +}; + +template <typename OutputIt, typename UInt, typename Char> +auto write_int_localized(OutputIt out, UInt value, unsigned prefix, + const basic_format_specs<Char>& specs, + const digit_grouping<Char>& grouping) -> OutputIt { + static_assert(std::is_same<uint64_or_128_t<UInt>, UInt>::value, ""); + int num_digits = count_digits(value); + char digits[40]; + format_decimal(digits, value, num_digits); + unsigned size = to_unsigned((prefix != 0 ? 1 : 0) + num_digits + + grouping.count_separators(num_digits)); + return write_padded<align::right>( + out, specs, size, size, [&](reserve_iterator<OutputIt> it) { + if (prefix != 0) *it++ = static_cast<Char>(prefix); + return grouping.apply(it, string_view(digits, to_unsigned(num_digits))); + }); +} + +template <typename OutputIt, typename UInt, typename Char> +auto write_int_localized(OutputIt& out, UInt value, unsigned prefix, + const basic_format_specs<Char>& specs, locale_ref loc) + -> bool { + auto grouping = digit_grouping<Char>(loc); + out = write_int_localized(out, value, prefix, specs, grouping); + return true; +} + +FMT_CONSTEXPR inline void prefix_append(unsigned& prefix, unsigned value) { + prefix |= prefix != 0 ? value << 8 : value; + prefix += (1u + (value > 0xff ? 1 : 0)) << 24; +} + +template <typename UInt> struct write_int_arg { + UInt abs_value; + unsigned prefix; +}; + +template <typename T> +FMT_CONSTEXPR auto make_write_int_arg(T value, sign_t sign) + -> write_int_arg<uint32_or_64_or_128_t<T>> { + auto prefix = 0u; + auto abs_value = static_cast<uint32_or_64_or_128_t<T>>(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 <typename Char, typename OutputIt, typename T> +FMT_CONSTEXPR FMT_INLINE auto write_int(OutputIt out, write_int_arg<T> arg, + const basic_format_specs<Char>& specs, + locale_ref loc) -> OutputIt { + static_assert(std::is_same<T, uint32_or_64_or_128_t<T>>::value, ""); + auto abs_value = arg.abs_value; + auto prefix = arg.prefix; + switch (specs.type) { + case presentation_type::none: + case presentation_type::dec: { + if (specs.localized && + write_int_localized(out, static_cast<uint64_or_128_t<T>>(abs_value), + prefix, specs, loc)) { + return out; + } + auto num_digits = count_digits(abs_value); + return write_int( + out, num_digits, prefix, specs, [=](reserve_iterator<OutputIt> it) { + return format_decimal<Char>(it, abs_value, num_digits).end; + }); + } + case presentation_type::hex_lower: + case presentation_type::hex_upper: { + bool upper = specs.type == presentation_type::hex_upper; + if (specs.alt) + prefix_append(prefix, unsigned(upper ? 'X' : 'x') << 8 | '0'); + int num_digits = count_digits<4>(abs_value); + return write_int( + out, num_digits, prefix, specs, [=](reserve_iterator<OutputIt> it) { + return format_uint<4, Char>(it, abs_value, num_digits, upper); + }); + } + case presentation_type::bin_lower: + case presentation_type::bin_upper: { + bool upper = specs.type == presentation_type::bin_upper; + if (specs.alt) + prefix_append(prefix, unsigned(upper ? 'B' : 'b') << 8 | '0'); + int num_digits = count_digits<1>(abs_value); + return write_int(out, num_digits, prefix, specs, + [=](reserve_iterator<OutputIt> it) { + return format_uint<1, Char>(it, abs_value, num_digits); + }); + } + 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<OutputIt> it) { + return format_uint<3, Char>(it, abs_value, num_digits); + }); + } + case presentation_type::chr: + return write_char(out, static_cast<Char>(abs_value), specs); + default: + throw_format_error("invalid type specifier"); + } + return out; +} +template <typename Char, typename OutputIt, typename T> +FMT_CONSTEXPR FMT_NOINLINE auto write_int_noinline( + OutputIt out, write_int_arg<T> arg, const basic_format_specs<Char>& specs, + locale_ref loc) -> OutputIt { + return write_int(out, arg, specs, loc); +} +template <typename Char, typename OutputIt, typename T, + FMT_ENABLE_IF(is_integral<T>::value && + !std::is_same<T, bool>::value && + std::is_same<OutputIt, buffer_appender<Char>>::value)> +FMT_CONSTEXPR FMT_INLINE auto write(OutputIt out, T value, + const basic_format_specs<Char>& specs, + locale_ref loc) -> OutputIt { + 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 <typename Char, typename OutputIt, typename T, + FMT_ENABLE_IF(is_integral<T>::value && + !std::is_same<T, bool>::value && + !std::is_same<OutputIt, buffer_appender<Char>>::value)> +FMT_CONSTEXPR FMT_INLINE auto write(OutputIt out, T value, + const basic_format_specs<Char>& specs, + locale_ref loc) -> OutputIt { + return write_int(out, make_write_int_arg(value, specs.sign), specs, loc); +} + +template <typename Char, typename OutputIt> +FMT_CONSTEXPR auto write(OutputIt out, basic_string_view<Char> s, + const basic_format_specs<Char>& 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)); + auto width = + specs.width != 0 ? compute_width(basic_string_view<Char>(data, size)) : 0; + return write_padded(out, specs, size, width, + [=](reserve_iterator<OutputIt> it) { + return copy_str<Char>(data, data + size, it); + }); +} +template <typename Char, typename OutputIt> +FMT_CONSTEXPR auto write(OutputIt out, + basic_string_view<type_identity_t<Char>> s, + const basic_format_specs<Char>& specs, locale_ref) + -> OutputIt { + check_string_type_spec(specs.type); + return write(out, s, specs); +} +template <typename Char, typename OutputIt> +FMT_CONSTEXPR auto write(OutputIt out, const Char* s, + const basic_format_specs<Char>& specs, locale_ref) + -> OutputIt { + return check_cstring_type_spec(specs.type) + ? write(out, basic_string_view<Char>(s), specs, {}) + : write_ptr<Char>(out, to_uintptr(s), &specs); +} + +template <typename Char, typename OutputIt> +FMT_CONSTEXPR20 auto write_nonfinite(OutputIt out, bool isinf, + basic_format_specs<Char> specs, + const float_specs& fspecs) -> OutputIt { + auto str = + isinf ? (fspecs.upper ? "INF" : "inf") : (fspecs.upper ? "NAN" : "nan"); + constexpr size_t str_size = 3; + auto sign = fspecs.sign; + 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.data() == static_cast<Char>('0'); + if (is_zero_fill) specs.fill[0] = static_cast<Char>(' '); + return write_padded(out, specs, size, [=](reserve_iterator<OutputIt> it) { + if (sign) *it++ = detail::sign<Char>(sign); + return copy_str<Char>(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& fp) -> int { + return fp.significand_size; +} +template <typename T> +inline auto get_significand_size(const dragonbox::decimal_fp<T>& fp) -> int { + return count_digits(fp.significand); +} + +template <typename Char, typename OutputIt> +constexpr auto write_significand(OutputIt out, const char* significand, + int significand_size) -> OutputIt { + return copy_str<Char>(significand, significand + significand_size, out); +} +template <typename Char, typename OutputIt, typename UInt> +inline auto write_significand(OutputIt out, UInt significand, + int significand_size) -> OutputIt { + return format_decimal<Char>(out, significand, significand_size).end; +} +template <typename Char, typename OutputIt, typename T, typename Grouping> +FMT_CONSTEXPR20 auto write_significand(OutputIt out, T significand, + int significand_size, int exponent, + const Grouping& grouping) -> OutputIt { + if (!grouping.separator()) { + out = write_significand<Char>(out, significand, significand_size); + return detail::fill_n(out, exponent, static_cast<Char>('0')); + } + auto buffer = memory_buffer(); + write_significand<char>(appender(buffer), significand, significand_size); + detail::fill_n(appender(buffer), exponent, '0'); + return grouping.apply(out, string_view(buffer.data(), buffer.size())); +} + +template <typename Char, typename UInt, + FMT_ENABLE_IF(std::is_integral<UInt>::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(significand % 100)); + significand /= 100; + } + if (floating_size % 2 != 0) { + *--out = static_cast<Char>('0' + significand % 10); + significand /= 10; + } + *--out = decimal_point; + format_decimal(out - integral_size, significand, integral_size); + return end; +} + +template <typename OutputIt, typename UInt, typename Char, + FMT_ENABLE_IF(!std::is_pointer<remove_cvref_t<OutputIt>>::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<UInt>() + 2]; + auto end = write_significand(buffer, significand, significand_size, + integral_size, decimal_point); + return detail::copy_str_noinline<Char>(buffer, end, out); +} + +template <typename OutputIt, typename Char> +FMT_CONSTEXPR auto write_significand(OutputIt out, const char* significand, + int significand_size, int integral_size, + Char decimal_point) -> OutputIt { + out = detail::copy_str_noinline<Char>(significand, + significand + integral_size, out); + if (!decimal_point) return out; + *out++ = decimal_point; + return detail::copy_str_noinline<Char>(significand + integral_size, + significand + significand_size, out); +} + +template <typename OutputIt, typename Char, typename T, typename Grouping> +FMT_CONSTEXPR20 auto write_significand(OutputIt out, T significand, + int significand_size, int integral_size, + Char decimal_point, + const Grouping& grouping) -> OutputIt { + if (!grouping.separator()) { + return write_significand(out, significand, significand_size, integral_size, + decimal_point); + } + auto buffer = basic_memory_buffer<Char>(); + write_significand(buffer_appender<Char>(buffer), significand, + significand_size, integral_size, decimal_point); + grouping.apply( + out, basic_string_view<Char>(buffer.data(), to_unsigned(integral_size))); + return detail::copy_str_noinline<Char>(buffer.data() + integral_size, + buffer.end(), out); +} + +template <typename OutputIt, typename DecimalFP, typename Char, + typename Grouping = digit_grouping<Char>> +FMT_CONSTEXPR20 auto do_write_float(OutputIt out, const DecimalFP& fp, + const basic_format_specs<Char>& specs, + float_specs fspecs, locale_ref loc) + -> OutputIt { + auto significand = fp.significand; + int significand_size = get_significand_size(fp); + constexpr Char zero = static_cast<Char>('0'); + auto sign = fspecs.sign; + size_t size = to_unsigned(significand_size) + (sign ? 1 : 0); + using iterator = reserve_iterator<OutputIt>; + + Char decimal_point = + fspecs.locale ? detail::decimal_point<Char>(loc) : static_cast<Char>('.'); + + int output_exp = fp.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 = fspecs.upper ? 'E' : 'e'; + auto write = [=](iterator it) { + if (sign) *it++ = detail::sign<Char>(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<Char>(exp_char); + return write_exponent<Char>(output_exp, it); + }; + return specs.width > 0 ? write_padded<align::right>(out, specs, size, write) + : base_iterator(out, write(reserve(out, size))); + } + + int exp = fp.exponent + significand_size; + if (fp.exponent >= 0) { + // 1234e5 -> 123400000[.0+] + size += to_unsigned(fp.exponent); + int num_zeros = fspecs.precision - exp; +#ifdef FMT_FUZZ + if (num_zeros > 5000) + throw std::runtime_error("fuzz mode - avoiding excessive cpu use"); +#endif + if (fspecs.showpoint) { + if (num_zeros <= 0 && fspecs.format != float_format::fixed) num_zeros = 1; + if (num_zeros > 0) size += to_unsigned(num_zeros) + 1; + } + auto grouping = Grouping(loc, fspecs.locale); + size += to_unsigned(grouping.count_separators(significand_size)); + return write_padded<align::right>(out, specs, size, [&](iterator it) { + if (sign) *it++ = detail::sign<Char>(sign); + it = write_significand<Char>(it, significand, significand_size, + fp.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(significand_size)); + return write_padded<align::right>(out, specs, size, [&](iterator it) { + if (sign) *it++ = detail::sign<Char>(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<align::right>(out, specs, size, [&](iterator it) { + if (sign) *it++ = detail::sign<Char>(sign); + *it++ = zero; + if (!pointy) return it; + *it++ = decimal_point; + it = detail::fill_n(it, num_zeros, zero); + return write_significand<Char>(it, significand, significand_size); + }); +} + +template <typename Char> class fallback_digit_grouping { + public: + constexpr fallback_digit_grouping(locale_ref, bool) {} + + constexpr Char separator() const { return Char(); } + + constexpr int count_separators(int) const { return 0; } + + template <typename Out, typename C> + constexpr Out apply(Out out, basic_string_view<C>) const { + return out; + } +}; + +template <typename OutputIt, typename DecimalFP, typename Char> +FMT_CONSTEXPR20 auto write_float(OutputIt out, const DecimalFP& fp, + const basic_format_specs<Char>& specs, + float_specs fspecs, locale_ref loc) + -> OutputIt { + if (is_constant_evaluated()) { + return do_write_float<OutputIt, DecimalFP, Char, + fallback_digit_grouping<Char>>(out, fp, specs, fspecs, + loc); + } else { + return do_write_float(out, fp, specs, fspecs, loc); + } +} + +template <typename T, FMT_ENABLE_IF(std::is_floating_point<T>::value)> +FMT_CONSTEXPR20 bool isinf(T value) { + if (is_constant_evaluated()) { +#if defined(__cpp_if_constexpr) + if constexpr (std::numeric_limits<double>::is_iec559) { + auto bits = detail::bit_cast<uint64_t>(static_cast<double>(value)); + constexpr auto significand_bits = + dragonbox::float_info<double>::significand_bits; + return (bits & exponent_mask<double>()) && + !(bits & ((uint64_t(1) << significand_bits) - 1)); + } +#endif + } + return std::isinf(value); +} + +template <typename T, FMT_ENABLE_IF(std::is_floating_point<T>::value)> +FMT_CONSTEXPR20 bool isfinite(T value) { + if (is_constant_evaluated()) { +#if defined(__cpp_if_constexpr) + if constexpr (std::numeric_limits<double>::is_iec559) { + auto bits = detail::bit_cast<uint64_t>(static_cast<double>(value)); + return (bits & exponent_mask<double>()) != exponent_mask<double>(); + } +#endif + } + return std::isfinite(value); +} + +template <typename T, FMT_ENABLE_IF(std::is_floating_point<T>::value)> +FMT_INLINE FMT_CONSTEXPR bool signbit(T value) { + if (is_constant_evaluated()) { +#ifdef __cpp_if_constexpr + if constexpr (std::numeric_limits<double>::is_iec559) { + auto bits = detail::bit_cast<uint64_t>(static_cast<double>(value)); + return (bits & (uint64_t(1) << (num_bits<uint64_t>() - 1))) != 0; + } +#endif + } + return std::signbit(value); +} + +template <typename Char, typename OutputIt, typename T, + FMT_ENABLE_IF(std::is_floating_point<T>::value)> +FMT_CONSTEXPR20 auto write(OutputIt out, T value, + basic_format_specs<Char> specs, locale_ref loc = {}) + -> OutputIt { + if (const_check(!is_supported_floating_point(value))) return out; + float_specs fspecs = parse_float_type_spec(specs); + fspecs.sign = specs.sign; + if (detail::signbit(value)) { // value < 0 is false for NaN so use signbit. + fspecs.sign = sign::minus; + value = -value; + } else if (fspecs.sign == sign::minus) { + fspecs.sign = sign::none; + } + + if (!detail::isfinite(value)) + return write_nonfinite(out, detail::isinf(value), specs, fspecs); + + if (specs.align == align::numeric && fspecs.sign) { + auto it = reserve(out, 1); + *it++ = detail::sign<Char>(fspecs.sign); + out = base_iterator(out, it); + fspecs.sign = sign::none; + if (specs.width != 0) --specs.width; + } + + memory_buffer buffer; + if (fspecs.format == float_format::hex) { + if (fspecs.sign) buffer.push_back(detail::sign<char>(fspecs.sign)); + snprintf_float(promote_float(value), specs.precision, fspecs, buffer); + return write_bytes<align::right>(out, {buffer.data(), buffer.size()}, + specs); + } + int precision = specs.precision >= 0 || specs.type == presentation_type::none + ? specs.precision + : 6; + if (fspecs.format == float_format::exp) { + if (precision == max_value<int>()) + throw_format_error("number is too big"); + else + ++precision; + } + if (const_check(std::is_same<T, float>())) fspecs.binary32 = true; + if (!is_fast_float<T>()) fspecs.fallback = true; + int exp = format_float(promote_float(value), precision, fspecs, buffer); + fspecs.precision = precision; + auto fp = big_decimal_fp{buffer.data(), static_cast<int>(buffer.size()), exp}; + return write_float(out, fp, specs, fspecs, loc); +} + +template <typename Char, typename OutputIt, typename T, + FMT_ENABLE_IF(is_fast_float<T>::value)> +FMT_CONSTEXPR20 auto write(OutputIt out, T value) -> OutputIt { + if (is_constant_evaluated()) { + return write(out, value, basic_format_specs<Char>()); + } + + if (const_check(!is_supported_floating_point(value))) return out; + + using floaty = conditional_t<std::is_same<T, long double>::value, double, T>; + using uint = typename dragonbox::float_info<floaty>::carrier_uint; + auto bits = bit_cast<uint>(value); + + auto fspecs = float_specs(); + if (detail::signbit(value)) { + fspecs.sign = sign::minus; + value = -value; + } + + constexpr auto specs = basic_format_specs<Char>(); + uint mask = exponent_mask<floaty>(); + if ((bits & mask) == mask) + return write_nonfinite(out, std::isinf(value), specs, fspecs); + + auto dec = dragonbox::to_decimal(static_cast<floaty>(value)); + return write_float(out, dec, specs, fspecs, {}); +} + +template <typename Char, typename OutputIt, typename T, + FMT_ENABLE_IF(std::is_floating_point<T>::value && + !is_fast_float<T>::value)> +inline auto write(OutputIt out, T value) -> OutputIt { + return write(out, value, basic_format_specs<Char>()); +} + +template <typename Char, typename OutputIt> +auto write(OutputIt out, monostate, basic_format_specs<Char> = {}, + locale_ref = {}) -> OutputIt { + FMT_ASSERT(false, ""); + return out; +} + +template <typename Char, typename OutputIt> +FMT_CONSTEXPR auto write(OutputIt out, basic_string_view<Char> value) + -> OutputIt { + auto it = reserve(out, value.size()); + it = copy_str_noinline<Char>(value.begin(), value.end(), it); + return base_iterator(out, it); +} + +template <typename Char, typename OutputIt, typename T, + FMT_ENABLE_IF(is_string<T>::value)> +constexpr auto write(OutputIt out, const T& value) -> OutputIt { + return write<Char>(out, to_string_view(value)); +} + +template <typename Char, typename OutputIt, typename T, + FMT_ENABLE_IF(is_integral<T>::value && + !std::is_same<T, bool>::value && + !std::is_same<T, Char>::value)> +FMT_CONSTEXPR auto write(OutputIt out, T value) -> OutputIt { + auto abs_value = static_cast<uint32_or_64_or_128_t<T>>(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<size_t>(num_digits); + auto it = reserve(out, size); + if (auto ptr = to_pointer<Char>(it, size)) { + if (negative) *ptr++ = static_cast<Char>('-'); + format_decimal<Char>(ptr, abs_value, num_digits); + return out; + } + if (negative) *it++ = static_cast<Char>('-'); + it = format_decimal<Char>(it, abs_value, num_digits).end; + return base_iterator(out, it); +} + +// FMT_ENABLE_IF() condition separated to workaround an MSVC bug. +template < + typename Char, typename OutputIt, typename T, + bool check = + std::is_enum<T>::value && !std::is_same<T, Char>::value && + mapped_type_constant<T, basic_format_context<OutputIt, Char>>::value != + type::custom_type, + FMT_ENABLE_IF(check)> +FMT_CONSTEXPR auto write(OutputIt out, T value) -> OutputIt { + return write<Char>( + out, static_cast<typename std::underlying_type<T>::type>(value)); +} + +template <typename Char, typename OutputIt, typename T, + FMT_ENABLE_IF(std::is_same<T, bool>::value)> +FMT_CONSTEXPR auto write(OutputIt out, T value, + const basic_format_specs<Char>& 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 <typename Char, typename OutputIt> +FMT_CONSTEXPR auto write(OutputIt out, Char value) -> OutputIt { + auto it = reserve(out, 1); + *it++ = value; + return base_iterator(out, it); +} + +template <typename Char, typename OutputIt> +FMT_CONSTEXPR_CHAR_TRAITS auto write(OutputIt out, const Char* value) + -> OutputIt { + if (!value) { + throw_format_error("string pointer is null"); + } else { + out = write(out, basic_string_view<Char>(value)); + } + return out; +} + +template <typename Char, typename OutputIt, typename T, + FMT_ENABLE_IF(std::is_same<T, void>::value)> +auto write(OutputIt out, const T* value, + const basic_format_specs<Char>& specs = {}, locale_ref = {}) + -> OutputIt { + check_pointer_type_spec(specs.type, error_handler()); + return write_ptr<Char>(out, to_uintptr(value), &specs); +} + +// A write overload that handles implicit conversions. +template <typename Char, typename OutputIt, typename T, + typename Context = basic_format_context<OutputIt, Char>> +FMT_CONSTEXPR auto write(OutputIt out, const T& value) -> enable_if_t< + std::is_class<T>::value && !is_string<T>::value && + !std::is_same<T, Char>::value && + !std::is_same<const T&, + decltype(arg_mapper<Context>().map(value))>::value, + OutputIt> { + return write<Char>(out, arg_mapper<Context>().map(value)); +} + +template <typename Char, typename OutputIt, typename T, + typename Context = basic_format_context<OutputIt, Char>> +FMT_CONSTEXPR auto write(OutputIt out, const T& value) + -> enable_if_t<mapped_type_constant<T, Context>::value == type::custom_type, + OutputIt> { + using formatter_type = + conditional_t<has_formatter<T, Context>::value, + typename Context::template formatter_type<T>, + fallback_formatter<T, Char>>; + auto ctx = Context(out, {}, {}); + return formatter_type().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 <typename Char> struct default_arg_formatter { + using iterator = buffer_appender<Char>; + using context = buffer_context<Char>; + + iterator out; + basic_format_args<context> args; + locale_ref loc; + + template <typename T> auto operator()(T value) -> iterator { + return write<Char>(out, value); + } + auto operator()(typename basic_format_arg<context>::handle h) -> iterator { + basic_format_parse_context<Char> parse_ctx({}); + context format_ctx(out, args, loc); + h.format(parse_ctx, format_ctx); + return format_ctx.out(); + } +}; + +template <typename Char> struct arg_formatter { + using iterator = buffer_appender<Char>; + using context = buffer_context<Char>; + + iterator out; + const basic_format_specs<Char>& specs; + locale_ref locale; + + template <typename T> + FMT_CONSTEXPR FMT_INLINE auto operator()(T value) -> iterator { + return detail::write(out, value, specs, locale); + } + auto operator()(typename basic_format_arg<context>::handle) -> iterator { + // User-defined types are handled separately because they require access + // to the parse context. + return out; + } +}; + +template <typename Char> struct custom_formatter { + basic_format_parse_context<Char>& parse_ctx; + buffer_context<Char>& ctx; + + void operator()( + typename basic_format_arg<buffer_context<Char>>::handle h) const { + h.format(parse_ctx, ctx); + } + template <typename T> void operator()(T) const {} +}; + +template <typename T> +using is_integer = + bool_constant<is_integral<T>::value && !std::is_same<T, bool>::value && + !std::is_same<T, char>::value && + !std::is_same<T, wchar_t>::value>; + +template <typename ErrorHandler> class width_checker { + public: + explicit FMT_CONSTEXPR width_checker(ErrorHandler& eh) : handler_(eh) {} + + template <typename T, FMT_ENABLE_IF(is_integer<T>::value)> + FMT_CONSTEXPR auto operator()(T value) -> unsigned long long { + if (is_negative(value)) handler_.on_error("negative width"); + return static_cast<unsigned long long>(value); + } + + template <typename T, FMT_ENABLE_IF(!is_integer<T>::value)> + FMT_CONSTEXPR auto operator()(T) -> unsigned long long { + handler_.on_error("width is not integer"); + return 0; + } + + private: + ErrorHandler& handler_; +}; + +template <typename ErrorHandler> class precision_checker { + public: + explicit FMT_CONSTEXPR precision_checker(ErrorHandler& eh) : handler_(eh) {} + + template <typename T, FMT_ENABLE_IF(is_integer<T>::value)> + FMT_CONSTEXPR auto operator()(T value) -> unsigned long long { + if (is_negative(value)) handler_.on_error("negative precision"); + return static_cast<unsigned long long>(value); + } + + template <typename T, FMT_ENABLE_IF(!is_integer<T>::value)> + FMT_CONSTEXPR auto operator()(T) -> unsigned long long { + handler_.on_error("precision is not integer"); + return 0; + } + + private: + ErrorHandler& handler_; +}; + +template <template <typename> class Handler, typename FormatArg, + typename ErrorHandler> +FMT_CONSTEXPR auto get_dynamic_spec(FormatArg arg, ErrorHandler eh) -> int { + unsigned long long value = visit_format_arg(Handler<ErrorHandler>(eh), arg); + if (value > to_unsigned(max_value<int>())) eh.on_error("number is too big"); + return static_cast<int>(value); +} + +template <typename Context, typename ID> +FMT_CONSTEXPR auto get_arg(Context& ctx, ID id) -> + typename Context::format_arg { + auto arg = ctx.arg(id); + if (!arg) ctx.on_error("argument not found"); + return arg; +} + +// The standard format specifier handler with checking. +template <typename Char> class specs_handler : public specs_setter<Char> { + private: + basic_format_parse_context<Char>& parse_context_; + buffer_context<Char>& context_; + + // This is only needed for compatibility with gcc 4.4. + using format_arg = basic_format_arg<buffer_context<Char>>; + + FMT_CONSTEXPR auto get_arg(auto_id) -> format_arg { + return detail::get_arg(context_, parse_context_.next_arg_id()); + } + + FMT_CONSTEXPR auto get_arg(int arg_id) -> format_arg { + parse_context_.check_arg_id(arg_id); + return detail::get_arg(context_, arg_id); + } + + FMT_CONSTEXPR auto get_arg(basic_string_view<Char> arg_id) -> format_arg { + parse_context_.check_arg_id(arg_id); + return detail::get_arg(context_, arg_id); + } + + public: + FMT_CONSTEXPR specs_handler(basic_format_specs<Char>& specs, + basic_format_parse_context<Char>& parse_ctx, + buffer_context<Char>& ctx) + : specs_setter<Char>(specs), parse_context_(parse_ctx), context_(ctx) {} + + template <typename Id> FMT_CONSTEXPR void on_dynamic_width(Id arg_id) { + this->specs_.width = get_dynamic_spec<width_checker>( + get_arg(arg_id), context_.error_handler()); + } + + template <typename Id> FMT_CONSTEXPR void on_dynamic_precision(Id arg_id) { + this->specs_.precision = get_dynamic_spec<precision_checker>( + get_arg(arg_id), context_.error_handler()); + } + + void on_error(const char* message) { context_.on_error(message); } +}; + +template <template <typename> class Handler, typename Context> +FMT_CONSTEXPR void handle_dynamic_spec(int& value, + arg_ref<typename Context::char_type> ref, + Context& ctx) { + switch (ref.kind) { + case arg_id_kind::none: + break; + case arg_id_kind::index: + value = detail::get_dynamic_spec<Handler>(ctx.arg(ref.val.index), + ctx.error_handler()); + break; + case arg_id_kind::name: + value = detail::get_dynamic_spec<Handler>(ctx.arg(ref.val.name), + ctx.error_handler()); + break; + } +} + +#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_GCC_VISIBILITY_HIDDEN FMT_COMPILE_STRING : base { \ + using char_type = fmt::remove_cvref_t<decltype(s[0])>; \ + FMT_MAYBE_UNUSED FMT_CONSTEXPR explicit \ + operator fmt::basic_string_view<char_type>() const { \ + return fmt::detail_exported::compile_string_to_view<char_type>(s); \ + } \ + }; \ + return FMT_COMPILE_STRING(); \ + }() + +/** + \rst + 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"); + \endrst + */ +#define FMT_STRING(s) FMT_STRING_IMPL(s, fmt::compile_string, ) + +#if FMT_USE_USER_DEFINED_LITERALS +template <typename Char> struct udl_formatter { + basic_string_view<Char> str; + + template <typename... T> + auto operator()(T&&... args) const -> std::basic_string<Char> { + return vformat(str, fmt::make_args_checked<T...>(str, args...)); + } +}; + +# if FMT_USE_NONTYPE_TEMPLATE_PARAMETERS +template <typename T, typename Char, size_t N, + fmt::detail_exported::fixed_string<Char, N> Str> +struct statically_named_arg : view { + static constexpr auto name = Str.data; + + const T& value; + statically_named_arg(const T& v) : value(v) {} +}; + +template <typename T, typename Char, size_t N, + fmt::detail_exported::fixed_string<Char, N> Str> +struct is_named_arg<statically_named_arg<T, Char, N, Str>> : std::true_type {}; + +template <typename T, typename Char, size_t N, + fmt::detail_exported::fixed_string<Char, N> Str> +struct is_statically_named_arg<statically_named_arg<T, Char, N, Str>> + : std::true_type {}; + +template <typename Char, size_t N, + fmt::detail_exported::fixed_string<Char, N> Str> +struct udl_arg { + template <typename T> auto operator=(T&& value) const { + return statically_named_arg<T, Char, N, Str>(std::forward<T>(value)); + } +}; +# else +template <typename Char> struct udl_arg { + const Char* str; + + template <typename T> auto operator=(T&& value) const -> named_arg<Char, T> { + return {str, std::forward<T>(value)}; + } +}; +# endif +#endif // FMT_USE_USER_DEFINED_LITERALS + +template <typename Locale, typename Char> +auto vformat(const Locale& loc, basic_string_view<Char> format_str, + basic_format_args<buffer_context<type_identity_t<Char>>> args) + -> std::basic_string<Char> { + basic_memory_buffer<Char> buffer; + detail::vformat_to(buffer, format_str, args, detail::locale_ref(loc)); + return {buffer.data(), buffer.size()}; +} + +using format_func = void (*)(detail::buffer<char>&, int, const char*); + +FMT_API void format_error_code(buffer<char>& out, int error_code, + string_view message) FMT_NOEXCEPT; + +FMT_API void report_error(format_func func, int error_code, + const char* message) FMT_NOEXCEPT; +FMT_END_DETAIL_NAMESPACE + +FMT_API auto vsystem_error(int error_code, string_view format_str, + format_args args) -> std::system_error; + +/** + \rst + Constructs :class:`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); + \endrst +*/ +template <typename... T> +auto system_error(int error_code, format_string<T...> fmt, T&&... args) + -> std::system_error { + return vsystem_error(error_code, fmt, fmt::make_format_args(args...)); +} + +/** + \rst + 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: + + .. parsed-literal:: + *<message>*: *<system-message>* + + where *<message>* is the passed message and *<system-message>* is the system + message corresponding to the error code. + *error_code* is a system error code as given by ``errno``. + \endrst + */ +FMT_API void format_system_error(detail::buffer<char>& out, int error_code, + const char* message) FMT_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) FMT_NOEXCEPT; + +/** 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<unsigned long long>::digits10 + 3 }; + mutable char buffer_[buffer_size]; + char* str_; + + template <typename UInt> auto format_unsigned(UInt value) -> char* { + auto n = static_cast<detail::uint32_or_64_or_128_t<UInt>>(value); + return detail::format_decimal(buffer_, n, buffer_size - 1).begin; + } + + template <typename Int> auto format_signed(Int value) -> char* { + auto abs_value = static_cast<detail::uint32_or_64_or_128_t<Int>>(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 format_int(int value) : str_(format_signed(value)) {} + explicit format_int(long value) : str_(format_signed(value)) {} + explicit format_int(long long value) : str_(format_signed(value)) {} + explicit format_int(unsigned value) : str_(format_unsigned(value)) {} + explicit format_int(unsigned long value) : str_(format_unsigned(value)) {} + explicit format_int(unsigned long long value) + : str_(format_unsigned(value)) {} + + /** Returns the number of characters written to the output buffer. */ + 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. + */ + auto data() const -> const char* { return str_; } + + /** + Returns a pointer to the output buffer content with terminating null + character appended. + */ + auto c_str() const -> const char* { + buffer_[buffer_size - 1] = '\0'; + return str_; + } + + /** + \rst + Returns the content of the output buffer as an ``std::string``. + \endrst + */ + auto str() const -> std::string { return std::string(str_, size()); } +}; + +template <typename T, typename Char> +template <typename FormatContext> +FMT_CONSTEXPR FMT_INLINE auto +formatter<T, Char, + enable_if_t<detail::type_constant<T, Char>::value != + detail::type::custom_type>>::format(const T& val, + FormatContext& ctx) + const -> decltype(ctx.out()) { + if (specs_.width_ref.kind != detail::arg_id_kind::none || + specs_.precision_ref.kind != detail::arg_id_kind::none) { + auto specs = specs_; + detail::handle_dynamic_spec<detail::width_checker>(specs.width, + specs.width_ref, ctx); + detail::handle_dynamic_spec<detail::precision_checker>( + specs.precision, specs.precision_ref, ctx); + return detail::write<Char>(ctx.out(), val, specs, ctx.locale()); + } + return detail::write<Char>(ctx.out(), val, specs_, ctx.locale()); +} + +#define FMT_FORMAT_AS(Type, Base) \ + template <typename Char> \ + struct formatter<Type, Char> : formatter<Base, Char> { \ + template <typename FormatContext> \ + auto format(Type const& val, FormatContext& ctx) const \ + -> decltype(ctx.out()) { \ + return formatter<Base, Char>::format(static_cast<Base>(val), 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, long long); +FMT_FORMAT_AS(unsigned long, unsigned long long); +FMT_FORMAT_AS(Char*, const Char*); +FMT_FORMAT_AS(std::basic_string<Char>, basic_string_view<Char>); +FMT_FORMAT_AS(std::nullptr_t, const void*); +FMT_FORMAT_AS(detail::byte, unsigned char); +FMT_FORMAT_AS(detail::std_string_view<Char>, basic_string_view<Char>); + +template <typename Char> +struct formatter<void*, Char> : formatter<const void*, Char> { + template <typename FormatContext> + auto format(void* val, FormatContext& ctx) const -> decltype(ctx.out()) { + return formatter<const void*, Char>::format(val, ctx); + } +}; + +template <typename Char, size_t N> +struct formatter<Char[N], Char> : formatter<basic_string_view<Char>, Char> { + template <typename FormatContext> + FMT_CONSTEXPR auto format(const Char* val, FormatContext& ctx) const + -> decltype(ctx.out()) { + return formatter<basic_string_view<Char>, Char>::format(val, ctx); + } +}; + +// A formatter for types known only at run time such as variant alternatives. +// +// Usage: +// using variant = std::variant<int, std::string>; +// template <> +// struct formatter<variant>: dynamic_formatter<> { +// auto format(const variant& v, format_context& ctx) { +// return visit([&](const auto& val) { +// return dynamic_formatter<>::format(val, ctx); +// }, v); +// } +// }; +template <typename Char = char> class dynamic_formatter { + private: + detail::dynamic_format_specs<Char> specs_; + const Char* format_str_; + + struct null_handler : detail::error_handler { + void on_align(align_t) {} + void on_sign(sign_t) {} + void on_hash() {} + }; + + template <typename Context> void handle_specs(Context& ctx) { + detail::handle_dynamic_spec<detail::width_checker>(specs_.width, + specs_.width_ref, ctx); + detail::handle_dynamic_spec<detail::precision_checker>( + specs_.precision, specs_.precision_ref, ctx); + } + + public: + template <typename ParseContext> + FMT_CONSTEXPR auto parse(ParseContext& ctx) -> decltype(ctx.begin()) { + format_str_ = ctx.begin(); + // Checks are deferred to formatting time when the argument type is known. + detail::dynamic_specs_handler<ParseContext> handler(specs_, ctx); + return detail::parse_format_specs(ctx.begin(), ctx.end(), handler); + } + + template <typename T, typename FormatContext> + auto format(const T& val, FormatContext& ctx) -> decltype(ctx.out()) { + handle_specs(ctx); + detail::specs_checker<null_handler> checker( + null_handler(), detail::mapped_type_constant<T, FormatContext>::value); + checker.on_align(specs_.align); + if (specs_.sign != sign::none) checker.on_sign(specs_.sign); + if (specs_.alt) checker.on_hash(); + if (specs_.precision >= 0) checker.end_precision(); + return detail::write<Char>(ctx.out(), val, specs_, ctx.locale()); + } +}; + +/** + \rst + Converts ``p`` to ``const void*`` for pointer formatting. + + **Example**:: + + auto s = fmt::format("{}", fmt::ptr(p)); + \endrst + */ +template <typename T> auto ptr(T p) -> const void* { + static_assert(std::is_pointer<T>::value, ""); + return detail::bit_cast<const void*>(p); +} +template <typename T> auto ptr(const std::unique_ptr<T>& p) -> const void* { + return p.get(); +} +template <typename T> auto ptr(const std::shared_ptr<T>& p) -> const void* { + return p.get(); +} + +class bytes { + private: + string_view data_; + friend struct formatter<bytes>; + + public: + explicit bytes(string_view data) : data_(data) {} +}; + +template <> struct formatter<bytes> { + private: + detail::dynamic_format_specs<char> specs_; + + public: + template <typename ParseContext> + FMT_CONSTEXPR auto parse(ParseContext& ctx) -> decltype(ctx.begin()) { + using handler_type = detail::dynamic_specs_handler<ParseContext>; + detail::specs_checker<handler_type> handler(handler_type(specs_, ctx), + detail::type::string_type); + auto it = parse_format_specs(ctx.begin(), ctx.end(), handler); + detail::check_string_type_spec(specs_.type, ctx.error_handler()); + return it; + } + + template <typename FormatContext> + auto format(bytes b, FormatContext& ctx) -> decltype(ctx.out()) { + detail::handle_dynamic_spec<detail::width_checker>(specs_.width, + specs_.width_ref, ctx); + detail::handle_dynamic_spec<detail::precision_checker>( + 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 <typename T> struct group_digits_view { T value; }; + +/** + \rst + 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" + \endrst + */ +template <typename T> auto group_digits(T value) -> group_digits_view<T> { + return {value}; +} + +template <typename T> struct formatter<group_digits_view<T>> : formatter<T> { + private: + detail::dynamic_format_specs<char> specs_; + + public: + template <typename ParseContext> + FMT_CONSTEXPR auto parse(ParseContext& ctx) -> decltype(ctx.begin()) { + using handler_type = detail::dynamic_specs_handler<ParseContext>; + detail::specs_checker<handler_type> handler(handler_type(specs_, ctx), + detail::type::int_type); + auto it = parse_format_specs(ctx.begin(), ctx.end(), handler); + detail::check_string_type_spec(specs_.type, ctx.error_handler()); + return it; + } + + template <typename FormatContext> + auto format(group_digits_view<T> t, FormatContext& ctx) + -> decltype(ctx.out()) { + detail::handle_dynamic_spec<detail::width_checker>(specs_.width, + specs_.width_ref, ctx); + detail::handle_dynamic_spec<detail::precision_checker>( + specs_.precision, specs_.precision_ref, ctx); + return detail::write_int_localized( + ctx.out(), static_cast<detail::uint64_or_128_t<T>>(t.value), 0, specs_, + detail::digit_grouping<char>({"\3", ','})); + } +}; + +template <typename It, typename Sentinel, typename Char = char> +struct join_view : detail::view { + It begin; + Sentinel end; + basic_string_view<Char> sep; + + join_view(It b, Sentinel e, basic_string_view<Char> s) + : begin(b), end(e), sep(s) {} +}; + +template <typename It, typename Sentinel, typename Char> +using arg_join FMT_DEPRECATED_ALIAS = join_view<It, Sentinel, Char>; + +template <typename It, typename Sentinel, typename Char> +struct formatter<join_view<It, Sentinel, Char>, Char> { + private: + using value_type = +#ifdef __cpp_lib_ranges + std::iter_value_t<It>; +#else + typename std::iterator_traits<It>::value_type; +#endif + using context = buffer_context<Char>; + using mapper = detail::arg_mapper<context>; + + template <typename T, FMT_ENABLE_IF(has_formatter<T, context>::value)> + static auto map(const T& value) -> const T& { + return value; + } + template <typename T, FMT_ENABLE_IF(!has_formatter<T, context>::value)> + static auto map(const T& value) -> decltype(mapper().map(value)) { + return mapper().map(value); + } + + using formatter_type = + conditional_t<is_formattable<value_type, Char>::value, + formatter<remove_cvref_t<decltype(map( + std::declval<const value_type&>()))>, + Char>, + detail::fallback_formatter<value_type, Char>>; + + formatter_type value_formatter_; + + public: + template <typename ParseContext> + FMT_CONSTEXPR auto parse(ParseContext& ctx) -> decltype(ctx.begin()) { + return value_formatter_.parse(ctx); + } + + template <typename FormatContext> + auto format(const join_view<It, Sentinel, Char>& value, FormatContext& ctx) + -> decltype(ctx.out()) { + auto it = value.begin; + auto out = ctx.out(); + if (it != value.end) { + out = value_formatter_.format(map(*it), ctx); + ++it; + while (it != value.end) { + out = detail::copy_str<Char>(value.sep.begin(), value.sep.end(), out); + ctx.advance_to(out); + out = value_formatter_.format(map(*it), ctx); + ++it; + } + } + return out; + } +}; + +/** + Returns a view that formats the iterator range `[begin, end)` with elements + separated by `sep`. + */ +template <typename It, typename Sentinel> +auto join(It begin, Sentinel end, string_view sep) -> join_view<It, Sentinel> { + return {begin, end, sep}; +} + +/** + \rst + Returns a view that formats `range` with elements separated by `sep`. + + **Example**:: + + std::vector<int> v = {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" + \endrst + */ +template <typename Range> +auto join(Range&& range, string_view sep) + -> join_view<detail::iterator_t<Range>, detail::sentinel_t<Range>> { + return join(std::begin(range), std::end(range), sep); +} + +/** + \rst + Converts *value* to ``std::string`` using the default format for type *T*. + + **Example**:: + + #include <fmt/format.h> + + std::string answer = fmt::to_string(42); + \endrst + */ +template <typename T, FMT_ENABLE_IF(!std::is_integral<T>::value)> +inline auto to_string(const T& value) -> std::string { + auto result = std::string(); + detail::write<char>(std::back_inserter(result), value); + return result; +} + +template <typename T, FMT_ENABLE_IF(std::is_integral<T>::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<T>() + 2; + char buffer[max_size > 5 ? static_cast<unsigned>(max_size) : 5]; + char* begin = buffer; + return std::string(begin, detail::write<char>(begin, value)); +} + +template <typename Char, size_t SIZE> +FMT_NODISCARD auto to_string(const basic_memory_buffer<Char, SIZE>& buf) + -> std::basic_string<Char> { + auto size = buf.size(); + detail::assume(size < std::basic_string<Char>().max_size()); + return std::basic_string<Char>(buf.data(), size); +} + +FMT_BEGIN_DETAIL_NAMESPACE + +template <typename Char> +void vformat_to( + buffer<Char>& buf, basic_string_view<Char> fmt, + basic_format_args<FMT_BUFFER_CONTEXT(type_identity_t<Char>)> args, + locale_ref loc) { + // workaround for msvc bug regarding name-lookup in module + // link names into function scope + using detail::arg_formatter; + using detail::buffer_appender; + using detail::custom_formatter; + using detail::default_arg_formatter; + using detail::get_arg; + using detail::locale_ref; + using detail::parse_format_specs; + using detail::specs_checker; + using detail::specs_handler; + using detail::to_unsigned; + using detail::type; + using detail::write; + auto out = buffer_appender<Char>(buf); + if (fmt.size() == 2 && equal2(fmt.data(), "{}")) { + auto arg = args.get(0); + if (!arg) error_handler().on_error("argument not found"); + visit_format_arg(default_arg_formatter<Char>{out, args, loc}, arg); + return; + } + + struct format_handler : error_handler { + basic_format_parse_context<Char> parse_context; + buffer_context<Char> context; + + format_handler(buffer_appender<Char> out, basic_string_view<Char> str, + basic_format_args<buffer_context<Char>> args, locale_ref loc) + : parse_context(str), context(out, args, loc) {} + + void on_text(const Char* begin, const Char* end) { + auto text = basic_string_view<Char>(begin, to_unsigned(end - begin)); + context.advance_to(write<Char>(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 { + return parse_context.check_arg_id(id), id; + } + FMT_CONSTEXPR auto on_arg_id(basic_string_view<Char> id) -> int { + int arg_id = context.arg_id(id); + if (arg_id < 0) on_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(visit_format_arg( + default_arg_formatter<Char>{context.out(), context.args(), + context.locale()}, + arg)); + } + + auto on_format_specs(int id, const Char* begin, const Char* end) + -> const Char* { + auto arg = get_arg(context, id); + if (arg.type() == type::custom_type) { + parse_context.advance_to(parse_context.begin() + + (begin - &*parse_context.begin())); + visit_format_arg(custom_formatter<Char>{parse_context, context}, arg); + return parse_context.begin(); + } + auto specs = basic_format_specs<Char>(); + specs_checker<specs_handler<Char>> handler( + specs_handler<Char>(specs, parse_context, context), arg.type()); + begin = parse_format_specs(begin, end, handler); + if (begin == end || *begin != '}') + on_error("missing '}' in format string"); + auto f = arg_formatter<Char>{context.out(), specs, context.locale()}; + context.advance_to(visit_format_arg(f, arg)); + return begin; + } + }; + detail::parse_format_string<false>(fmt, format_handler(out, fmt, args, loc)); +} + +#ifndef FMT_HEADER_ONLY +extern template FMT_API auto thousands_sep_impl<char>(locale_ref) + -> thousands_sep_result<char>; +extern template FMT_API auto thousands_sep_impl<wchar_t>(locale_ref) + -> thousands_sep_result<wchar_t>; +extern template FMT_API auto decimal_point_impl(locale_ref) -> char; +extern template FMT_API auto decimal_point_impl(locale_ref) -> wchar_t; +extern template auto format_float<double>(double value, int precision, + float_specs specs, buffer<char>& buf) + -> int; +extern template auto format_float<long double>(long double value, int precision, + float_specs specs, + buffer<char>& buf) -> int; +void snprintf_float(float, int, float_specs, buffer<char>&) = delete; +extern template auto snprintf_float<double>(double value, int precision, + float_specs specs, + buffer<char>& buf) -> int; +extern template auto snprintf_float<long double>(long double value, + int precision, + float_specs specs, + buffer<char>& buf) -> int; +#endif // FMT_HEADER_ONLY + +FMT_END_DETAIL_NAMESPACE + +#if FMT_USE_USER_DEFINED_LITERALS +inline namespace literals { +/** + \rst + User-defined literal equivalent of :func:`fmt::arg`. + + **Example**:: + + using namespace fmt::literals; + fmt::print("Elapsed time: {s:.2f} seconds", "s"_a=1.23); + \endrst + */ +# if FMT_USE_NONTYPE_TEMPLATE_PARAMETERS +template <detail_exported::fixed_string Str> +constexpr auto operator""_a() + -> detail::udl_arg<remove_cvref_t<decltype(Str.data[0])>, + sizeof(Str.data) / sizeof(decltype(Str.data[0])), Str> { + return {}; +} +# else +constexpr auto operator"" _a(const char* s, size_t) -> detail::udl_arg<char> { + return {s}; +} +# endif + +// DEPRECATED! +// User-defined literal equivalent of fmt::format. +FMT_DEPRECATED constexpr auto operator"" _format(const char* s, size_t n) + -> detail::udl_formatter<char> { + return {{s, n}}; +} +} // namespace literals +#endif // FMT_USE_USER_DEFINED_LITERALS + +template <typename Locale, FMT_ENABLE_IF(detail::is_locale<Locale>::value)> +inline auto vformat(const Locale& loc, string_view fmt, format_args args) + -> std::string { + return detail::vformat(loc, fmt, args); +} + +template <typename Locale, typename... T, + FMT_ENABLE_IF(detail::is_locale<Locale>::value)> +inline auto format(const Locale& loc, format_string<T...> fmt, T&&... args) + -> std::string { + return vformat(loc, string_view(fmt), fmt::make_format_args(args...)); +} + +template <typename... T, size_t SIZE, typename Allocator> +FMT_DEPRECATED auto format_to(basic_memory_buffer<char, SIZE, Allocator>& buf, + format_string<T...> fmt, T&&... args) + -> appender { + detail::vformat_to(buf, string_view(fmt), fmt::make_format_args(args...)); + return appender(buf); +} + +template <typename OutputIt, typename Locale, + FMT_ENABLE_IF(detail::is_output_iterator<OutputIt, char>::value&& + detail::is_locale<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<char>(out); + detail::vformat_to(buf, fmt, args, detail::locale_ref(loc)); + return detail::get_iterator(buf); +} + +template <typename OutputIt, typename Locale, typename... T, + FMT_ENABLE_IF(detail::is_output_iterator<OutputIt, char>::value&& + detail::is_locale<Locale>::value)> +FMT_INLINE auto format_to(OutputIt out, const Locale& loc, + format_string<T...> fmt, T&&... args) -> OutputIt { + return vformat_to(out, loc, fmt, fmt::make_format_args(args...)); +} + +FMT_MODULE_EXPORT_END +FMT_END_NAMESPACE + +#ifdef FMT_DEPRECATED_INCLUDE_XCHAR +# include "xchar.h" +#endif + +#ifdef FMT_HEADER_ONLY +# define FMT_FUNC inline +# include "format-inl.h" +#else +# define FMT_FUNC +#endif + +#endif // FMT_FORMAT_H_ diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/spdlog/fmt/bundled/locale.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/spdlog/fmt/bundled/locale.h new file mode 100644 index 0000000000000000000000000000000000000000..7571b5261ba78c62d0e45c7ba71567ae512ea6bb --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/spdlog/fmt/bundled/locale.h @@ -0,0 +1,2 @@ +#include "xchar.h" +#warning fmt/locale.h is deprecated, include fmt/format.h or fmt/xchar.h instead diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/spdlog/fmt/bundled/os.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/spdlog/fmt/bundled/os.h new file mode 100644 index 0000000000000000000000000000000000000000..b64f8bbfa57ac3fd97c849fd303a2f28d002e5e1 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/spdlog/fmt/bundled/os.h @@ -0,0 +1,527 @@ +// 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 <cerrno> +#include <clocale> // locale_t +#include <cstddef> +#include <cstdio> +#include <cstdlib> // strtod_l +#include <system_error> // std::system_error + +#if defined __APPLE__ || defined(__FreeBSD__) +# include <xlocale.h> // for LC_NUMERIC_MASK on OS X +#endif + +#include "format.h" + +#ifndef FMT_USE_FCNTL +// UWP doesn't provide _pipe. +# if FMT_HAS_INCLUDE("winapifamily.h") +# include <winapifamily.h> +# endif +# if (FMT_HAS_INCLUDE(<fcntl.h>) || defined(__APPLE__) || \ + defined(__linux__)) && \ + (!defined(WINAPI_FAMILY) || \ + (WINAPI_FAMILY == WINAPI_FAMILY_DESKTOP_APP)) +# include <fcntl.h> // 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_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_MODULE_EXPORT_BEGIN + +/** + \rst + 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<char> | + +---------------+-----------------------------+ + | wcstring_view | basic_cstring_view<wchar_t> | + +---------------+-----------------------------+ + + This class is most useful as a parameter type to allow passing + different types of strings to a function, for example:: + + template <typename... Args> + std::string format(cstring_view format_str, const Args & ... args); + + format("{}", 42); + format(std::string("{}"), 42); + \endrst + */ +template <typename Char> 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) {} + + /** + \rst + Constructs a string reference from an ``std::string`` object. + \endrst + */ + basic_cstring_view(const std::basic_string<Char>& s) : data_(s.c_str()) {} + + /** Returns the pointer to a C string. */ + const Char* c_str() const { return data_; } +}; + +using cstring_view = basic_cstring_view<char>; +using wcstring_view = basic_cstring_view<wchar_t>; + +template <typename Char> struct formatter<std::error_code, Char> { + template <typename ParseContext> + FMT_CONSTEXPR auto parse(ParseContext& ctx) -> decltype(ctx.begin()) { + return ctx.begin(); + } + + template <typename FormatContext> + 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(), + basic_format_specs<Char>()); + out = detail::write<Char>(out, Char(':')); + out = detail::write<Char>(out, ec.value()); + return out; + } +}; + +#ifdef _WIN32 +FMT_API const std::error_category& system_category() FMT_NOEXCEPT; + +FMT_BEGIN_DETAIL_NAMESPACE +// A converter from UTF-16 to UTF-8. +// It is only provided for Windows since other systems support UTF-8 natively. +class utf16_to_utf8 { + private: + memory_buffer buffer_; + + public: + utf16_to_utf8() {} + FMT_API explicit utf16_to_utf8(basic_string_view<wchar_t> s); + operator string_view() const { return string_view(&buffer_[0], size()); } + size_t size() const { return buffer_.size() - 1; } + const char* c_str() const { return &buffer_[0]; } + std::string str() const { return std::string(&buffer_[0], size()); } + + // Performs conversion returning a system error code instead of + // throwing exception on conversion error. This method may still throw + // in case of memory allocation error. + FMT_API int convert(basic_string_view<wchar_t> s); +}; + +FMT_API void format_windows_error(buffer<char>& out, int error_code, + const char* message) FMT_NOEXCEPT; +FMT_END_DETAIL_NAMESPACE + +FMT_API std::system_error vwindows_error(int error_code, string_view format_str, + format_args args); + +/** + \rst + Constructs a :class:`std::system_error` object with the description + of the form + + .. parsed-literal:: + *<message>*: *<system-message>* + + where *<message>* is the formatted message and *<system-message>* 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); + } + \endrst +*/ +template <typename... Args> +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) FMT_NOEXCEPT; +#else +inline const std::error_category& system_category() FMT_NOEXCEPT { + return std::system_category(); +} +#endif // _WIN32 + +// std::system is not available on some platforms such as iOS (#2248). +#ifdef __OSX__ +template <typename S, typename... Args, typename Char = char_t<S>> +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() FMT_NOEXCEPT : file_(nullptr) {} + + // Destroys the object closing the file it represents if any. + FMT_API ~buffered_file() FMT_NOEXCEPT; + + public: + buffered_file(buffered_file&& other) FMT_NOEXCEPT : file_(other.file_) { + other.file_ = nullptr; + } + + buffered_file& operator=(buffered_file&& other) { + 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. + FILE* get() const FMT_NOEXCEPT { return file_; } + + // We place parentheses around fileno to workaround a bug in some versions + // of MinGW that define fileno as a macro. + FMT_API int(fileno)() const; + + void vprint(string_view format_str, format_args args) { + fmt::vprint(file_, format_str, args); + } + + template <typename... Args> + inline void print(string_view format_str, const Args&... args) { + vprint(format_str, fmt::make_format_args(args...)); + } +}; + +#if FMT_USE_FCNTL +// A file. Closed file is represented by a file object with descriptor -1. +// Methods that are not declared with FMT_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 file { + private: + int fd_; // File descriptor. + + // Constructs a file object with a given descriptor. + explicit file(int fd) : fd_(fd) {} + + 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() FMT_NOEXCEPT : fd_(-1) {} + + // Opens a file and constructs a file object representing this file. + FMT_API file(cstring_view path, int oflag); + + public: + file(const file&) = delete; + void operator=(const file&) = delete; + + file(file&& other) FMT_NOEXCEPT : fd_(other.fd_) { other.fd_ = -1; } + + // Move assignment is not noexcept because close may throw. + file& operator=(file&& other) { + close(); + fd_ = other.fd_; + other.fd_ = -1; + return *this; + } + + // Destroys the object closing the file it represents if any. + FMT_API ~file() FMT_NOEXCEPT; + + // Returns the file descriptor. + int descriptor() const FMT_NOEXCEPT { return fd_; } + + // Closes the file. + FMT_API void close(); + + // Returns the file size. The size has signed type for consistency with + // stat::st_size. + FMT_API long long size() const; + + // Attempts to read count bytes from the file into the specified buffer. + FMT_API size_t read(void* buffer, size_t count); + + // Attempts to write count bytes from the specified buffer to the file. + FMT_API size_t write(const void* buffer, size_t count); + + // Duplicates a file descriptor with the dup function and returns + // the duplicate as a file object. + FMT_API static file dup(int fd); + + // Makes fd be the copy of this file descriptor, closing fd first if + // necessary. + FMT_API void dup2(int fd); + + // Makes fd be the copy of this file descriptor, closing fd first if + // necessary. + FMT_API void dup2(int fd, std::error_code& ec) FMT_NOEXCEPT; + + // Creates a pipe setting up read_end and write_end file objects for reading + // and writing respectively. + FMT_API static void pipe(file& read_end, file& write_end); + + // Creates a buffered_file object associated with this file and detaches + // this file object from the file. + FMT_API buffered_file fdopen(const char* mode); +}; + +// Returns the memory page size. +long getpagesize(); + +FMT_BEGIN_DETAIL_NAMESPACE + +struct buffer_size { + buffer_size() = default; + size_t value = 0; + buffer_size operator=(size_t val) const { + 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 <typename... T> + ostream_params(T... params, int new_oflag) : ostream_params(params...) { + oflag = new_oflag; + } + + template <typename... T> + 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 +}; + +FMT_END_DETAIL_NAMESPACE + +// Added {} below to work around default constructor error known to +// occur in Xcode versions 7.2.1 and 8.2.1. +constexpr detail::buffer_size buffer_size{}; + +/** A fast output stream which is not thread-safe. */ +class FMT_API ostream final : private detail::buffer<char> { + private: + file file_; + + void grow(size_t) override; + + ostream(cstring_view path, const detail::ostream_params& params) + : file_(path, params.oflag) { + set(new char[params.buffer_size], params.buffer_size); + } + + public: + ostream(ostream&& other) + : detail::buffer<char>(other.data(), other.size(), other.capacity()), + file_(std::move(other.file_)) { + other.clear(); + other.set(nullptr, 0); + } + ~ostream() { + flush(); + delete[] data(); + } + + void flush() { + if (size() == 0) return; + file_.write(data(), size()); + clear(); + } + + template <typename... T> + friend ostream output_file(cstring_view path, T... params); + + void close() { + flush(); + file_.close(); + } + + /** + Formats ``args`` according to specifications in ``fmt`` and writes the + output to the file. + */ + template <typename... T> void print(format_string<T...> fmt, T&&... args) { + vformat_to(detail::buffer_appender<char>(*this), fmt, + fmt::make_format_args(args...)); + } +}; + +/** + \rst + Opens a file for writing. Supported parameters passed in *params*: + + * ``<integer>``: Flags passed to `open + <https://pubs.opengroup.org/onlinepubs/007904875/functions/open.html>`_ + (``file::WRONLY | file::CREATE`` by default) + * ``buffer_size=<integer>``: Output buffer size + + **Example**:: + + auto out = fmt::output_file("guide.txt"); + out.print("Don't {}", "Panic"); + \endrst + */ +template <typename... T> +inline ostream output_file(cstring_view path, T... params) { + return {path, detail::ostream_params(params...)}; +} +#endif // FMT_USE_FCNTL + +#ifdef FMT_LOCALE +// A "C" numeric locale. +class locale { + private: +# ifdef _WIN32 + using locale_t = _locale_t; + + static void freelocale(locale_t loc) { _free_locale(loc); } + + static double strtod_l(const char* nptr, char** endptr, _locale_t loc) { + return _strtod_l(nptr, endptr, loc); + } +# endif + + locale_t locale_; + + public: + using type = locale_t; + locale(const locale&) = delete; + void operator=(const locale&) = delete; + + locale() { +# ifndef _WIN32 + locale_ = FMT_SYSTEM(newlocale(LC_NUMERIC_MASK, "C", nullptr)); +# else + locale_ = _create_locale(LC_NUMERIC, "C"); +# endif + if (!locale_) FMT_THROW(system_error(errno, "cannot create locale")); + } + ~locale() { freelocale(locale_); } + + type get() const { return locale_; } + + // Converts string to floating-point number and advances str past the end + // of the parsed input. + FMT_DEPRECATED double strtod(const char*& str) const { + char* end = nullptr; + double result = strtod_l(str, &end, locale_); + str = end; + return result; + } +}; +using Locale FMT_DEPRECATED_ALIAS = locale; +#endif // FMT_LOCALE +FMT_MODULE_EXPORT_END +FMT_END_NAMESPACE + +#endif // FMT_OS_H_ diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/spdlog/fmt/bundled/ostream.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/spdlog/fmt/bundled/ostream.h new file mode 100644 index 0000000000000000000000000000000000000000..3d716ece84d00c3ee05298c79b5504e72d433402 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/spdlog/fmt/bundled/ostream.h @@ -0,0 +1,135 @@ +// 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_ + +#include <ostream> + +#include "format.h" + +FMT_BEGIN_NAMESPACE + +template <typename OutputIt, typename Char> class basic_printf_context; + +namespace detail { + +// Checks if T has a user-defined operator<<. +template <typename T, typename Char, typename Enable = void> +class is_streamable { + private: + template <typename U> + static auto test(int) + -> bool_constant<sizeof(std::declval<std::basic_ostream<Char>&>() + << std::declval<U>()) != 0>; + + template <typename> static auto test(...) -> std::false_type; + + using result = decltype(test<T>(0)); + + public: + is_streamable() = default; + + static const bool value = result::value; +}; + +// Formatting of built-in types and arrays is intentionally disabled because +// it's handled by standard (non-ostream) formatters. +template <typename T, typename Char> +struct is_streamable< + T, Char, + enable_if_t< + std::is_arithmetic<T>::value || std::is_array<T>::value || + std::is_pointer<T>::value || std::is_same<T, char8_type>::value || + std::is_same<T, std::basic_string<Char>>::value || + std::is_same<T, std_string_view<Char>>::value || + (std::is_convertible<T, int>::value && !std::is_enum<T>::value)>> + : std::false_type {}; + +// Write the content of buf to os. +// It is a separate function rather than a part of vprint to simplify testing. +template <typename Char> +void write_buffer(std::basic_ostream<Char>& os, buffer<Char>& buf) { + const Char* buf_data = buf.data(); + using unsigned_streamsize = std::make_unsigned<std::streamsize>::type; + unsigned_streamsize size = buf.size(); + unsigned_streamsize max_size = to_unsigned(max_value<std::streamsize>()); + do { + unsigned_streamsize n = size <= max_size ? size : max_size; + os.write(buf_data, static_cast<std::streamsize>(n)); + buf_data += n; + size -= n; + } while (size != 0); +} + +template <typename Char, typename T> +void format_value(buffer<Char>& buf, const T& value, + locale_ref loc = locale_ref()) { + auto&& format_buf = formatbuf<std::basic_streambuf<Char>>(buf); + auto&& output = std::basic_ostream<Char>(&format_buf); +#if !defined(FMT_STATIC_THOUSANDS_SEPARATOR) + if (loc) output.imbue(loc.get<std::locale>()); +#endif + output << value; + output.exceptions(std::ios_base::failbit | std::ios_base::badbit); + buf.try_resize(buf.size()); +} + +// Formats an object of type T that has an overloaded ostream operator<<. +template <typename T, typename Char> +struct fallback_formatter<T, Char, enable_if_t<is_streamable<T, Char>::value>> + : private formatter<basic_string_view<Char>, Char> { + using formatter<basic_string_view<Char>, Char>::parse; + + template <typename OutputIt> + auto format(const T& value, basic_format_context<OutputIt, Char>& ctx) + -> OutputIt { + auto buffer = basic_memory_buffer<Char>(); + format_value(buffer, value, ctx.locale()); + return formatter<basic_string_view<Char>, Char>::format( + {buffer.data(), buffer.size()}, ctx); + } + + // DEPRECATED! + template <typename OutputIt> + auto format(const T& value, basic_printf_context<OutputIt, Char>& ctx) + -> OutputIt { + auto buffer = basic_memory_buffer<Char>(); + format_value(buffer, value, ctx.locale()); + return std::copy(buffer.begin(), buffer.end(), ctx.out()); + } +}; +} // namespace detail + +FMT_MODULE_EXPORT +template <typename Char> +void vprint(std::basic_ostream<Char>& os, basic_string_view<Char> format_str, + basic_format_args<buffer_context<type_identity_t<Char>>> args) { + auto buffer = basic_memory_buffer<Char>(); + detail::vformat_to(buffer, format_str, args); + detail::write_buffer(os, buffer); +} + +/** + \rst + Prints formatted data to the stream *os*. + + **Example**:: + + fmt::print(cerr, "Don't {}!", "panic"); + \endrst + */ +FMT_MODULE_EXPORT +template <typename S, typename... Args, + typename Char = enable_if_t<detail::is_string<S>::value, char_t<S>>> +void print(std::basic_ostream<Char>& os, const S& format_str, Args&&... args) { + vprint(os, to_string_view(format_str), + fmt::make_args_checked<Args...>(format_str, args...)); +} +FMT_END_NAMESPACE + +#endif // FMT_OSTREAM_H_ diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/spdlog/fmt/bundled/printf.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/spdlog/fmt/bundled/printf.h new file mode 100644 index 0000000000000000000000000000000000000000..19d550f6cf5393a3fb9cc8a92369f2908ab48a89 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/spdlog/fmt/bundled/printf.h @@ -0,0 +1,657 @@ +// 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_ + +#include <algorithm> // std::max +#include <limits> // std::numeric_limits +#include <ostream> + +#include "format.h" + +FMT_BEGIN_NAMESPACE +FMT_MODULE_EXPORT_BEGIN + +template <typename T> struct printf_formatter { printf_formatter() = delete; }; + +template <typename Char> +class basic_printf_parse_context : public basic_format_parse_context<Char> { + using basic_format_parse_context<Char>::basic_format_parse_context; +}; + +template <typename OutputIt, typename Char> class basic_printf_context { + private: + OutputIt out_; + basic_format_args<basic_printf_context> args_; + + public: + using char_type = Char; + using format_arg = basic_format_arg<basic_printf_context>; + using parse_context_type = basic_printf_parse_context<Char>; + template <typename T> using formatter_type = printf_formatter<T>; + + /** + \rst + Constructs a ``printf_context`` object. References to the arguments are + stored in the context object so make sure they have appropriate lifetimes. + \endrst + */ + basic_printf_context(OutputIt out, + basic_format_args<basic_printf_context> args) + : out_(out), args_(args) {} + + OutputIt out() { return out_; } + void advance_to(OutputIt it) { out_ = it; } + + detail::locale_ref locale() { return {}; } + + format_arg arg(int id) const { return args_.get(id); } + + FMT_CONSTEXPR void on_error(const char* message) { + detail::error_handler().on_error(message); + } +}; + +FMT_BEGIN_DETAIL_NAMESPACE + +// Checks if a value fits in int - used to avoid warnings about comparing +// signed and unsigned integers. +template <bool IsSigned> struct int_checker { + template <typename T> static bool fits_in_int(T value) { + unsigned max = max_value<int>(); + return value <= max; + } + static bool fits_in_int(bool) { return true; } +}; + +template <> struct int_checker<true> { + template <typename T> static bool fits_in_int(T value) { + return value >= (std::numeric_limits<int>::min)() && + value <= max_value<int>(); + } + static bool fits_in_int(int) { return true; } +}; + +class printf_precision_handler { + public: + template <typename T, FMT_ENABLE_IF(std::is_integral<T>::value)> + int operator()(T value) { + if (!int_checker<std::numeric_limits<T>::is_signed>::fits_in_int(value)) + FMT_THROW(format_error("number is too big")); + return (std::max)(static_cast<int>(value), 0); + } + + template <typename T, FMT_ENABLE_IF(!std::is_integral<T>::value)> + int operator()(T) { + FMT_THROW(format_error("precision is not integer")); + return 0; + } +}; + +// An argument visitor that returns true iff arg is a zero integer. +class is_zero_int { + public: + template <typename T, FMT_ENABLE_IF(std::is_integral<T>::value)> + bool operator()(T value) { + return value == 0; + } + + template <typename T, FMT_ENABLE_IF(!std::is_integral<T>::value)> + bool operator()(T) { + return false; + } +}; + +template <typename T> struct make_unsigned_or_bool : std::make_unsigned<T> {}; + +template <> struct make_unsigned_or_bool<bool> { using type = bool; }; + +template <typename T, typename Context> class arg_converter { + private: + using char_type = typename Context::char_type; + + basic_format_arg<Context>& arg_; + char_type type_; + + public: + arg_converter(basic_format_arg<Context>& arg, char_type type) + : arg_(arg), type_(type) {} + + void operator()(bool value) { + if (type_ != 's') operator()<bool>(value); + } + + template <typename U, FMT_ENABLE_IF(std::is_integral<U>::value)> + void operator()(U value) { + bool is_signed = type_ == 'd' || type_ == 'i'; + using target_type = conditional_t<std::is_same<T, void>::value, U, T>; + if (const_check(sizeof(target_type) <= sizeof(int))) { + // Extra casts are used to silence warnings. + if (is_signed) { + arg_ = detail::make_arg<Context>( + static_cast<int>(static_cast<target_type>(value))); + } else { + using unsigned_type = typename make_unsigned_or_bool<target_type>::type; + arg_ = detail::make_arg<Context>( + static_cast<unsigned>(static_cast<unsigned_type>(value))); + } + } 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. + arg_ = detail::make_arg<Context>(static_cast<long long>(value)); + } else { + arg_ = detail::make_arg<Context>( + static_cast<typename make_unsigned_or_bool<U>::type>(value)); + } + } + } + + template <typename U, FMT_ENABLE_IF(!std::is_integral<U>::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 <typename T, typename Context, typename Char> +void convert_arg(basic_format_arg<Context>& arg, Char type) { + visit_format_arg(arg_converter<T, Context>(arg, type), arg); +} + +// Converts an integer argument to char for printf. +template <typename Context> class char_converter { + private: + basic_format_arg<Context>& arg_; + + public: + explicit char_converter(basic_format_arg<Context>& arg) : arg_(arg) {} + + template <typename T, FMT_ENABLE_IF(std::is_integral<T>::value)> + void operator()(T value) { + arg_ = detail::make_arg<Context>( + static_cast<typename Context::char_type>(value)); + } + + template <typename T, FMT_ENABLE_IF(!std::is_integral<T>::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 <typename Char> struct get_cstring { + template <typename T> const Char* operator()(T) { return nullptr; } + const Char* operator()(const Char* s) { return s; } +}; + +// Checks if an argument is a valid printf width specifier and sets +// left alignment if it is negative. +template <typename Char> class printf_width_handler { + private: + using format_specs = basic_format_specs<Char>; + + format_specs& specs_; + + public: + explicit printf_width_handler(format_specs& specs) : specs_(specs) {} + + template <typename T, FMT_ENABLE_IF(std::is_integral<T>::value)> + unsigned operator()(T value) { + auto width = static_cast<uint32_or_64_or_128_t<T>>(value); + if (detail::is_negative(value)) { + specs_.align = align::left; + width = 0 - width; + } + unsigned int_max = max_value<int>(); + if (width > int_max) FMT_THROW(format_error("number is too big")); + return static_cast<unsigned>(width); + } + + template <typename T, FMT_ENABLE_IF(!std::is_integral<T>::value)> + unsigned operator()(T) { + FMT_THROW(format_error("width is not integer")); + return 0; + } +}; + +// The ``printf`` argument formatter. +template <typename OutputIt, typename Char> +class printf_arg_formatter : public arg_formatter<Char> { + private: + using base = arg_formatter<Char>; + using context_type = basic_printf_context<OutputIt, Char>; + using format_specs = basic_format_specs<Char>; + + context_type& context_; + + OutputIt write_null_pointer(bool is_string = false) { + auto s = this->specs; + s.type = presentation_type::none; + return write_bytes(this->out, is_string ? "(null)" : "(nil)", s); + } + + public: + printf_arg_formatter(OutputIt iter, format_specs& s, context_type& ctx) + : base{iter, s, locale_ref()}, context_(ctx) {} + + OutputIt operator()(monostate value) { return base::operator()(value); } + + template <typename T, FMT_ENABLE_IF(detail::is_integral<T>::value)> + OutputIt operator()(T value) { + // MSVC2013 fails to compile separate overloads for bool and Char so use + // std::is_same instead. + if (std::is_same<T, Char>::value) { + format_specs fmt_specs = this->specs; + if (fmt_specs.type != presentation_type::none && + fmt_specs.type != presentation_type::chr) { + return (*this)(static_cast<int>(value)); + } + fmt_specs.sign = sign::none; + fmt_specs.alt = false; + fmt_specs.fill[0] = ' '; // Ignore '0' flag for char types. + // align::numeric needs to be overwritten here since the '0' flag is + // ignored for non-numeric types + if (fmt_specs.align == align::none || fmt_specs.align == align::numeric) + fmt_specs.align = align::right; + return write<Char>(this->out, static_cast<Char>(value), fmt_specs); + } + return base::operator()(value); + } + + template <typename T, FMT_ENABLE_IF(std::is_floating_point<T>::value)> + OutputIt operator()(T value) { + return base::operator()(value); + } + + /** Formats a null-terminated C string. */ + OutputIt operator()(const char* value) { + if (value) return base::operator()(value); + return write_null_pointer(this->specs.type != presentation_type::pointer); + } + + /** Formats a null-terminated wide C string. */ + OutputIt operator()(const wchar_t* value) { + if (value) return base::operator()(value); + return write_null_pointer(this->specs.type != presentation_type::pointer); + } + + OutputIt operator()(basic_string_view<Char> value) { + return base::operator()(value); + } + + /** Formats a pointer. */ + OutputIt operator()(const void* value) { + return value ? base::operator()(value) : write_null_pointer(); + } + + /** Formats an argument of a custom (user-defined) type. */ + OutputIt operator()(typename basic_format_arg<context_type>::handle handle) { + auto parse_ctx = + basic_printf_parse_context<Char>(basic_string_view<Char>()); + handle.format(parse_ctx, context_); + return this->out; + } +}; + +template <typename Char> +void parse_flags(basic_format_specs<Char>& 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] = '0'; + break; + case ' ': + if (specs.sign != sign::plus) { + specs.sign = sign::space; + } + break; + case '#': + specs.alt = true; + break; + default: + return; + } + } +} + +template <typename Char, typename GetArg> +int parse_header(const Char*& it, const Char* end, + basic_format_specs<Char>& specs, GetArg get_arg) { + 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<int>(); + } else { + if (c == '0') specs.fill[0] = '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) FMT_THROW(format_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) FMT_THROW(format_error("number is too big")); + } else if (*it == '*') { + ++it; + specs.width = static_cast<int>(visit_format_arg( + detail::printf_width_handler<Char>(specs), get_arg(-1))); + } + } + return arg_index; +} + +template <typename Char, typename Context> +void vprintf(buffer<Char>& buf, basic_string_view<Char> format, + basic_format_args<Context> args) { + using OutputIt = buffer_appender<Char>; + auto out = OutputIt(buf); + auto context = basic_printf_context<OutputIt, Char>(out, args); + auto parse_ctx = basic_printf_parse_context<Char>(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 (!detail::find<false, Char>(it, end, '%', it)) { + it = end; // detail::find leaves it == nullptr if it doesn't find '%' + break; + } + Char c = *it++; + if (it != end && *it == c) { + out = detail::write( + out, basic_string_view<Char>(start, detail::to_unsigned(it - start))); + start = ++it; + continue; + } + out = detail::write(out, basic_string_view<Char>( + start, detail::to_unsigned(it - 1 - start))); + + basic_format_specs<Char> 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) parse_ctx.on_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<int>( + visit_format_arg(detail::printf_precision_handler(), get_arg(-1))); + } 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()) + specs.fill[0] = + ' '; // Ignore '0' flag for non-numeric types or if '-' present. + if (specs.precision >= 0 && arg.type() == detail::type::cstring_type) { + auto str = visit_format_arg(detail::get_cstring<Char>(), arg); + auto str_end = str + specs.precision; + auto nul = std::find(str, str_end, Char()); + arg = detail::make_arg<basic_printf_context<OutputIt, Char>>( + basic_string_view<Char>( + str, detail::to_unsigned(nul != str_end ? nul - str + : specs.precision))); + } + if (specs.alt && visit_format_arg(detail::is_zero_int(), arg)) + specs.alt = false; + if (specs.fill[0] == '0') { + if (arg.is_arithmetic() && specs.align != align::left) + specs.align = align::numeric; + else + specs.fill[0] = ' '; // 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; + using detail::convert_arg; + switch (c) { + case 'h': + if (t == 'h') { + ++it; + t = it != end ? *it : 0; + convert_arg<signed char>(arg, t); + } else { + convert_arg<short>(arg, t); + } + break; + case 'l': + if (t == 'l') { + ++it; + t = it != end ? *it : 0; + convert_arg<long long>(arg, t); + } else { + convert_arg<long>(arg, t); + } + break; + case 'j': + convert_arg<intmax_t>(arg, t); + break; + case 'z': + convert_arg<size_t>(arg, t); + break; + case 't': + convert_arg<std::ptrdiff_t>(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<void>(arg, c); + } + + // Parse type. + if (it == end) FMT_THROW(format_error("invalid format string")); + char type = static_cast<char>(*it++); + if (arg.is_integral()) { + // Normalize type. + switch (type) { + case 'i': + case 'u': + type = 'd'; + break; + case 'c': + visit_format_arg( + detail::char_converter<basic_printf_context<OutputIt, Char>>(arg), + arg); + break; + } + } + specs.type = parse_presentation_type(type); + if (specs.type == presentation_type::none) + parse_ctx.on_error("invalid type specifier"); + + start = it; + + // Format argument. + out = visit_format_arg( + detail::printf_arg_formatter<OutputIt, Char>(out, specs, context), arg); + } + detail::write(out, basic_string_view<Char>(start, to_unsigned(it - start))); +} +FMT_END_DETAIL_NAMESPACE + +template <typename Char> +using basic_printf_context_t = + basic_printf_context<detail::buffer_appender<Char>, Char>; + +using printf_context = basic_printf_context_t<char>; +using wprintf_context = basic_printf_context_t<wchar_t>; + +using printf_args = basic_format_args<printf_context>; +using wprintf_args = basic_format_args<wprintf_context>; + +/** + \rst + Constructs an `~fmt::format_arg_store` object that contains references to + arguments and can be implicitly converted to `~fmt::printf_args`. + \endrst + */ +template <typename... T> +inline auto make_printf_args(const T&... args) + -> format_arg_store<printf_context, T...> { + return {args...}; +} + +/** + \rst + Constructs an `~fmt::format_arg_store` object that contains references to + arguments and can be implicitly converted to `~fmt::wprintf_args`. + \endrst + */ +template <typename... T> +inline auto make_wprintf_args(const T&... args) + -> format_arg_store<wprintf_context, T...> { + return {args...}; +} + +template <typename S, typename Char = char_t<S>> +inline auto vsprintf( + const S& fmt, + basic_format_args<basic_printf_context_t<type_identity_t<Char>>> args) + -> std::basic_string<Char> { + basic_memory_buffer<Char> buffer; + vprintf(buffer, to_string_view(fmt), args); + return to_string(buffer); +} + +/** + \rst + Formats arguments and returns the result as a string. + + **Example**:: + + std::string message = fmt::sprintf("The answer is %d", 42); + \endrst +*/ +template <typename S, typename... T, + typename Char = enable_if_t<detail::is_string<S>::value, char_t<S>>> +inline auto sprintf(const S& fmt, const T&... args) -> std::basic_string<Char> { + using context = basic_printf_context_t<Char>; + return vsprintf(to_string_view(fmt), fmt::make_format_args<context>(args...)); +} + +template <typename S, typename Char = char_t<S>> +inline auto vfprintf( + std::FILE* f, const S& fmt, + basic_format_args<basic_printf_context_t<type_identity_t<Char>>> args) + -> int { + basic_memory_buffer<Char> buffer; + vprintf(buffer, to_string_view(fmt), args); + size_t size = buffer.size(); + return std::fwrite(buffer.data(), sizeof(Char), size, f) < size + ? -1 + : static_cast<int>(size); +} + +/** + \rst + Prints formatted data to the file *f*. + + **Example**:: + + fmt::fprintf(stderr, "Don't %s!", "panic"); + \endrst + */ +template <typename S, typename... T, typename Char = char_t<S>> +inline auto fprintf(std::FILE* f, const S& fmt, const T&... args) -> int { + using context = basic_printf_context_t<Char>; + return vfprintf(f, to_string_view(fmt), + fmt::make_format_args<context>(args...)); +} + +template <typename S, typename Char = char_t<S>> +inline auto vprintf( + const S& fmt, + basic_format_args<basic_printf_context_t<type_identity_t<Char>>> args) + -> int { + return vfprintf(stdout, to_string_view(fmt), args); +} + +/** + \rst + Prints formatted data to ``stdout``. + + **Example**:: + + fmt::printf("Elapsed time: %.2f seconds", 1.23); + \endrst + */ +template <typename S, typename... T, FMT_ENABLE_IF(detail::is_string<S>::value)> +inline auto printf(const S& fmt, const T&... args) -> int { + return vprintf( + to_string_view(fmt), + fmt::make_format_args<basic_printf_context_t<char_t<S>>>(args...)); +} + +template <typename S, typename Char = char_t<S>> +FMT_DEPRECATED auto vfprintf( + std::basic_ostream<Char>& os, const S& fmt, + basic_format_args<basic_printf_context_t<type_identity_t<Char>>> args) + -> int { + basic_memory_buffer<Char> buffer; + vprintf(buffer, to_string_view(fmt), args); + os.write(buffer.data(), static_cast<std::streamsize>(buffer.size())); + return static_cast<int>(buffer.size()); +} +template <typename S, typename... T, typename Char = char_t<S>> +FMT_DEPRECATED auto fprintf(std::basic_ostream<Char>& os, const S& fmt, + const T&... args) -> int { + return vfprintf(os, to_string_view(fmt), + fmt::make_format_args<basic_printf_context_t<Char>>(args...)); +} + +FMT_MODULE_EXPORT_END +FMT_END_NAMESPACE + +#endif // FMT_PRINTF_H_ diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/spdlog/fmt/bundled/ranges.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/spdlog/fmt/bundled/ranges.h new file mode 100644 index 0000000000000000000000000000000000000000..eb9fb8a92d6a0f8f0bcda12301349ac5c74b8cc2 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/spdlog/fmt/bundled/ranges.h @@ -0,0 +1,793 @@ +// Formatting library for C++ - experimental range support +// +// Copyright (c) 2012 - present, Victor Zverovich +// All rights reserved. +// +// For the license information refer to format.h. +// +// Copyright (c) 2018 - present, Remotion (Igor Schulz) +// All Rights Reserved +// {fmt} support for ranges, containers and types tuple interface. + +#ifndef FMT_RANGES_H_ +#define FMT_RANGES_H_ + +#include <initializer_list> +#include <tuple> +#include <type_traits> + +#include "format.h" + +FMT_BEGIN_NAMESPACE + +namespace detail { + +template <typename RangeT, typename OutputIterator> +OutputIterator copy(const RangeT& range, OutputIterator out) { + for (auto it = range.begin(), end = range.end(); it != end; ++it) + *out++ = *it; + return out; +} + +template <typename OutputIterator> +OutputIterator copy(const char* str, OutputIterator out) { + while (*str) *out++ = *str++; + return out; +} + +template <typename OutputIterator> +OutputIterator copy(char ch, OutputIterator out) { + *out++ = ch; + return out; +} + +template <typename OutputIterator> +OutputIterator copy(wchar_t ch, OutputIterator out) { + *out++ = ch; + return out; +} + +// Returns true if T has a std::string-like interface, like std::string_view. +template <typename T> class is_std_string_like { + template <typename U> + static auto check(U* p) + -> decltype((void)p->find('a'), p->length(), (void)p->data(), int()); + template <typename> static void check(...); + + public: + static FMT_CONSTEXPR_DECL const bool value = + is_string<T>::value || + std::is_convertible<T, std_string_view<char>>::value || + !std::is_void<decltype(check<T>(nullptr))>::value; +}; + +template <typename Char> +struct is_std_string_like<fmt::basic_string_view<Char>> : std::true_type {}; + +template <typename T> class is_map { + template <typename U> static auto check(U*) -> typename U::mapped_type; + template <typename> static void check(...); + + public: +#ifdef FMT_FORMAT_MAP_AS_LIST + static FMT_CONSTEXPR_DECL const bool value = false; +#else + static FMT_CONSTEXPR_DECL const bool value = + !std::is_void<decltype(check<T>(nullptr))>::value; +#endif +}; + +template <typename T> class is_set { + template <typename U> static auto check(U*) -> typename U::key_type; + template <typename> static void check(...); + + public: +#ifdef FMT_FORMAT_SET_AS_LIST + static FMT_CONSTEXPR_DECL const bool value = false; +#else + static FMT_CONSTEXPR_DECL const bool value = + !std::is_void<decltype(check<T>(nullptr))>::value && !is_map<T>::value; +#endif +}; + +template <typename... Ts> struct conditional_helper {}; + +template <typename T, typename _ = void> struct is_range_ : std::false_type {}; + +#if !FMT_MSC_VER || FMT_MSC_VER > 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 <typename T, std::size_t N> +auto range_begin(const T (&arr)[N]) -> const T* { + return arr; +} +template <typename T, std::size_t N> +auto range_end(const T (&arr)[N]) -> const T* { + return arr + N; +} + +template <typename T, typename Enable = void> +struct has_member_fn_begin_end_t : std::false_type {}; + +template <typename T> +struct has_member_fn_begin_end_t<T, void_t<decltype(std::declval<T>().begin()), + decltype(std::declval<T>().end())>> + : std::true_type {}; + +// Member function overload +template <typename T> +auto range_begin(T&& rng) FMT_DECLTYPE_RETURN(static_cast<T&&>(rng).begin()); +template <typename T> +auto range_end(T&& rng) FMT_DECLTYPE_RETURN(static_cast<T&&>(rng).end()); + +// ADL overload. Only participates in overload resolution if member functions +// are not found. +template <typename T> +auto range_begin(T&& rng) + -> enable_if_t<!has_member_fn_begin_end_t<T&&>::value, + decltype(begin(static_cast<T&&>(rng)))> { + return begin(static_cast<T&&>(rng)); +} +template <typename T> +auto range_end(T&& rng) -> enable_if_t<!has_member_fn_begin_end_t<T&&>::value, + decltype(end(static_cast<T&&>(rng)))> { + return end(static_cast<T&&>(rng)); +} + +template <typename T, typename Enable = void> +struct has_const_begin_end : std::false_type {}; +template <typename T, typename Enable = void> +struct has_mutable_begin_end : std::false_type {}; + +template <typename T> +struct has_const_begin_end< + T, + void_t< + decltype(detail::range_begin(std::declval<const remove_cvref_t<T>&>())), + decltype(detail::range_end(std::declval<const remove_cvref_t<T>&>()))>> + : std::true_type {}; + +template <typename T> +struct has_mutable_begin_end< + T, void_t<decltype(detail::range_begin(std::declval<T>())), + decltype(detail::range_end(std::declval<T>())), + enable_if_t<std::is_copy_constructible<T>::value>>> + : std::true_type {}; + +template <typename T> +struct is_range_<T, void> + : std::integral_constant<bool, (has_const_begin_end<T>::value || + has_mutable_begin_end<T>::value)> {}; +# undef FMT_DECLTYPE_RETURN +#endif + +// tuple_size and tuple_element check. +template <typename T> class is_tuple_like_ { + template <typename U> + static auto check(U* p) -> decltype(std::tuple_size<U>::value, int()); + template <typename> static void check(...); + + public: + static FMT_CONSTEXPR_DECL const bool value = + !std::is_void<decltype(check<T>(nullptr))>::value; +}; + +// Check for integer_sequence +#if defined(__cpp_lib_integer_sequence) || FMT_MSC_VER >= 1900 +template <typename T, T... N> +using integer_sequence = std::integer_sequence<T, N...>; +template <size_t... N> using index_sequence = std::index_sequence<N...>; +template <size_t N> using make_index_sequence = std::make_index_sequence<N>; +#else +template <typename T, T... N> struct integer_sequence { + using value_type = T; + + static FMT_CONSTEXPR size_t size() { return sizeof...(N); } +}; + +template <size_t... N> using index_sequence = integer_sequence<size_t, N...>; + +template <typename T, size_t N, T... Ns> +struct make_integer_sequence : make_integer_sequence<T, N - 1, N - 1, Ns...> {}; +template <typename T, T... Ns> +struct make_integer_sequence<T, 0, Ns...> : integer_sequence<T, Ns...> {}; + +template <size_t N> +using make_index_sequence = make_integer_sequence<size_t, N>; +#endif + +template <class Tuple, class F, size_t... Is> +void for_each(index_sequence<Is...>, Tuple&& tup, F&& f) FMT_NOEXCEPT { + using std::get; + // using free function get<I>(T) now. + const int _[] = {0, ((void)f(get<Is>(tup)), 0)...}; + (void)_; // blocks warnings +} + +template <class T> +FMT_CONSTEXPR make_index_sequence<std::tuple_size<T>::value> get_indexes( + T const&) { + return {}; +} + +template <class Tuple, class F> void for_each(Tuple&& tup, F&& f) { + const auto indexes = get_indexes(tup); + for_each(indexes, std::forward<Tuple>(tup), std::forward<F>(f)); +} + +template <typename Range> +using value_type = + remove_cvref_t<decltype(*detail::range_begin(std::declval<Range>()))>; + +template <typename OutputIt> OutputIt write_delimiter(OutputIt out) { + *out++ = ','; + *out++ = ' '; + return out; +} + +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<int>(x); + auto current = true; + for (size_t i = 0; i < normal_size; ++i) { + auto v = static_cast<int>(normal[i]); + auto len = (v & 0x80) != 0 ? (v & 0x7f) << 8 | normal[++i] : v; + xsigned -= len; + if (xsigned < 0) break; + current = !current; + } + return current; +} + +// Returns true iff the code point cp is printable. +// This code is generated by support/printable.py. +inline 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<uint16_t>(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; +} + +inline auto needs_escape(uint32_t cp) -> bool { + return cp < 0x20 || cp == 0x7f || cp == '"' || cp == '\\' || + !is_printable(cp); +} + +template <typename Char> struct find_escape_result { + const Char* begin; + const Char* end; + uint32_t cp; +}; + +template <typename Char> +auto find_escape(const Char* begin, const Char* end) + -> find_escape_result<Char> { + for (; begin != end; ++begin) { + auto cp = static_cast<typename std::make_unsigned<Char>::type>(*begin); + if (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<char> { + if (!is_utf8()) return find_escape<char>(begin, end); + auto result = find_escape_result<char>{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; +} + +template <typename Char, typename OutputIt> +auto write_range_entry(OutputIt out, basic_string_view<Char> str) -> OutputIt { + *out++ = '"'; + auto begin = str.begin(), end = str.end(); + do { + auto escape = find_escape(begin, end); + out = copy_str<Char>(begin, escape.begin, out); + begin = escape.end; + if (!begin) break; + auto c = static_cast<Char>(escape.cp); + switch (escape.cp) { + case '\n': + *out++ = '\\'; + c = 'n'; + break; + case '\r': + *out++ = '\\'; + c = 'r'; + break; + case '\t': + *out++ = '\\'; + c = 't'; + break; + case '"': + FMT_FALLTHROUGH; + case '\\': + *out++ = '\\'; + break; + default: + if (is_utf8()) { + if (escape.cp < 0x100) { + out = format_to(out, "\\x{:02x}", escape.cp); + continue; + } + if (escape.cp < 0x10000) { + out = format_to(out, "\\u{:04x}", escape.cp); + continue; + } + if (escape.cp < 0x110000) { + out = format_to(out, "\\U{:08x}", escape.cp); + continue; + } + } + for (Char escape_char : basic_string_view<Char>( + escape.begin, to_unsigned(escape.end - escape.begin))) { + out = format_to( + out, "\\x{:02x}", + static_cast<typename std::make_unsigned<Char>::type>(escape_char)); + } + continue; + } + *out++ = c; + } while (begin != end); + *out++ = '"'; + return out; +} + +template <typename Char, typename OutputIt, typename T, + FMT_ENABLE_IF(std::is_convertible<T, std_string_view<char>>::value)> +inline auto write_range_entry(OutputIt out, const T& str) -> OutputIt { + auto sv = std_string_view<Char>(str); + return write_range_entry<Char>(out, basic_string_view<Char>(sv)); +} + +template <typename Char, typename OutputIt, typename Arg, + FMT_ENABLE_IF(std::is_same<Arg, Char>::value)> +OutputIt write_range_entry(OutputIt out, const Arg v) { + *out++ = '\''; + *out++ = v; + *out++ = '\''; + return out; +} + +template < + typename Char, typename OutputIt, typename Arg, + FMT_ENABLE_IF(!is_std_string_like<typename std::decay<Arg>::type>::value && + !std::is_same<Arg, Char>::value)> +OutputIt write_range_entry(OutputIt out, const Arg& v) { + return write<Char>(out, v); +} + +} // namespace detail + +template <typename T> struct is_tuple_like { + static FMT_CONSTEXPR_DECL const bool value = + detail::is_tuple_like_<T>::value && !detail::is_range_<T>::value; +}; + +template <typename TupleT, typename Char> +struct formatter<TupleT, Char, enable_if_t<fmt::is_tuple_like<TupleT>::value>> { + private: + // C++11 generic lambda for format(). + template <typename FormatContext> struct format_each { + template <typename T> void operator()(const T& v) { + if (i > 0) out = detail::write_delimiter(out); + out = detail::write_range_entry<Char>(out, v); + ++i; + } + int i; + typename FormatContext::iterator& out; + }; + + public: + template <typename ParseContext> + FMT_CONSTEXPR auto parse(ParseContext& ctx) -> decltype(ctx.begin()) { + return ctx.begin(); + } + + template <typename FormatContext = format_context> + auto format(const TupleT& values, FormatContext& ctx) -> decltype(ctx.out()) { + auto out = ctx.out(); + *out++ = '('; + detail::for_each(values, format_each<FormatContext>{0, out}); + *out++ = ')'; + return out; + } +}; + +template <typename T, typename Char> struct is_range { + static FMT_CONSTEXPR_DECL const bool value = + detail::is_range_<T>::value && !detail::is_std_string_like<T>::value && + !detail::is_map<T>::value && + !std::is_convertible<T, std::basic_string<Char>>::value && + !std::is_constructible<detail::std_string_view<Char>, T>::value; +}; + +template <typename T, typename Char> +struct formatter< + T, Char, + enable_if_t< + fmt::is_range<T, Char>::value +// Workaround a bug in MSVC 2019 and earlier. +#if !FMT_MSC_VER + && (is_formattable<detail::value_type<T>, Char>::value || + detail::has_fallback_formatter<detail::value_type<T>, Char>::value) +#endif + >> { + template <typename ParseContext> + FMT_CONSTEXPR auto parse(ParseContext& ctx) -> decltype(ctx.begin()) { + return ctx.begin(); + } + + template < + typename FormatContext, typename U, + FMT_ENABLE_IF( + std::is_same<U, conditional_t<detail::has_const_begin_end<T>::value, + const T, T>>::value)> + auto format(U& range, FormatContext& ctx) -> decltype(ctx.out()) { +#ifdef FMT_DEPRECATED_BRACED_RANGES + Char prefix = '{'; + Char postfix = '}'; +#else + Char prefix = detail::is_set<T>::value ? '{' : '['; + Char postfix = detail::is_set<T>::value ? '}' : ']'; +#endif + auto out = ctx.out(); + *out++ = prefix; + int i = 0; + auto it = std::begin(range); + auto end = std::end(range); + for (; it != end; ++it) { + if (i > 0) out = detail::write_delimiter(out); + out = detail::write_range_entry<Char>(out, *it); + ++i; + } + *out++ = postfix; + return out; + } +}; + +template <typename T, typename Char> +struct formatter< + T, Char, + enable_if_t< + detail::is_map<T>::value +// Workaround a bug in MSVC 2019 and earlier. +#if !FMT_MSC_VER + && (is_formattable<detail::value_type<T>, Char>::value || + detail::has_fallback_formatter<detail::value_type<T>, Char>::value) +#endif + >> { + template <typename ParseContext> + FMT_CONSTEXPR auto parse(ParseContext& ctx) -> decltype(ctx.begin()) { + return ctx.begin(); + } + + template < + typename FormatContext, typename U, + FMT_ENABLE_IF( + std::is_same<U, conditional_t<detail::has_const_begin_end<T>::value, + const T, T>>::value)> + auto format(U& map, FormatContext& ctx) -> decltype(ctx.out()) { + auto out = ctx.out(); + *out++ = '{'; + int i = 0; + for (const auto& item : map) { + if (i > 0) out = detail::write_delimiter(out); + out = detail::write_range_entry<Char>(out, item.first); + *out++ = ':'; + *out++ = ' '; + out = detail::write_range_entry<Char>(out, item.second); + ++i; + } + *out++ = '}'; + return out; + } +}; + +template <typename Char, typename... T> struct tuple_join_view : detail::view { + const std::tuple<T...>& tuple; + basic_string_view<Char> sep; + + tuple_join_view(const std::tuple<T...>& t, basic_string_view<Char> s) + : tuple(t), sep{s} {} +}; + +template <typename Char, typename... T> +using tuple_arg_join = tuple_join_view<Char, T...>; + +// 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 <typename Char, typename... T> +struct formatter<tuple_join_view<Char, T...>, Char> { + template <typename ParseContext> + FMT_CONSTEXPR auto parse(ParseContext& ctx) -> decltype(ctx.begin()) { + return do_parse(ctx, std::integral_constant<size_t, sizeof...(T)>()); + } + + template <typename FormatContext> + auto format(const tuple_join_view<Char, T...>& value, + FormatContext& ctx) const -> typename FormatContext::iterator { + return do_format(value, ctx, + std::integral_constant<size_t, sizeof...(T)>()); + } + + private: + std::tuple<formatter<typename std::decay<T>::type, Char>...> formatters_; + + template <typename ParseContext> + FMT_CONSTEXPR auto do_parse(ParseContext& ctx, + std::integral_constant<size_t, 0>) + -> decltype(ctx.begin()) { + return ctx.begin(); + } + + template <typename ParseContext, size_t N> + FMT_CONSTEXPR auto do_parse(ParseContext& ctx, + std::integral_constant<size_t, N>) + -> decltype(ctx.begin()) { + auto end = ctx.begin(); +#if FMT_TUPLE_JOIN_SPECIFIERS + end = std::get<sizeof...(T) - N>(formatters_).parse(ctx); + if (N > 1) { + auto end1 = do_parse(ctx, std::integral_constant<size_t, N - 1>()); + if (end != end1) + FMT_THROW(format_error("incompatible format specs for tuple elements")); + } +#endif + return end; + } + + template <typename FormatContext> + auto do_format(const tuple_join_view<Char, T...>&, FormatContext& ctx, + std::integral_constant<size_t, 0>) const -> + typename FormatContext::iterator { + return ctx.out(); + } + + template <typename FormatContext, size_t N> + auto do_format(const tuple_join_view<Char, T...>& value, FormatContext& ctx, + std::integral_constant<size_t, N>) const -> + typename FormatContext::iterator { + auto out = std::get<sizeof...(T) - N>(formatters_) + .format(std::get<sizeof...(T) - N>(value.tuple), ctx); + if (N > 1) { + out = std::copy(value.sep.begin(), value.sep.end(), out); + ctx.advance_to(out); + return do_format(value, ctx, std::integral_constant<size_t, N - 1>()); + } + return out; + } +}; + +FMT_MODULE_EXPORT_BEGIN + +/** + \rst + Returns an object that formats `tuple` with elements separated by `sep`. + + **Example**:: + + std::tuple<int, char> t = {1, 'a'}; + fmt::print("{}", fmt::join(t, ", ")); + // Output: "1, a" + \endrst + */ +template <typename... T> +FMT_CONSTEXPR auto join(const std::tuple<T...>& tuple, string_view sep) + -> tuple_join_view<char, T...> { + return {tuple, sep}; +} + +template <typename... T> +FMT_CONSTEXPR auto join(const std::tuple<T...>& tuple, + basic_string_view<wchar_t> sep) + -> tuple_join_view<wchar_t, T...> { + return {tuple, sep}; +} + +/** + \rst + Returns an object that formats `initializer_list` with elements separated by + `sep`. + + **Example**:: + + fmt::print("{}", fmt::join({1, 2, 3}, ", ")); + // Output: "1, 2, 3" + \endrst + */ +template <typename T> +auto join(std::initializer_list<T> list, string_view sep) + -> join_view<const T*, const T*> { + return join(std::begin(list), std::end(list), sep); +} + +FMT_MODULE_EXPORT_END +FMT_END_NAMESPACE + +#endif // FMT_RANGES_H_ diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/spdlog/fmt/bundled/xchar.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/spdlog/fmt/bundled/xchar.h new file mode 100644 index 0000000000000000000000000000000000000000..55825077f8ed21d386661f089efd0bbcf200b861 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/spdlog/fmt/bundled/xchar.h @@ -0,0 +1,236 @@ +// 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 <cwchar> +#include <tuple> + +#include "format.h" + +FMT_BEGIN_NAMESPACE +namespace detail { +template <typename T> +using is_exotic_char = bool_constant<!std::is_same<T, char>::value>; +} + +FMT_MODULE_EXPORT_BEGIN + +using wstring_view = basic_string_view<wchar_t>; +using wformat_parse_context = basic_format_parse_context<wchar_t>; +using wformat_context = buffer_context<wchar_t>; +using wformat_args = basic_format_args<wformat_context>; +using wmemory_buffer = basic_memory_buffer<wchar_t>; + +#if FMT_GCC_VERSION && FMT_GCC_VERSION < 409 +// Workaround broken conversion on older gcc. +template <typename... Args> using wformat_string = wstring_view; +#else +template <typename... Args> +using wformat_string = basic_format_string<wchar_t, type_identity_t<Args>...>; +#endif + +template <> struct is_char<wchar_t> : std::true_type {}; +template <> struct is_char<detail::char8_type> : std::true_type {}; +template <> struct is_char<char16_t> : std::true_type {}; +template <> struct is_char<char32_t> : std::true_type {}; + +template <typename... Args> +constexpr format_arg_store<wformat_context, Args...> make_wformat_args( + const Args&... args) { + return {args...}; +} + +inline namespace literals { +constexpr auto operator"" _format(const wchar_t* s, size_t n) + -> detail::udl_formatter<wchar_t> { + return {{s, n}}; +} + +#if FMT_USE_USER_DEFINED_LITERALS && !FMT_USE_NONTYPE_TEMPLATE_PARAMETERS +constexpr detail::udl_arg<wchar_t> operator"" _a(const wchar_t* s, size_t) { + return {s}; +} +#endif +} // namespace literals + +template <typename It, typename Sentinel> +auto join(It begin, Sentinel end, wstring_view sep) + -> join_view<It, Sentinel, wchar_t> { + return {begin, end, sep}; +} + +template <typename Range> +auto join(Range&& range, wstring_view sep) + -> join_view<detail::iterator_t<Range>, detail::sentinel_t<Range>, + wchar_t> { + return join(std::begin(range), std::end(range), sep); +} + +template <typename T> +auto join(std::initializer_list<T> list, wstring_view sep) + -> join_view<const T*, const T*, wchar_t> { + return join(std::begin(list), std::end(list), sep); +} + +template <typename Char, FMT_ENABLE_IF(!std::is_same<Char, char>::value)> +auto vformat(basic_string_view<Char> format_str, + basic_format_args<buffer_context<type_identity_t<Char>>> args) + -> std::basic_string<Char> { + basic_memory_buffer<Char> buffer; + detail::vformat_to(buffer, format_str, args); + return to_string(buffer); +} + +// Pass char_t as a default template parameter instead of using +// std::basic_string<char_t<S>> to reduce the symbol size. +template <typename S, typename... Args, typename Char = char_t<S>, + FMT_ENABLE_IF(!std::is_same<Char, char>::value)> +auto format(const S& format_str, Args&&... args) -> std::basic_string<Char> { + const auto& vargs = fmt::make_args_checked<Args...>(format_str, args...); + return vformat(to_string_view(format_str), vargs); +} + +template <typename Locale, typename S, typename Char = char_t<S>, + FMT_ENABLE_IF(detail::is_locale<Locale>::value&& + detail::is_exotic_char<Char>::value)> +inline auto vformat( + const Locale& loc, const S& format_str, + basic_format_args<buffer_context<type_identity_t<Char>>> args) + -> std::basic_string<Char> { + return detail::vformat(loc, to_string_view(format_str), args); +} + +template <typename Locale, typename S, typename... Args, + typename Char = char_t<S>, + FMT_ENABLE_IF(detail::is_locale<Locale>::value&& + detail::is_exotic_char<Char>::value)> +inline auto format(const Locale& loc, const S& format_str, Args&&... args) + -> std::basic_string<Char> { + return detail::vformat(loc, to_string_view(format_str), + fmt::make_args_checked<Args...>(format_str, args...)); +} + +template <typename OutputIt, typename S, typename Char = char_t<S>, + FMT_ENABLE_IF(detail::is_output_iterator<OutputIt, Char>::value&& + detail::is_exotic_char<Char>::value)> +auto vformat_to(OutputIt out, const S& format_str, + basic_format_args<buffer_context<type_identity_t<Char>>> args) + -> OutputIt { + auto&& buf = detail::get_buffer<Char>(out); + detail::vformat_to(buf, to_string_view(format_str), args); + return detail::get_iterator(buf); +} + +template <typename OutputIt, typename S, typename... Args, + typename Char = char_t<S>, + FMT_ENABLE_IF(detail::is_output_iterator<OutputIt, Char>::value&& + detail::is_exotic_char<Char>::value)> +inline auto format_to(OutputIt out, const S& fmt, Args&&... args) -> OutputIt { + const auto& vargs = fmt::make_args_checked<Args...>(fmt, args...); + return vformat_to(out, to_string_view(fmt), vargs); +} + +template <typename S, typename... Args, typename Char, size_t SIZE, + typename Allocator, FMT_ENABLE_IF(detail::is_string<S>::value)> +FMT_DEPRECATED auto format_to(basic_memory_buffer<Char, SIZE, Allocator>& buf, + const S& format_str, Args&&... args) -> + typename buffer_context<Char>::iterator { + const auto& vargs = fmt::make_args_checked<Args...>(format_str, args...); + detail::vformat_to(buf, to_string_view(format_str), vargs, {}); + return detail::buffer_appender<Char>(buf); +} + +template <typename Locale, typename S, typename OutputIt, typename... Args, + typename Char = char_t<S>, + FMT_ENABLE_IF(detail::is_output_iterator<OutputIt, Char>::value&& + detail::is_locale<Locale>::value&& + detail::is_exotic_char<Char>::value)> +inline auto vformat_to( + OutputIt out, const Locale& loc, const S& format_str, + basic_format_args<buffer_context<type_identity_t<Char>>> args) -> OutputIt { + auto&& buf = detail::get_buffer<Char>(out); + vformat_to(buf, to_string_view(format_str), args, detail::locale_ref(loc)); + return detail::get_iterator(buf); +} + +template < + typename OutputIt, typename Locale, typename S, typename... Args, + typename Char = char_t<S>, + bool enable = detail::is_output_iterator<OutputIt, Char>::value&& + detail::is_locale<Locale>::value&& detail::is_exotic_char<Char>::value> +inline auto format_to(OutputIt out, const Locale& loc, const S& format_str, + Args&&... args) -> + typename std::enable_if<enable, OutputIt>::type { + const auto& vargs = fmt::make_args_checked<Args...>(format_str, args...); + return vformat_to(out, loc, to_string_view(format_str), vargs); +} + +template <typename OutputIt, typename Char, typename... Args, + FMT_ENABLE_IF(detail::is_output_iterator<OutputIt, Char>::value&& + detail::is_exotic_char<Char>::value)> +inline auto vformat_to_n( + OutputIt out, size_t n, basic_string_view<Char> format_str, + basic_format_args<buffer_context<type_identity_t<Char>>> args) + -> format_to_n_result<OutputIt> { + detail::iterator_buffer<OutputIt, Char, detail::fixed_buffer_traits> buf(out, + n); + detail::vformat_to(buf, format_str, args); + return {buf.out(), buf.count()}; +} + +template <typename OutputIt, typename S, typename... Args, + typename Char = char_t<S>, + FMT_ENABLE_IF(detail::is_output_iterator<OutputIt, Char>::value&& + detail::is_exotic_char<Char>::value)> +inline auto format_to_n(OutputIt out, size_t n, const S& fmt, + const Args&... args) -> format_to_n_result<OutputIt> { + const auto& vargs = fmt::make_args_checked<Args...>(fmt, args...); + return vformat_to_n(out, n, to_string_view(fmt), vargs); +} + +template <typename S, typename... Args, typename Char = char_t<S>, + FMT_ENABLE_IF(detail::is_exotic_char<Char>::value)> +inline auto formatted_size(const S& fmt, Args&&... args) -> size_t { + detail::counting_buffer<Char> buf; + const auto& vargs = fmt::make_args_checked<Args...>(fmt, args...); + detail::vformat_to(buf, to_string_view(fmt), vargs); + return buf.count(); +} + +inline void vprint(std::FILE* f, wstring_view fmt, wformat_args args) { + wmemory_buffer buffer; + detail::vformat_to(buffer, fmt, args); + buffer.push_back(L'\0'); + if (std::fputws(buffer.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 <typename... T> +void print(std::FILE* f, wformat_string<T...> fmt, T&&... args) { + return vprint(f, wstring_view(fmt), fmt::make_wformat_args(args...)); +} + +template <typename... T> void print(wformat_string<T...> fmt, T&&... args) { + return vprint(wstring_view(fmt), fmt::make_wformat_args(args...)); +} + +/** + Converts *value* to ``std::wstring`` using the default format for type *T*. + */ +template <typename T> inline auto to_wstring(const T& value) -> std::wstring { + return format(FMT_STRING(L"{}"), value); +} +FMT_MODULE_EXPORT_END +FMT_END_NAMESPACE + +#endif // FMT_XCHAR_H_ 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 0000000000000000000000000000000000000000..83fad2ff9a54afba704a22d9b401530be601681b --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/spdlog/fmt/chrono.h @@ -0,0 +1,22 @@ +// +// 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 +// + +#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 <spdlog/fmt/bundled/chrono.h> +# else +# include <fmt/chrono.h> +# 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 0000000000000000000000000000000000000000..906e9f57accddb334c21543303869567b3f40f50 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/spdlog/fmt/compile.h @@ -0,0 +1,22 @@ +// +// 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 +// + +#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 <spdlog/fmt/bundled/compile.h> +# else +# include <fmt/compile.h> +# 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 0000000000000000000000000000000000000000..fa4a2a84f595e8e2856a009d5ffbce1334357c97 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/spdlog/fmt/fmt.h @@ -0,0 +1,29 @@ +// +// 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. +// + +#if defined(SPDLOG_USE_STD_FORMAT) // SPDLOG_USE_STD_FORMAT is defined - use std::format +# include <format> +#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 +// enable the 'n' flag in for backward compatibility with fmt 6.x +# define FMT_DEPRECATED_N_SPECIFIER +# include <spdlog/fmt/bundled/core.h> +# include <spdlog/fmt/bundled/format.h> +#else // SPDLOG_FMT_EXTERNAL is defined - use external fmtlib +# include <fmt/core.h> +# include <fmt/format.h> +#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 0000000000000000000000000000000000000000..75880341761dc6b41d8942e058c846f86399c4ec --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/spdlog/fmt/ostr.h @@ -0,0 +1,22 @@ +// +// 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 +// + +#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 <spdlog/fmt/bundled/ostream.h> +# else +# include <fmt/ostream.h> +# 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 0000000000000000000000000000000000000000..9103a5f6a7f337c2767a07d471c19a36361ef6ab --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/spdlog/fmt/ranges.h @@ -0,0 +1,22 @@ +// +// 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 +// + +#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 <spdlog/fmt/bundled/ranges.h> +# else +# include <fmt/ranges.h> +# 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 0000000000000000000000000000000000000000..9a766e5a08db4355c74b2bf340c785732d881732 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/spdlog/fmt/xchar.h @@ -0,0 +1,22 @@ +// +// 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 +// + +#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 <spdlog/fmt/bundled/xchar.h> +# else +# include <fmt/xchar.h> +# 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 0000000000000000000000000000000000000000..5086fb2172e1d1baab1f9449d76718c9b11c4b55 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/spdlog/formatter.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 + +#include <spdlog/fmt/fmt.h> +#include <spdlog/details/log_msg.h> + +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<formatter> 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 0000000000000000000000000000000000000000..d258825727a2ee0f3760d50dd9c499ab5b6ce708 --- /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 0000000000000000000000000000000000000000..411f2cb5a4d36e2610925542d86165af3438c38d --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/spdlog/logger-inl.h @@ -0,0 +1,257 @@ +// 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 <spdlog/logger.h> +#endif + +#include <spdlog/sinks/sink.h> +#include <spdlog/details/backtracer.h> +#include <spdlog/pattern_formatter.h> + +#include <cstdio> + +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::level_enum>(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<formatter> 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<pattern_formatter>(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<level::level_enum>(flush_level_.load(std::memory_order_relaxed)); +} + +// sinks +SPDLOG_INLINE const std::vector<sink_ptr> &logger::sinks() const +{ + return sinks_; +} + +SPDLOG_INLINE std::vector<sink_ptr> &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> logger::clone(std::string logger_name) +{ + auto cloned = std::make_shared<logger>(*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()) + { + 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<std::mutex> 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 0000000000000000000000000000000000000000..a8abae419a97adae67af46a243ad25c11a6785c8 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/spdlog/logger.h @@ -0,0 +1,447 @@ +// 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 <spdlog/common.h> +#include <spdlog/details/log_msg.h> +#include <spdlog/details/backtracer.h> + +#ifdef SPDLOG_WCHAR_TO_UTF8_SUPPORT +# ifndef _WIN32 +# error SPDLOG_WCHAR_TO_UTF8_SUPPORT only supported on windows +# endif +# include <spdlog/details/os.h> +#endif + +#include <vector> + +#ifndef SPDLOG_NO_EXCEPTIONS +# define SPDLOG_LOGGER_CATCH(location) \ + catch (const std::exception &ex) \ + { \ + if (location.filename) \ + { \ + err_handler_(fmt_lib::format("{} [{}({})]", 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<typename It> + 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<typename... Args> + void log(source_loc loc, level::level_enum lvl, format_string_t<Args...> fmt, Args &&... args) + { + log_(loc, lvl, fmt, std::forward<Args>(args)...); + } + + template<typename... Args> + void log(level::level_enum lvl, format_string_t<Args...> fmt, Args &&... args) + { + log(source_loc{}, lvl, fmt, std::forward<Args>(args)...); + } + + template<typename T> + 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<class T, typename std::enable_if<!is_convertible_to_any_format_string<const T &>::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<typename... Args> + void trace(format_string_t<Args...> fmt, Args &&... args) + { + log(level::trace, fmt, std::forward<Args>(args)...); + } + + template<typename... Args> + void debug(format_string_t<Args...> fmt, Args &&... args) + { + log(level::debug, fmt, std::forward<Args>(args)...); + } + + template<typename... Args> + void info(format_string_t<Args...> fmt, Args &&... args) + { + log(level::info, fmt, std::forward<Args>(args)...); + } + + template<typename... Args> + void warn(format_string_t<Args...> fmt, Args &&... args) + { + log(level::warn, fmt, std::forward<Args>(args)...); + } + + template<typename... Args> + void error(format_string_t<Args...> fmt, Args &&... args) + { + log(level::err, fmt, std::forward<Args>(args)...); + } + + template<typename... Args> + void critical(format_string_t<Args...> fmt, Args &&... args) + { + log(level::critical, fmt, std::forward<Args>(args)...); + } + +#ifdef SPDLOG_WCHAR_TO_UTF8_SUPPORT + template<typename... Args> + void log(source_loc loc, level::level_enum lvl, wformat_string_t<Args...> fmt, Args &&... args) + { + log_(loc, lvl, fmt, std::forward<Args>(args)...); + } + + template<typename... Args> + void log(level::level_enum lvl, wformat_string_t<Args...> fmt, Args &&... args) + { + log(source_loc{}, lvl, fmt, std::forward<Args>(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<typename... Args> + void trace(wformat_string_t<Args...> fmt, Args &&... args) + { + log(level::trace, fmt, std::forward<Args>(args)...); + } + + template<typename... Args> + void debug(wformat_string_t<Args...> fmt, Args &&... args) + { + log(level::debug, fmt, std::forward<Args>(args)...); + } + + template<typename... Args> + void info(wformat_string_t<Args...> fmt, Args &&... args) + { + log(level::info, fmt, std::forward<Args>(args)...); + } + + template<typename... Args> + void warn(wformat_string_t<Args...> fmt, Args &&... args) + { + log(level::warn, fmt, std::forward<Args>(args)...); + } + + template<typename... Args> + void error(wformat_string_t<Args...> fmt, Args &&... args) + { + log(level::err, fmt, std::forward<Args>(args)...); + } + + template<typename... Args> + void critical(wformat_string_t<Args...> fmt, Args &&... args) + { + log(level::critical, fmt, std::forward<Args>(args)...); + } +#endif + + template<typename T> + void trace(const T &msg) + { + log(level::trace, msg); + } + + template<typename T> + void debug(const T &msg) + { + log(level::debug, msg); + } + + template<typename T> + void info(const T &msg) + { + log(level::info, msg); + } + + template<typename T> + void warn(const T &msg) + { + log(level::warn, msg); + } + + template<typename T> + void error(const T &msg) + { + log(level::err, msg); + } + + template<typename T> + 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<formatter> f); + + 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<sink_ptr> &sinks() const; + + std::vector<sink_ptr> &sinks(); + + // error handler + void set_error_handler(err_handler); + + // create new logger with same sinks and configuration. + virtual std::shared_ptr<logger> clone(std::string logger_name); + +protected: + std::string name_; + std::vector<sink_ptr> 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<typename... Args> + 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 + { +#ifdef SPDLOG_USE_STD_FORMAT + memory_buf_t buf = std::vformat(fmt, std::make_format_args(std::forward<Args>(args)...)); +#else + memory_buf_t buf; + fmt::detail::vformat_to(buf, fmt, fmt::make_format_args(std::forward<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<typename... Args> + 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 + ; +# ifdef SPDLOG_USE_STD_FORMAT + wmemory_buf_t wbuf = std::vformat(fmt, std::make_wformat_args(std::forward<Args>(args)...)); +# else + wmemory_buf_t wbuf; + fmt::detail::vformat_to(wbuf, fmt, fmt::make_format_args<fmt::wformat_context>(std::forward<Args>(args)...)); +# endif + 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) + } + + // T can be statically converted to wstring_view, and no formatting needed. + template<class T, typename std::enable_if<std::is_convertible<const T &, spdlog::wstring_view_t>::value, int>::type = 0> + void log_(source_loc loc, level::level_enum lvl, const T &msg) + { + bool log_enabled = should_log(lvl); + bool traceback_enabled = tracer_.enabled(); + if (!log_enabled && !traceback_enabled) + { + return; + } + SPDLOG_TRY + { + memory_buf_t buf; + details::os::wstr_to_utf8buf(msg, 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/pattern_formatter-inl.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/spdlog/pattern_formatter-inl.h new file mode 100644 index 0000000000000000000000000000000000000000..bf9da079f7be6678775cbc2a297d5825c70c1826 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/spdlog/pattern_formatter-inl.h @@ -0,0 +1,1425 @@ +// 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 <spdlog/pattern_formatter.h> +#endif + +#include <spdlog/details/fmt_helper.h> +#include <spdlog/details/log_msg.h> +#include <spdlog/details/os.h> +#include <spdlog/fmt/fmt.h> +#include <spdlog/formatter.h> + +#include <algorithm> +#include <array> +#include <chrono> +#include <ctime> +#include <cctype> +#include <cstring> +#include <iterator> +#include <memory> +#include <mutex> +#include <string> +#include <thread> +#include <utility> +#include <vector> + +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<long>(padinfo.width_) - static_cast<long>(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<typename T> + 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<long>(dest_.size()) + remaining_pad_; + dest_.resize(static_cast<size_t>(new_size)); + } + } + +private: + void pad_it(long count) + { + fmt_helper::append_string_view(string_view_t(spaces_.data(), static_cast<size_t>(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<typename T> + static unsigned int count_digits(T /* number */) + { + return 0; + } +}; + +template<typename ScopedPadder> +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<typename ScopedPadder> +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<typename ScopedPadder> +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<const char *, 7> days{{"Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"}}; + +template<typename ScopedPadder> +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<size_t>(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<const char *, 7> full_days{{"Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"}}; + +template<typename ScopedPadder> +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<size_t>(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<const char *, 12> months{{"Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sept", "Oct", "Nov", "Dec"}}; + +template<typename ScopedPadder> +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<size_t>(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<const char *, 12> full_months{ + {"January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"}}; + +template<typename ScopedPadder> +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<size_t>(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<typename ScopedPadder> +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<size_t>(tm_time.tm_wday)], dest); + dest.push_back(' '); + fmt_helper::append_string_view(months[static_cast<size_t>(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<typename ScopedPadder> +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<typename ScopedPadder> +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<typename ScopedPadder> +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<typename ScopedPadder> +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<typename ScopedPadder> +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<typename ScopedPadder> +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<typename ScopedPadder> +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<typename ScopedPadder> +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<typename ScopedPadder> +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<typename ScopedPadder> +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<std::chrono::milliseconds>(msg.time); + const size_t field_size = 3; + ScopedPadder p(field_size, padinfo_, dest); + fmt_helper::pad3(static_cast<uint32_t>(millis.count()), dest); + } +}; + +// microseconds +template<typename ScopedPadder> +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<std::chrono::microseconds>(msg.time); + + const size_t field_size = 6; + ScopedPadder p(field_size, padinfo_, dest); + fmt_helper::pad6(static_cast<size_t>(micros.count()), dest); + } +}; + +// nanoseconds +template<typename ScopedPadder> +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<std::chrono::nanoseconds>(msg.time); + const size_t field_size = 9; + ScopedPadder p(field_size, padinfo_, dest); + fmt_helper::pad9(static_cast<size_t>(ns.count()), dest); + } +}; + +// seconds since epoch +template<typename ScopedPadder> +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<std::chrono::seconds>(duration).count(); + fmt_helper::append_int(seconds, dest); + } +}; + +// AM/PM +template<typename ScopedPadder> +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<typename ScopedPadder> +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<typename ScopedPadder> +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<typename ScopedPadder> +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<typename ScopedPadder> +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<typename ScopedPadder> +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<typename ScopedPadder> +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<uint32_t>(details::os::pid()); + auto field_size = ScopedPadder::count_digits(pid); + ScopedPadder p(field_size, padinfo_, dest); + fmt_helper::append_int(pid, dest); + } +}; + +template<typename ScopedPadder> +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<typename ScopedPadder> +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<char>::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<typename ScopedPadder> +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<char>::length(msg.source.filename) : 0; + ScopedPadder p(text_size, padinfo_, dest); + fmt_helper::append_string_view(msg.source.filename, dest); + } +}; + +template<typename ScopedPadder> +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<const char *> begin(filename + std::strlen(filename)); + const std::reverse_iterator<const char *> 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<char>::length(filename) : 0; + ScopedPadder p(text_size, padinfo_, dest); + fmt_helper::append_string_view(filename, dest); + } +}; + +template<typename ScopedPadder> +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<typename ScopedPadder> +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<char>::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<typename ScopedPadder, typename Units> +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<DurationUnits>(delta); + last_message_time_ = msg.time; + auto delta_count = static_cast<size_t>(delta_units.count()); + auto n_digits = static_cast<size_t>(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_; +}; + +// 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<seconds>(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<milliseconds>(msg.time); + fmt_helper::pad3(static_cast<uint32_t>(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<details::null_scoped_padder>::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(' '); + } + // 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_; +}; + +} // 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::full_formatter>(details::padding_info{})); +} + +SPDLOG_INLINE std::unique_ptr<formatter> pattern_formatter::clone() const +{ + custom_flags cloned_custom_formatters; + for (auto &it : custom_handlers_) + { + cloned_custom_formatters[it.first] = it.second->clone(); + } + return details::make_unique<pattern_formatter>(pattern_, pattern_time_type_, eol_, std::move(cloned_custom_formatters)); +} + +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<std::chrono::seconds>(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 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<typename Padder> +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<details::full_formatter>(padding)); + need_localtime_ = true; + break; + + case 'n': // logger name + formatters_.push_back(details::make_unique<details::name_formatter<Padder>>(padding)); + break; + + case 'l': // level + formatters_.push_back(details::make_unique<details::level_formatter<Padder>>(padding)); + break; + + case 'L': // short level + formatters_.push_back(details::make_unique<details::short_level_formatter<Padder>>(padding)); + break; + + case ('t'): // thread id + formatters_.push_back(details::make_unique<details::t_formatter<Padder>>(padding)); + break; + + case ('v'): // the message text + formatters_.push_back(details::make_unique<details::v_formatter<Padder>>(padding)); + break; + + case ('a'): // weekday + formatters_.push_back(details::make_unique<details::a_formatter<Padder>>(padding)); + need_localtime_ = true; + break; + + case ('A'): // short weekday + formatters_.push_back(details::make_unique<details::A_formatter<Padder>>(padding)); + need_localtime_ = true; + break; + + case ('b'): + case ('h'): // month + formatters_.push_back(details::make_unique<details::b_formatter<Padder>>(padding)); + need_localtime_ = true; + break; + + case ('B'): // short month + formatters_.push_back(details::make_unique<details::B_formatter<Padder>>(padding)); + need_localtime_ = true; + break; + + case ('c'): // datetime + formatters_.push_back(details::make_unique<details::c_formatter<Padder>>(padding)); + need_localtime_ = true; + break; + + case ('C'): // year 2 digits + formatters_.push_back(details::make_unique<details::C_formatter<Padder>>(padding)); + need_localtime_ = true; + break; + + case ('Y'): // year 4 digits + formatters_.push_back(details::make_unique<details::Y_formatter<Padder>>(padding)); + need_localtime_ = true; + break; + + case ('D'): + case ('x'): // datetime MM/DD/YY + formatters_.push_back(details::make_unique<details::D_formatter<Padder>>(padding)); + need_localtime_ = true; + break; + + case ('m'): // month 1-12 + formatters_.push_back(details::make_unique<details::m_formatter<Padder>>(padding)); + need_localtime_ = true; + break; + + case ('d'): // day of month 1-31 + formatters_.push_back(details::make_unique<details::d_formatter<Padder>>(padding)); + need_localtime_ = true; + break; + + case ('H'): // hours 24 + formatters_.push_back(details::make_unique<details::H_formatter<Padder>>(padding)); + need_localtime_ = true; + break; + + case ('I'): // hours 12 + formatters_.push_back(details::make_unique<details::I_formatter<Padder>>(padding)); + need_localtime_ = true; + break; + + case ('M'): // minutes + formatters_.push_back(details::make_unique<details::M_formatter<Padder>>(padding)); + need_localtime_ = true; + break; + + case ('S'): // seconds + formatters_.push_back(details::make_unique<details::S_formatter<Padder>>(padding)); + need_localtime_ = true; + break; + + case ('e'): // milliseconds + formatters_.push_back(details::make_unique<details::e_formatter<Padder>>(padding)); + break; + + case ('f'): // microseconds + formatters_.push_back(details::make_unique<details::f_formatter<Padder>>(padding)); + break; + + case ('F'): // nanoseconds + formatters_.push_back(details::make_unique<details::F_formatter<Padder>>(padding)); + break; + + case ('E'): // seconds since epoch + formatters_.push_back(details::make_unique<details::E_formatter<Padder>>(padding)); + break; + + case ('p'): // am/pm + formatters_.push_back(details::make_unique<details::p_formatter<Padder>>(padding)); + need_localtime_ = true; + break; + + case ('r'): // 12 hour clock 02:55:02 pm + formatters_.push_back(details::make_unique<details::r_formatter<Padder>>(padding)); + need_localtime_ = true; + break; + + case ('R'): // 24-hour HH:MM time + formatters_.push_back(details::make_unique<details::R_formatter<Padder>>(padding)); + need_localtime_ = true; + break; + + case ('T'): + case ('X'): // ISO 8601 time format (HH:MM:SS) + formatters_.push_back(details::make_unique<details::T_formatter<Padder>>(padding)); + need_localtime_ = true; + break; + + case ('z'): // timezone + formatters_.push_back(details::make_unique<details::z_formatter<Padder>>(padding)); + need_localtime_ = true; + break; + + case ('P'): // pid + formatters_.push_back(details::make_unique<details::pid_formatter<Padder>>(padding)); + break; + + case ('^'): // color range start + formatters_.push_back(details::make_unique<details::color_start_formatter>(padding)); + break; + + case ('$'): // color range end + formatters_.push_back(details::make_unique<details::color_stop_formatter>(padding)); + break; + + case ('@'): // source location (filename:filenumber) + formatters_.push_back(details::make_unique<details::source_location_formatter<Padder>>(padding)); + break; + + case ('s'): // short source filename - without directory name + formatters_.push_back(details::make_unique<details::short_filename_formatter<Padder>>(padding)); + break; + + case ('g'): // full source filename + formatters_.push_back(details::make_unique<details::source_filename_formatter<Padder>>(padding)); + break; + + case ('#'): // source line number + formatters_.push_back(details::make_unique<details::source_linenum_formatter<Padder>>(padding)); + break; + + case ('!'): // source funcname + formatters_.push_back(details::make_unique<details::source_funcname_formatter<Padder>>(padding)); + break; + + case ('%'): // % char + formatters_.push_back(details::make_unique<details::ch_formatter>('%')); + break; + + case ('u'): // elapsed time since last log message in nanos + formatters_.push_back(details::make_unique<details::elapsed_formatter<Padder, std::chrono::nanoseconds>>(padding)); + break; + + case ('i'): // elapsed time since last log message in micros + formatters_.push_back(details::make_unique<details::elapsed_formatter<Padder, std::chrono::microseconds>>(padding)); + break; + + case ('o'): // elapsed time since last log message in millis + formatters_.push_back(details::make_unique<details::elapsed_formatter<Padder, std::chrono::milliseconds>>(padding)); + break; + + case ('O'): // elapsed time since last log message in seconds + formatters_.push_back(details::make_unique<details::elapsed_formatter<Padder, std::chrono::seconds>>(padding)); + break; + + default: // Unknown flag appears as is + auto unknown_flag = details::make_unique<details::aggregate_formatter>(); + + 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<details::source_funcname_formatter<Padder>>(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<unsigned char>(*it))) + { + return padding_info{}; // no padding if no digit found here + } + + auto width = static_cast<size_t>(*it) - '0'; + for (++it; it != end && std::isdigit(static_cast<unsigned char>(*it)); ++it) + { + auto digit = static_cast<size_t>(*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<size_t>(width, max_width), side, truncate}; +} + +SPDLOG_INLINE void pattern_formatter::compile_pattern_(const std::string &pattern) +{ + auto end = pattern.end(); + std::unique_ptr<details::aggregate_formatter> 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_<details::scoped_padder>(*it, padding); + } + else + { + handle_flag_<details::null_scoped_padder>(*it, padding); + } + } + else + { + break; + } + } + else // chars not following the % sign should be displayed as is + { + if (!user_chars) + { + user_chars = details::make_unique<details::aggregate_formatter>(); + } + 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 0000000000000000000000000000000000000000..8bcf8e2ab9afa4f6a3ac9df61e133f52fb9238d5 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/spdlog/pattern_formatter.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 + +#include <spdlog/common.h> +#include <spdlog/details/log_msg.h> +#include <spdlog/details/os.h> +#include <spdlog/formatter.h> + +#include <chrono> +#include <ctime> +#include <memory> + +#include <string> +#include <vector> +#include <unordered_map> + +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<custom_flag_formatter> 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<char, std::unique_ptr<custom_flag_formatter>>; + + 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<formatter> clone() const override; + void format(const details::log_msg &msg, memory_buf_t &dest) override; + + template<typename T, typename... Args> + pattern_formatter &add_flag(char flag, Args &&... args) + { + custom_handlers_[flag] = details::make_unique<T>(std::forward<Args>(args)...); + return *this; + } + void set_pattern(std::string pattern); + +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<std::unique_ptr<details::flag_formatter>> formatters_; + custom_flags custom_handlers_; + + std::tm get_time_(const details::log_msg &msg); + template<typename Padder> + 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 0000000000000000000000000000000000000000..42935a7cb0d5183af1b116eed869b25a6d5bb73e --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/spdlog/sinks/android_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 + +#ifdef __ANDROID__ + +# include <spdlog/details/fmt_helper.h> +# include <spdlog/details/null_mutex.h> +# include <spdlog/details/os.h> +# include <spdlog/sinks/base_sink.h> +# include <spdlog/details/synchronous_factory.h> + +# include <android/log.h> +# include <chrono> +# include <mutex> +# include <string> +# include <thread> + +# if !defined(SPDLOG_ANDROID_RETRIES) +# define SPDLOG_ANDROID_RETRIES 2 +# endif + +namespace spdlog { +namespace sinks { + +/* + * Android sink (logging using __android_log_write) + */ +template<typename Mutex> +class android_sink final : public base_sink<Mutex> +{ +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<Mutex>::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_write(priority, tag_.c_str(), msg_output); + int retry_count = 0; + while ((ret == -11 /*EAGAIN*/) && (retry_count < SPDLOG_ANDROID_RETRIES)) + { + details::os::sleep_for_millis(5); + ret = __android_log_write(priority, tag_.c_str(), msg_output); + retry_count++; + } + + if (ret < 0) + { + throw_spdlog_ex("__android_log_write() failed", ret); + } + } + + void flush_() override {} + +private: + 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<std::mutex>; +using android_sink_st = android_sink<details::null_mutex>; +} // namespace sinks + +// Create and register android syslog logger + +template<typename Factory = spdlog::synchronous_factory> +inline std::shared_ptr<logger> android_logger_mt(const std::string &logger_name, const std::string &tag = "spdlog") +{ + return Factory::template create<sinks::android_sink_mt>(logger_name, tag); +} + +template<typename Factory = spdlog::synchronous_factory> +inline std::shared_ptr<logger> android_logger_st(const std::string &logger_name, const std::string &tag = "spdlog") +{ + return Factory::template create<sinks::android_sink_st>(logger_name, tag); +} + +} // namespace spdlog + +#endif // __ANDROID__ \ No newline at end of file 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 0000000000000000000000000000000000000000..b5848f2dbc39fb184640c7f29f09c5f29393da1a --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/spdlog/sinks/ansicolor_sink-inl.h @@ -0,0 +1,145 @@ +// 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 <spdlog/sinks/ansicolor_sink.h> +#endif + +#include <spdlog/pattern_formatter.h> +#include <spdlog/details/os.h> + +namespace spdlog { +namespace sinks { + +template<typename ConsoleMutex> +SPDLOG_INLINE ansicolor_sink<ConsoleMutex>::ansicolor_sink(FILE *target_file, color_mode mode) + : target_file_(target_file) + , mutex_(ConsoleMutex::mutex()) + , formatter_(details::make_unique<spdlog::pattern_formatter>()) + +{ + set_color_mode(mode); + colors_[level::trace] = to_string_(white); + colors_[level::debug] = to_string_(cyan); + colors_[level::info] = to_string_(green); + colors_[level::warn] = to_string_(yellow_bold); + colors_[level::err] = to_string_(red_bold); + colors_[level::critical] = to_string_(bold_on_red); + colors_[level::off] = to_string_(reset); +} + +template<typename ConsoleMutex> +SPDLOG_INLINE void ansicolor_sink<ConsoleMutex>::set_color(level::level_enum color_level, string_view_t color) +{ + std::lock_guard<mutex_t> lock(mutex_); + colors_[static_cast<size_t>(color_level)] = to_string_(color); +} + +template<typename ConsoleMutex> +SPDLOG_INLINE void ansicolor_sink<ConsoleMutex>::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<mutex_t> 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_[static_cast<size_t>(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<typename ConsoleMutex> +SPDLOG_INLINE void ansicolor_sink<ConsoleMutex>::flush() +{ + std::lock_guard<mutex_t> lock(mutex_); + fflush(target_file_); +} + +template<typename ConsoleMutex> +SPDLOG_INLINE void ansicolor_sink<ConsoleMutex>::set_pattern(const std::string &pattern) +{ + std::lock_guard<mutex_t> lock(mutex_); + formatter_ = std::unique_ptr<spdlog::formatter>(new pattern_formatter(pattern)); +} + +template<typename ConsoleMutex> +SPDLOG_INLINE void ansicolor_sink<ConsoleMutex>::set_formatter(std::unique_ptr<spdlog::formatter> sink_formatter) +{ + std::lock_guard<mutex_t> lock(mutex_); + formatter_ = std::move(sink_formatter); +} + +template<typename ConsoleMutex> +SPDLOG_INLINE bool ansicolor_sink<ConsoleMutex>::should_color() +{ + return should_do_colors_; +} + +template<typename ConsoleMutex> +SPDLOG_INLINE void ansicolor_sink<ConsoleMutex>::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<typename ConsoleMutex> +SPDLOG_INLINE void ansicolor_sink<ConsoleMutex>::print_ccode_(const string_view_t &color_code) +{ + fwrite(color_code.data(), sizeof(char), color_code.size(), target_file_); +} + +template<typename ConsoleMutex> +SPDLOG_INLINE void ansicolor_sink<ConsoleMutex>::print_range_(const memory_buf_t &formatted, size_t start, size_t end) +{ + fwrite(formatted.data() + start, sizeof(char), end - start, target_file_); +} + +template<typename ConsoleMutex> +SPDLOG_INLINE std::string ansicolor_sink<ConsoleMutex>::to_string_(const string_view_t &sv) +{ + return std::string(sv.data(), sv.size()); +} + +// ansicolor_stdout_sink +template<typename ConsoleMutex> +SPDLOG_INLINE ansicolor_stdout_sink<ConsoleMutex>::ansicolor_stdout_sink(color_mode mode) + : ansicolor_sink<ConsoleMutex>(stdout, mode) +{} + +// ansicolor_stderr_sink +template<typename ConsoleMutex> +SPDLOG_INLINE ansicolor_stderr_sink<ConsoleMutex>::ansicolor_stderr_sink(color_mode mode) + : ansicolor_sink<ConsoleMutex>(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 0000000000000000000000000000000000000000..39d966bc94f87c3f08cf6316d2f6b1c76064c7ea --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/spdlog/sinks/ansicolor_sink.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 <spdlog/details/console_globals.h> +#include <spdlog/details/null_mutex.h> +#include <spdlog/sinks/sink.h> +#include <memory> +#include <mutex> +#include <string> +#include <array> + +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<typename ConsoleMutex> +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; + void set_formatter(std::unique_ptr<spdlog::formatter> 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<spdlog::formatter> formatter_; + std::array<std::string, level::n_levels> 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<typename ConsoleMutex> +class ansicolor_stdout_sink : public ansicolor_sink<ConsoleMutex> +{ +public: + explicit ansicolor_stdout_sink(color_mode mode = color_mode::automatic); +}; + +template<typename ConsoleMutex> +class ansicolor_stderr_sink : public ansicolor_sink<ConsoleMutex> +{ +public: + explicit ansicolor_stderr_sink(color_mode mode = color_mode::automatic); +}; + +using ansicolor_stdout_sink_mt = ansicolor_stdout_sink<details::console_mutex>; +using ansicolor_stdout_sink_st = ansicolor_stdout_sink<details::console_nullmutex>; + +using ansicolor_stderr_sink_mt = ansicolor_stderr_sink<details::console_mutex>; +using ansicolor_stderr_sink_st = ansicolor_stderr_sink<details::console_nullmutex>; + +} // 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 0000000000000000000000000000000000000000..421fdf9dd2d79b745707d87343e9117b682b73b3 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/spdlog/sinks/base_sink-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 <spdlog/sinks/base_sink.h> +#endif + +#include <spdlog/common.h> +#include <spdlog/pattern_formatter.h> + +#include <memory> + +template<typename Mutex> +SPDLOG_INLINE spdlog::sinks::base_sink<Mutex>::base_sink() + : formatter_{details::make_unique<spdlog::pattern_formatter>()} +{} + +template<typename Mutex> +SPDLOG_INLINE spdlog::sinks::base_sink<Mutex>::base_sink(std::unique_ptr<spdlog::formatter> formatter) + : formatter_{std::move(formatter)} +{} + +template<typename Mutex> +void SPDLOG_INLINE spdlog::sinks::base_sink<Mutex>::log(const details::log_msg &msg) +{ + std::lock_guard<Mutex> lock(mutex_); + sink_it_(msg); +} + +template<typename Mutex> +void SPDLOG_INLINE spdlog::sinks::base_sink<Mutex>::flush() +{ + std::lock_guard<Mutex> lock(mutex_); + flush_(); +} + +template<typename Mutex> +void SPDLOG_INLINE spdlog::sinks::base_sink<Mutex>::set_pattern(const std::string &pattern) +{ + std::lock_guard<Mutex> lock(mutex_); + set_pattern_(pattern); +} + +template<typename Mutex> +void SPDLOG_INLINE spdlog::sinks::base_sink<Mutex>::set_formatter(std::unique_ptr<spdlog::formatter> sink_formatter) +{ + std::lock_guard<Mutex> lock(mutex_); + set_formatter_(std::move(sink_formatter)); +} + +template<typename Mutex> +void SPDLOG_INLINE spdlog::sinks::base_sink<Mutex>::set_pattern_(const std::string &pattern) +{ + set_formatter_(details::make_unique<spdlog::pattern_formatter>(pattern)); +} + +template<typename Mutex> +void SPDLOG_INLINE spdlog::sinks::base_sink<Mutex>::set_formatter_(std::unique_ptr<spdlog::formatter> 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 0000000000000000000000000000000000000000..2e795f592cbe471d4f71442df0796e475888d5eb --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/spdlog/sinks/base_sink.h @@ -0,0 +1,52 @@ +// 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 <spdlog/common.h> +#include <spdlog/details/log_msg.h> +#include <spdlog/sinks/sink.h> + +namespace spdlog { +namespace sinks { +template<typename Mutex> +class SPDLOG_API base_sink : public sink +{ +public: + base_sink(); + explicit base_sink(std::unique_ptr<spdlog::formatter> 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; + void flush() final; + void set_pattern(const std::string &pattern) final; + void set_formatter(std::unique_ptr<spdlog::formatter> sink_formatter) final; + +protected: + // sink formatter + std::unique_ptr<spdlog::formatter> 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<spdlog::formatter> 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 0000000000000000000000000000000000000000..8d23f96dfa6a8b801aa5db62b9c9d35f1d10e270 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/spdlog/sinks/basic_file_sink-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 <spdlog/sinks/basic_file_sink.h> +#endif + +#include <spdlog/common.h> +#include <spdlog/details/os.h> + +namespace spdlog { +namespace sinks { + +template<typename Mutex> +SPDLOG_INLINE basic_file_sink<Mutex>::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<typename Mutex> +SPDLOG_INLINE const filename_t &basic_file_sink<Mutex>::filename() const +{ + return file_helper_.filename(); +} + +template<typename Mutex> +SPDLOG_INLINE void basic_file_sink<Mutex>::sink_it_(const details::log_msg &msg) +{ + memory_buf_t formatted; + base_sink<Mutex>::formatter_->format(msg, formatted); + file_helper_.write(formatted); +} + +template<typename Mutex> +SPDLOG_INLINE void basic_file_sink<Mutex>::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 0000000000000000000000000000000000000000..aacc993bf60263a9385f26fcc75d6ef18cb20348 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/spdlog/sinks/basic_file_sink.h @@ -0,0 +1,60 @@ +// Copyright(c) 2015-present, Gabi Melman & spdlog contributors. +// Distributed under the MIT License (http://opensource.org/licenses/MIT) + +#pragma once + +#include <spdlog/details/file_helper.h> +#include <spdlog/details/null_mutex.h> +#include <spdlog/sinks/base_sink.h> +#include <spdlog/details/synchronous_factory.h> + +#include <mutex> +#include <string> + +namespace spdlog { +namespace sinks { +/* + * Trivial file sink with single file as target + */ +template<typename Mutex> +class basic_file_sink final : public base_sink<Mutex> +{ +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<std::mutex>; +using basic_file_sink_st = basic_file_sink<details::null_mutex>; + +} // namespace sinks + +// +// factory functions +// +template<typename Factory = spdlog::synchronous_factory> +inline std::shared_ptr<logger> 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<sinks::basic_file_sink_mt>(logger_name, filename, truncate, event_handlers); +} + +template<typename Factory = spdlog::synchronous_factory> +inline std::shared_ptr<logger> 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<sinks::basic_file_sink_st>(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/daily_file_sink.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/spdlog/sinks/daily_file_sink.h new file mode 100644 index 0000000000000000000000000000000000000000..bb566e187451659c46cecd5bd508b260d294fff9 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/spdlog/sinks/daily_file_sink.h @@ -0,0 +1,294 @@ +// Copyright(c) 2015-present, Gabi Melman & spdlog contributors. +// Distributed under the MIT License (http://opensource.org/licenses/MIT) + +#pragma once + +#include <spdlog/common.h> +#include <spdlog/details/file_helper.h> +#include <spdlog/details/null_mutex.h> +#include <spdlog/fmt/fmt.h> +#include <spdlog/fmt/chrono.h> +#include <spdlog/sinks/base_sink.h> +#include <spdlog/details/os.h> +#include <spdlog/details/circular_q.h> +#include <spdlog/details/synchronous_factory.h> + +#include <chrono> +#include <cstdio> +#include <ctime> +#include <mutex> +#include <string> + +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_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<spdlog::sinks::daily_file_format_sink_mt>("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 &filename, const tm &now_tm) + { +#ifdef SPDLOG_USE_STD_FORMAT + // adapted from fmtlib: https://github.com/fmtlib/fmt/blob/8.0.1/include/fmt/chrono.h#L522-L546 + + filename_t tm_format; + tm_format.append(filename); + // By appending an extra space we can distinguish an empty result that + // indicates insufficient buffer size from a guaranteed non-empty result + // https://github.com/fmtlib/fmt/issues/2238 + tm_format.push_back(' '); + + const size_t MIN_SIZE = 10; + filename_t buf; + buf.resize(MIN_SIZE); + for (;;) + { + size_t count = strftime(buf.data(), buf.size(), tm_format.c_str(), &now_tm); + if (count != 0) + { + // Remove the extra space. + buf.resize(count - 1); + break; + } + buf.resize(buf.size() * 2); + } + + return buf; +#else + // generate fmt datetime format string, e.g. {:%Y-%m-%d}. + filename_t fmt_filename = fmt::format(SPDLOG_FILENAME_T("{{:{}}}"), filename); +# if defined(_MSC_VER) && defined(SPDLOG_WCHAR_FILENAMES) // for some reason msvc doesn't allow fmt::runtime(..) with wchar here + return fmt::format(fmt_filename, now_tm); +# else + return fmt::format(SPDLOG_FMT_RUNTIME(fmt_filename), now_tm); +# endif +#endif + } + +private: +#if defined __GNUC__ +# pragma GCC diagnostic push +# pragma GCC diagnostic ignored "-Wformat-nonliteral" +#endif + + static size_t strftime(char *str, size_t count, const char *format, const std::tm *time) + { + return std::strftime(str, count, format, time); + } + + static size_t strftime(wchar_t *str, size_t count, const wchar_t *format, const std::tm *time) + { + return std::wcsftime(str, count, format, time); + } + +#if defined(__GNUC__) +# pragma GCC diagnostic pop +#endif +}; + +/* + * 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. + */ +template<typename Mutex, typename FileNameCalc = daily_filename_calculator> +class daily_file_sink final : public base_sink<Mutex> +{ +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<Mutex> lock(base_sink<Mutex>::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<Mutex>::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<filename_t>(static_cast<size_t>(max_files_)); + std::vector<filename_t> 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<filename_t> filenames_q_; +}; + +using daily_file_sink_mt = daily_file_sink<std::mutex>; +using daily_file_sink_st = daily_file_sink<details::null_mutex>; +using daily_file_format_sink_mt = daily_file_sink<std::mutex, daily_filename_format_calculator>; +using daily_file_format_sink_st = daily_file_sink<details::null_mutex, daily_filename_format_calculator>; + +} // namespace sinks + +// +// factory functions +// +template<typename Factory = spdlog::synchronous_factory> +inline std::shared_ptr<logger> 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<sinks::daily_file_sink_mt>(logger_name, filename, hour, minute, truncate, max_files, event_handlers); +} + +template<typename Factory = spdlog::synchronous_factory> +inline std::shared_ptr<logger> 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<sinks::daily_file_format_sink_mt>( + logger_name, filename, hour, minute, truncate, max_files, event_handlers); +} + +template<typename Factory = spdlog::synchronous_factory> +inline std::shared_ptr<logger> 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<sinks::daily_file_sink_st>(logger_name, filename, hour, minute, truncate, max_files, event_handlers); +} + +template<typename Factory = spdlog::synchronous_factory> +inline std::shared_ptr<logger> 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<sinks::daily_file_format_sink_st>( + 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 0000000000000000000000000000000000000000..8fccb4ee58314f2d8e5a8a4f2fdd8b915f87e1c3 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/spdlog/sinks/dist_sink.h @@ -0,0 +1,97 @@ +// 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 <spdlog/details/log_msg.h> +#include <spdlog/details/null_mutex.h> +#include <spdlog/pattern_formatter.h> + +#include <algorithm> +#include <memory> +#include <mutex> +#include <vector> + +// Distribution sink (mux). Stores a vector of sinks which get called when log +// is called + +namespace spdlog { +namespace sinks { + +template<typename Mutex> +class dist_sink : public base_sink<Mutex> +{ +public: + dist_sink() = default; + explicit dist_sink(std::vector<std::shared_ptr<sink>> sinks) + : sinks_(sinks) + {} + + dist_sink(const dist_sink &) = delete; + dist_sink &operator=(const dist_sink &) = delete; + + void add_sink(std::shared_ptr<sink> sink) + { + std::lock_guard<Mutex> lock(base_sink<Mutex>::mutex_); + sinks_.push_back(sink); + } + + void remove_sink(std::shared_ptr<sink> sink) + { + std::lock_guard<Mutex> lock(base_sink<Mutex>::mutex_); + sinks_.erase(std::remove(sinks_.begin(), sinks_.end(), sink), sinks_.end()); + } + + void set_sinks(std::vector<std::shared_ptr<sink>> sinks) + { + std::lock_guard<Mutex> lock(base_sink<Mutex>::mutex_); + sinks_ = std::move(sinks); + } + + std::vector<std::shared_ptr<sink>> &sinks() + { + return sinks_; + } + +protected: + void sink_it_(const details::log_msg &msg) override + { + for (auto &sink : sinks_) + { + if (sink->should_log(msg.level)) + { + sink->log(msg); + } + } + } + + void flush_() override + { + for (auto &sink : sinks_) + { + sink->flush(); + } + } + + void set_pattern_(const std::string &pattern) override + { + set_formatter_(details::make_unique<spdlog::pattern_formatter>(pattern)); + } + + void set_formatter_(std::unique_ptr<spdlog::formatter> sink_formatter) override + { + base_sink<Mutex>::formatter_ = std::move(sink_formatter); + for (auto &sink : sinks_) + { + sink->set_formatter(base_sink<Mutex>::formatter_->clone()); + } + } + std::vector<std::shared_ptr<sink>> sinks_; +}; + +using dist_sink_mt = dist_sink<std::mutex>; +using dist_sink_st = dist_sink<details::null_mutex>; + +} // 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 0000000000000000000000000000000000000000..282163ae46cc5a7ac8bd8572b8fbddb6facfbceb --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/spdlog/sinks/dup_filter_sink.h @@ -0,0 +1,94 @@ +// 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 <spdlog/details/null_mutex.h> +#include <spdlog/details/log_msg.h> + +#include <cstdio> +#include <mutex> +#include <string> +#include <chrono> + +// Duplicate message removal sink. +// Skip the message if previous one is identical and less than "max_skip_duration" have passed +// +// Example: +// +// #include <spdlog/sinks/dup_filter_sink.h> +// +// int main() { +// auto dup_filter = std::make_shared<dup_filter_sink_st>(std::chrono::seconds(5)); +// dup_filter->add_sink(std::make_shared<stdout_color_sink_mt>()); +// 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<typename Mutex> +class dup_filter_sink : public dist_sink<Mutex> +{ +public: + template<class Rep, class Period> + explicit dup_filter_sink(std::chrono::duration<Rep, Period> max_skip_duration) + : max_skip_duration_{max_skip_duration} + {} + +protected: + std::chrono::microseconds max_skip_duration_; + log_clock::time_point last_msg_time_; + std::string last_msg_payload_; + size_t skip_counter_ = 0; + + 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<unsigned>(skip_counter_)); + if (msg_size > 0 && static_cast<size_t>(msg_size) < sizeof(buf)) + { + details::log_msg skipped_msg{msg.logger_name, level::info, string_view_t{buf, static_cast<size_t>(msg_size)}}; + dist_sink<Mutex>::sink_it_(skipped_msg); + } + } + + // log current message + dist_sink<Mutex>::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<std::mutex>; +using dup_filter_sink_st = dup_filter_sink<details::null_mutex>; + +} // 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 0000000000000000000000000000000000000000..029e7b1db24e87218499cef064ee2912582b82c5 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/spdlog/sinks/hourly_file_sink.h @@ -0,0 +1,196 @@ +// Copyright(c) 2015-present, Gabi Melman & spdlog contributors. +// Distributed under the MIT License (http://opensource.org/licenses/MIT) + +#pragma once + +#include <spdlog/common.h> +#include <spdlog/details/file_helper.h> +#include <spdlog/details/null_mutex.h> +#include <spdlog/fmt/fmt.h> +#include <spdlog/sinks/base_sink.h> +#include <spdlog/details/os.h> +#include <spdlog/details/circular_q.h> +#include <spdlog/details/synchronous_factory.h> + +#include <chrono> +#include <cstdio> +#include <ctime> +#include <mutex> +#include <string> + +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. + */ +template<typename Mutex, typename FileNameCalc = hourly_filename_calculator> +class hourly_file_sink final : public base_sink<Mutex> +{ +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_); + rotation_tp_ = next_rotation_tp_(); + + if (max_files_ > 0) + { + init_filenames_q_(); + } + } + + filename_t filename() + { + std::lock_guard<Mutex> lock(base_sink<Mutex>::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<Mutex>::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<filename_t>(static_cast<size_t>(max_files_)); + std::vector<filename_t> 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<filename_t> filenames_q_; +}; + +using hourly_file_sink_mt = hourly_file_sink<std::mutex>; +using hourly_file_sink_st = hourly_file_sink<details::null_mutex>; + +} // namespace sinks + +// +// factory functions +// +template<typename Factory = spdlog::synchronous_factory> +inline std::shared_ptr<logger> 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<sinks::hourly_file_sink_mt>(logger_name, filename, truncate, max_files, event_handlers); +} + +template<typename Factory = spdlog::synchronous_factory> +inline std::shared_ptr<logger> 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<sinks::hourly_file_sink_st>(logger_name, filename, truncate, max_files, event_handlers); +} +} // 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 0000000000000000000000000000000000000000..34f4ee3378d8f0d2162956ab9215436bfe2b6ac6 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/spdlog/sinks/mongo_sink.h @@ -0,0 +1,99 @@ +// 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 <spdlog/details/synchronous_factory.h> + +#include <bsoncxx/builder/stream/document.hpp> +#include <bsoncxx/types.hpp> +#include <bsoncxx/view_or_value.hpp> + +#include <mongocxx/client.hpp> +#include <mongocxx/instance.hpp> +#include <mongocxx/uri.hpp> + +namespace spdlog { +namespace sinks { +template<typename Mutex> +class mongo_sink : public base_sink<Mutex> +{ +public: + mongo_sink(const std::string &db_name, const std::string &collection_name, const std::string &uri = "mongodb://localhost:27017") + { + try + { + client_ = spdlog::details::make_unique<mongocxx::client>(mongocxx::uri{uri}); + db_name_ = db_name; + coll_name_ = collection_name; + } + catch (const std::exception) + { + throw spdlog_ex("Error opening database"); + } + } + + ~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() + << "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<int>(msg.thread_id) << finalize; + client_->database(db_name_).collection(coll_name_).insert_one(doc.view()); + } + } + + void flush_() override {} + +private: + static mongocxx::instance instance_; + std::string db_name_; + std::string coll_name_; + std::unique_ptr<mongocxx::client> client_ = nullptr; +}; +template<> +mongocxx::instance mongo_sink<std::mutex>::instance_{}; + +#include "spdlog/details/null_mutex.h" +#include <mutex> +using mongo_sink_mt = mongo_sink<std::mutex>; +using mongo_sink_st = mongo_sink<spdlog::details::null_mutex>; + +} // namespace sinks + +template<typename Factory = spdlog::synchronous_factory> +inline std::shared_ptr<logger> 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<sinks::mongo_sink_mt>(logger_name, db_name, collection_name, uri); +} + +template<typename Factory = spdlog::synchronous_factory> +inline std::shared_ptr<logger> 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<sinks::mongo_sink_st>(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 0000000000000000000000000000000000000000..cf2516d74d54f8e14284a6077c46f12984b00d74 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/spdlog/sinks/msvc_sink.h @@ -0,0 +1,52 @@ +// Copyright(c) 2016 Alexander Dalshov. +// Distributed under the MIT License (http://opensource.org/licenses/MIT) + +#pragma once + +#if defined(_WIN32) + +# include <spdlog/details/null_mutex.h> +# include <spdlog/sinks/base_sink.h> + +# include <mutex> +# include <string> + +// Avoid including windows.h (https://stackoverflow.com/a/30741042) +extern "C" __declspec(dllimport) void __stdcall OutputDebugStringA(const char *lpOutputString); + +namespace spdlog { +namespace sinks { +/* + * MSVC sink (logging using OutputDebugStringA) + */ +template<typename Mutex> +class msvc_sink : public base_sink<Mutex> +{ +public: + msvc_sink() = default; + +protected: + void sink_it_(const details::log_msg &msg) override + { + memory_buf_t formatted; + base_sink<Mutex>::formatter_->format(msg, formatted); +# ifdef SPDLOG_USE_STD_FORMAT + OutputDebugStringA(formatted.c_str()); +# else + OutputDebugStringA(fmt::to_string(formatted).c_str()); +# endif + } + + void flush_() override {} +}; + +using msvc_sink_mt = msvc_sink<std::mutex>; +using msvc_sink_st = msvc_sink<details::null_mutex>; + +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 0000000000000000000000000000000000000000..eb8328014474a80c07eb5bac548bc5bbacaafbb2 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/spdlog/sinks/null_sink.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 + +#include <spdlog/details/null_mutex.h> +#include <spdlog/sinks/base_sink.h> +#include <spdlog/details/synchronous_factory.h> + +#include <mutex> + +namespace spdlog { +namespace sinks { + +template<typename Mutex> +class null_sink : public base_sink<Mutex> +{ +protected: + void sink_it_(const details::log_msg &) override {} + void flush_() override {} +}; + +using null_sink_mt = null_sink<details::null_mutex>; +using null_sink_st = null_sink<details::null_mutex>; + +} // namespace sinks + +template<typename Factory = spdlog::synchronous_factory> +inline std::shared_ptr<logger> null_logger_mt(const std::string &logger_name) +{ + auto null_logger = Factory::template create<sinks::null_sink_mt>(logger_name); + null_logger->set_level(level::off); + return null_logger; +} + +template<typename Factory = spdlog::synchronous_factory> +inline std::shared_ptr<logger> null_logger_st(const std::string &logger_name) +{ + auto null_logger = Factory::template create<sinks::null_sink_st>(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 0000000000000000000000000000000000000000..95c1e9620fdc825bf4faecaec07c38d496e14090 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/spdlog/sinks/ostream_sink.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 + +#include <spdlog/details/null_mutex.h> +#include <spdlog/sinks/base_sink.h> + +#include <mutex> +#include <ostream> + +namespace spdlog { +namespace sinks { +template<typename Mutex> +class ostream_sink final : public base_sink<Mutex> +{ +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<Mutex>::formatter_->format(msg, formatted); + ostream_.write(formatted.data(), static_cast<std::streamsize>(formatted.size())); + if (force_flush_) + { + ostream_.flush(); + } + } + + void flush_() override + { + ostream_.flush(); + } + + std::ostream &ostream_; + bool force_flush_; +}; + +using ostream_sink_mt = ostream_sink<std::mutex>; +using ostream_sink_st = ostream_sink<details::null_mutex>; + +} // 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 0000000000000000000000000000000000000000..31b49c609ac6604e684a005c01eb388fe4bec5b4 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/spdlog/sinks/qt_sinks.h @@ -0,0 +1,102 @@ +// 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 childs(QTextBrowser... +// etc) Building and using requires Qt library. +// + +#include "spdlog/common.h" +#include "spdlog/details/log_msg.h" +#include "spdlog/details/synchronous_factory.h" +#include "spdlog/sinks/base_sink.h" + +#include <QTextEdit> +#include <QPlainTextEdit> + +// +// qt_sink class +// +namespace spdlog { +namespace sinks { +template<typename Mutex> +class qt_sink : public base_sink<Mutex> +{ +public: + qt_sink(QObject *qt_object, const std::string &meta_method) + { + qt_object_ = qt_object; + meta_method_ = meta_method; + } + + ~qt_sink() + { + flush_(); + } + +protected: + void sink_it_(const details::log_msg &msg) override + { + memory_buf_t formatted; + base_sink<Mutex>::formatter_->format(msg, formatted); + 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<int>(str.size())).trimmed())); + } + + void flush_() override {} + +private: + QObject *qt_object_ = nullptr; + std::string meta_method_; +}; + +#include "spdlog/details/null_mutex.h" +#include <mutex> +using qt_sink_mt = qt_sink<std::mutex>; +using qt_sink_st = qt_sink<spdlog::details::null_mutex>; +} // namespace sinks + +// +// Factory functions +// +template<typename Factory = spdlog::synchronous_factory> +inline std::shared_ptr<logger> qt_logger_mt(const std::string &logger_name, QTextEdit *qt_object, const std::string &meta_method = "append") +{ + return Factory::template create<sinks::qt_sink_mt>(logger_name, qt_object, meta_method); +} + +template<typename Factory = spdlog::synchronous_factory> +inline std::shared_ptr<logger> qt_logger_st(const std::string &logger_name, QTextEdit *qt_object, const std::string &meta_method = "append") +{ + return Factory::template create<sinks::qt_sink_st>(logger_name, qt_object, meta_method); +} + +template<typename Factory = spdlog::synchronous_factory> +inline std::shared_ptr<logger> qt_logger_mt( + const std::string &logger_name, QPlainTextEdit *qt_object, const std::string &meta_method = "appendPlainText") +{ + return Factory::template create<sinks::qt_sink_mt>(logger_name, qt_object, meta_method); +} + +template<typename Factory = spdlog::synchronous_factory> +inline std::shared_ptr<logger> qt_logger_st( + const std::string &logger_name, QPlainTextEdit *qt_object, const std::string &meta_method = "appendPlainText") +{ + return Factory::template create<sinks::qt_sink_st>(logger_name, qt_object, meta_method); +} + +template<typename Factory = spdlog::synchronous_factory> +inline std::shared_ptr<logger> qt_logger_mt(const std::string &logger_name, QObject *qt_object, const std::string &meta_method) +{ + return Factory::template create<sinks::qt_sink_mt>(logger_name, qt_object, meta_method); +} + +template<typename Factory = spdlog::synchronous_factory> +inline std::shared_ptr<logger> qt_logger_st(const std::string &logger_name, QObject *qt_object, const std::string &meta_method) +{ + return Factory::template create<sinks::qt_sink_st>(logger_name, qt_object, meta_method); +} +} // 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 0000000000000000000000000000000000000000..5836d98b515d9a49d1143bce6695ead102615ab1 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/spdlog/sinks/ringbuffer_sink.h @@ -0,0 +1,78 @@ +// Copyright(c) 2015-present, Gabi Melman & spdlog contributors. +// Distributed under the MIT License (http://opensource.org/licenses/MIT) + +#pragma once + +#include "spdlog/sinks/base_sink.h" +#include "spdlog/details/circular_q.h" +#include "spdlog/details/log_msg_buffer.h" +#include "spdlog/details/null_mutex.h" + +#include <mutex> +#include <string> +#include <vector> + +namespace spdlog { +namespace sinks { +/* + * Ring buffer sink + */ +template<typename Mutex> +class ringbuffer_sink final : public base_sink<Mutex> +{ +public: + explicit ringbuffer_sink(size_t n_items) + : q_{n_items} + {} + + std::vector<details::log_msg_buffer> last_raw(size_t lim = 0) + { + std::lock_guard<Mutex> lock(base_sink<Mutex>::mutex_); + auto items_available = q_.size(); + auto n_items = lim > 0 ? (std::min)(lim, items_available) : items_available; + std::vector<details::log_msg_buffer> 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<std::string> last_formatted(size_t lim = 0) + { + std::lock_guard<Mutex> lock(base_sink<Mutex>::mutex_); + auto items_available = q_.size(); + auto n_items = lim > 0 ? (std::min)(lim, items_available) : items_available; + std::vector<std::string> ret; + ret.reserve(n_items); + for (size_t i = (items_available - n_items); i < items_available; i++) + { + memory_buf_t formatted; + base_sink<Mutex>::formatter_->format(q_.at(i), formatted); +#ifdef SPDLOG_USE_STD_FORMAT + ret.push_back(std::move(formatted)); +#else + ret.push_back(fmt::to_string(formatted)); +#endif + } + 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<details::log_msg_buffer> q_; +}; + +using ringbuffer_sink_mt = ringbuffer_sink<std::mutex>; +using ringbuffer_sink_st = ringbuffer_sink<details::null_mutex>; + +} // 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 0000000000000000000000000000000000000000..cf8b9d5c64889fc9d7f7a28da6bb84b431122829 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/spdlog/sinks/rotating_file_sink-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 <spdlog/sinks/rotating_file_sink.h> +#endif + +#include <spdlog/common.h> + +#include <spdlog/details/file_helper.h> +#include <spdlog/details/null_mutex.h> +#include <spdlog/fmt/fmt.h> + +#include <cerrno> +#include <chrono> +#include <ctime> +#include <mutex> +#include <string> +#include <tuple> + +namespace spdlog { +namespace sinks { + +template<typename Mutex> +SPDLOG_INLINE rotating_file_sink<Mutex>::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<typename Mutex> +SPDLOG_INLINE filename_t rotating_file_sink<Mutex>::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_FILENAME_T("{}.{}{}"), basename, index, ext); +} + +template<typename Mutex> +SPDLOG_INLINE filename_t rotating_file_sink<Mutex>::filename() +{ + std::lock_guard<Mutex> lock(base_sink<Mutex>::mutex_); + return file_helper_.filename(); +} + +template<typename Mutex> +SPDLOG_INLINE void rotating_file_sink<Mutex>::sink_it_(const details::log_msg &msg) +{ + memory_buf_t formatted; + base_sink<Mutex>::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<typename Mutex> +SPDLOG_INLINE void rotating_file_sink<Mutex>::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<typename Mutex> +SPDLOG_INLINE void rotating_file_sink<Mutex>::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<typename Mutex> +SPDLOG_INLINE bool rotating_file_sink<Mutex>::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 0000000000000000000000000000000000000000..ce0d7b1efb4a95035cf266cacb5869d3c4a387a7 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/spdlog/sinks/rotating_file_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 <spdlog/sinks/base_sink.h> +#include <spdlog/details/file_helper.h> +#include <spdlog/details/null_mutex.h> +#include <spdlog/details/synchronous_factory.h> + +#include <chrono> +#include <mutex> +#include <string> + +namespace spdlog { +namespace sinks { + +// +// Rotating file sink based on size +// +template<typename Mutex> +class rotating_file_sink final : public base_sink<Mutex> +{ +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<std::mutex>; +using rotating_file_sink_st = rotating_file_sink<details::null_mutex>; + +} // namespace sinks + +// +// factory functions +// + +template<typename Factory = spdlog::synchronous_factory> +inline std::shared_ptr<logger> 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<sinks::rotating_file_sink_mt>( + logger_name, filename, max_file_size, max_files, rotate_on_open, event_handlers); +} + +template<typename Factory = spdlog::synchronous_factory> +inline std::shared_ptr<logger> 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<sinks::rotating_file_sink_st>( + 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 0000000000000000000000000000000000000000..df07adda4c41a181fa4c7f1aecfe632ee9d99228 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/spdlog/sinks/sink-inl.h @@ -0,0 +1,25 @@ +// 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 <spdlog/sinks/sink.h> +#endif + +#include <spdlog/common.h> + +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<spdlog::level::level_enum>(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 0000000000000000000000000000000000000000..0a28cccc734c12382a1648b16c093c5f962075da --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/spdlog/sinks/sink.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 <spdlog/details/log_msg.h> +#include <spdlog/formatter.h> + +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<spdlog::formatter> 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 0000000000000000000000000000000000000000..066df1826d7fe0701ed6c4e5230cfd0e7918f33c --- /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 <spdlog/sinks/stdout_color_sinks.h> +#endif + +#include <spdlog/logger.h> +#include <spdlog/common.h> + +namespace spdlog { + +template<typename Factory> +SPDLOG_INLINE std::shared_ptr<logger> stdout_color_mt(const std::string &logger_name, color_mode mode) +{ + return Factory::template create<sinks::stdout_color_sink_mt>(logger_name, mode); +} + +template<typename Factory> +SPDLOG_INLINE std::shared_ptr<logger> stdout_color_st(const std::string &logger_name, color_mode mode) +{ + return Factory::template create<sinks::stdout_color_sink_st>(logger_name, mode); +} + +template<typename Factory> +SPDLOG_INLINE std::shared_ptr<logger> stderr_color_mt(const std::string &logger_name, color_mode mode) +{ + return Factory::template create<sinks::stderr_color_sink_mt>(logger_name, mode); +} + +template<typename Factory> +SPDLOG_INLINE std::shared_ptr<logger> stderr_color_st(const std::string &logger_name, color_mode mode) +{ + return Factory::template create<sinks::stderr_color_sink_st>(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 0000000000000000000000000000000000000000..420b13ab40f10c8bbb74832b35a5dbae552bf98b --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/spdlog/sinks/stdout_color_sinks.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 + +#ifdef _WIN32 +# include <spdlog/sinks/wincolor_sink.h> +#else +# include <spdlog/sinks/ansicolor_sink.h> +#endif + +#include <spdlog/details/synchronous_factory.h> + +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<typename Factory = spdlog::synchronous_factory> +std::shared_ptr<logger> stdout_color_mt(const std::string &logger_name, color_mode mode = color_mode::automatic); + +template<typename Factory = spdlog::synchronous_factory> +std::shared_ptr<logger> stdout_color_st(const std::string &logger_name, color_mode mode = color_mode::automatic); + +template<typename Factory = spdlog::synchronous_factory> +std::shared_ptr<logger> stderr_color_mt(const std::string &logger_name, color_mode mode = color_mode::automatic); + +template<typename Factory = spdlog::synchronous_factory> +std::shared_ptr<logger> 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 0000000000000000000000000000000000000000..756734bf67b76a5edc41c718a249172f8ae3b662 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/spdlog/sinks/stdout_sinks-inl.h @@ -0,0 +1,139 @@ +// 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 <spdlog/sinks/stdout_sinks.h> +#endif + +#include <spdlog/details/console_globals.h> +#include <spdlog/pattern_formatter.h> +#include <memory> + +#ifdef _WIN32 +// under windows using fwrite to non-binary stream results in \r\r\n (see issue #1675) +// so instead we use ::FileWrite +# include <spdlog/details/windows_include.h> + +# ifndef _USING_V110_SDK71_ // fileapi.h doesn't exist in winxp +# include <fileapi.h> // WriteFile (..) +# endif + +# include <io.h> // _get_osfhandle(..) +# include <stdio.h> // _fileno(..) +#endif // WIN32 + +namespace spdlog { + +namespace sinks { + +template<typename ConsoleMutex> +SPDLOG_INLINE stdout_sink_base<ConsoleMutex>::stdout_sink_base(FILE *file) + : mutex_(ConsoleMutex::mutex()) + , file_(file) + , formatter_(details::make_unique<spdlog::pattern_formatter>()) +{ +#ifdef _WIN32 + // get windows handle from the FILE* object + + handle_ = reinterpret_cast<HANDLE>(::_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<typename ConsoleMutex> +SPDLOG_INLINE void stdout_sink_base<ConsoleMutex>::log(const details::log_msg &msg) +{ +#ifdef _WIN32 + if (handle_ == INVALID_HANDLE_VALUE) + { + return; + } + std::lock_guard<mutex_t> lock(mutex_); + memory_buf_t formatted; + formatter_->format(msg, formatted); + ::fflush(file_); // flush in case there is something in this file_ already + auto size = static_cast<DWORD>(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<mutex_t> lock(mutex_); + memory_buf_t formatted; + formatter_->format(msg, formatted); + ::fwrite(formatted.data(), sizeof(char), formatted.size(), file_); + ::fflush(file_); // flush every line to terminal +#endif // WIN32 +} + +template<typename ConsoleMutex> +SPDLOG_INLINE void stdout_sink_base<ConsoleMutex>::flush() +{ + std::lock_guard<mutex_t> lock(mutex_); + fflush(file_); +} + +template<typename ConsoleMutex> +SPDLOG_INLINE void stdout_sink_base<ConsoleMutex>::set_pattern(const std::string &pattern) +{ + std::lock_guard<mutex_t> lock(mutex_); + formatter_ = std::unique_ptr<spdlog::formatter>(new pattern_formatter(pattern)); +} + +template<typename ConsoleMutex> +SPDLOG_INLINE void stdout_sink_base<ConsoleMutex>::set_formatter(std::unique_ptr<spdlog::formatter> sink_formatter) +{ + std::lock_guard<mutex_t> lock(mutex_); + formatter_ = std::move(sink_formatter); +} + +// stdout sink +template<typename ConsoleMutex> +SPDLOG_INLINE stdout_sink<ConsoleMutex>::stdout_sink() + : stdout_sink_base<ConsoleMutex>(stdout) +{} + +// stderr sink +template<typename ConsoleMutex> +SPDLOG_INLINE stderr_sink<ConsoleMutex>::stderr_sink() + : stdout_sink_base<ConsoleMutex>(stderr) +{} + +} // namespace sinks + +// factory methods +template<typename Factory> +SPDLOG_INLINE std::shared_ptr<logger> stdout_logger_mt(const std::string &logger_name) +{ + return Factory::template create<sinks::stdout_sink_mt>(logger_name); +} + +template<typename Factory> +SPDLOG_INLINE std::shared_ptr<logger> stdout_logger_st(const std::string &logger_name) +{ + return Factory::template create<sinks::stdout_sink_st>(logger_name); +} + +template<typename Factory> +SPDLOG_INLINE std::shared_ptr<logger> stderr_logger_mt(const std::string &logger_name) +{ + return Factory::template create<sinks::stderr_sink_mt>(logger_name); +} + +template<typename Factory> +SPDLOG_INLINE std::shared_ptr<logger> stderr_logger_st(const std::string &logger_name) +{ + return Factory::template create<sinks::stderr_sink_st>(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 0000000000000000000000000000000000000000..6fdc0de34d976fbee624ff59747b83f1282a2053 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/spdlog/sinks/stdout_sinks.h @@ -0,0 +1,87 @@ +// Copyright(c) 2015-present, Gabi Melman & spdlog contributors. +// Distributed under the MIT License (http://opensource.org/licenses/MIT) + +#pragma once + +#include <spdlog/details/console_globals.h> +#include <spdlog/details/synchronous_factory.h> +#include <spdlog/sinks/sink.h> +#include <cstdio> + +#ifdef _WIN32 +# include <spdlog/details/windows_include.h> +#endif + +namespace spdlog { + +namespace sinks { + +template<typename ConsoleMutex> +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<spdlog::formatter> sink_formatter) override; + +protected: + mutex_t &mutex_; + FILE *file_; + std::unique_ptr<spdlog::formatter> formatter_; +#ifdef _WIN32 + HANDLE handle_; +#endif // WIN32 +}; + +template<typename ConsoleMutex> +class stdout_sink : public stdout_sink_base<ConsoleMutex> +{ +public: + stdout_sink(); +}; + +template<typename ConsoleMutex> +class stderr_sink : public stdout_sink_base<ConsoleMutex> +{ +public: + stderr_sink(); +}; + +using stdout_sink_mt = stdout_sink<details::console_mutex>; +using stdout_sink_st = stdout_sink<details::console_nullmutex>; + +using stderr_sink_mt = stderr_sink<details::console_mutex>; +using stderr_sink_st = stderr_sink<details::console_nullmutex>; + +} // namespace sinks + +// factory methods +template<typename Factory = spdlog::synchronous_factory> +std::shared_ptr<logger> stdout_logger_mt(const std::string &logger_name); + +template<typename Factory = spdlog::synchronous_factory> +std::shared_ptr<logger> stdout_logger_st(const std::string &logger_name); + +template<typename Factory = spdlog::synchronous_factory> +std::shared_ptr<logger> stderr_logger_mt(const std::string &logger_name); + +template<typename Factory = spdlog::synchronous_factory> +std::shared_ptr<logger> 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 0000000000000000000000000000000000000000..7c38fcb58ce2b62e940028f9432a0984cb1782c8 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/spdlog/sinks/syslog_sink.h @@ -0,0 +1,109 @@ +// Copyright(c) 2015-present, Gabi Melman & spdlog contributors. +// Distributed under the MIT License (http://opensource.org/licenses/MIT) + +#pragma once + +#include <spdlog/sinks/base_sink.h> +#include <spdlog/details/null_mutex.h> +#include <spdlog/details/synchronous_factory.h> + +#include <array> +#include <string> +#include <syslog.h> + +namespace spdlog { +namespace sinks { +/** + * Sink that write to syslog using the `syscall()` library call. + */ +template<typename Mutex> +class syslog_sink : public base_sink<Mutex> +{ + +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<Mutex>::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<size_t>(std::numeric_limits<int>::max())) + { + length = static_cast<size_t>(std::numeric_limits<int>::max()); + } + + ::syslog(syslog_prio_from_level(msg), "%.*s", static_cast<int>(length), payload.data()); + } + + void flush_() override {} + bool enable_formatting_ = false; + +private: + using levels_array = std::array<int, 7>; + levels_array syslog_levels_; + // must store the ident because the man says openlog might use the pointer as + // is and not a string copy + const std::string ident_; + + // + // Simply maps spdlog's log level to syslog priority level. + // + int syslog_prio_from_level(const details::log_msg &msg) const + { + return syslog_levels_.at(static_cast<levels_array::size_type>(msg.level)); + } +}; + +using syslog_sink_mt = syslog_sink<std::mutex>; +using syslog_sink_st = syslog_sink<details::null_mutex>; +} // namespace sinks + +// Create and register a syslog logger +template<typename Factory = spdlog::synchronous_factory> +inline std::shared_ptr<logger> 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<sinks::syslog_sink_mt>(logger_name, syslog_ident, syslog_option, syslog_facility, enable_formatting); +} + +template<typename Factory = spdlog::synchronous_factory> +inline std::shared_ptr<logger> 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<sinks::syslog_sink_st>(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 0000000000000000000000000000000000000000..e1e97bffe0dcb4e8838580ff442b17aa002440dd --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/spdlog/sinks/systemd_sink.h @@ -0,0 +1,119 @@ +// Copyright(c) 2019 ZVYAGIN.Alexander@gmail.com +// Distributed under the MIT License (http://opensource.org/licenses/MIT) + +#pragma once + +#include <spdlog/sinks/base_sink.h> +#include <spdlog/details/null_mutex.h> +#include <spdlog/details/synchronous_factory.h> + +#include <array> +#ifndef SD_JOURNAL_SUPPRESS_LOCATION +# define SD_JOURNAL_SUPPRESS_LOCATION +#endif +#include <systemd/sd-journal.h> + +namespace spdlog { +namespace sinks { + +/** + * Sink that write to systemd journal using the `sd_journal_send()` library call. + */ +template<typename Mutex> +class systemd_sink : public base_sink<Mutex> +{ +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<int, 7>; + 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<Mutex>::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<size_t>(std::numeric_limits<int>::max())) + { + length = static_cast<size_t>(std::numeric_limits<int>::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<int>(length), payload.data(), "PRIORITY=%d", syslog_level(msg.level), + "SYSLOG_IDENTIFIER=%.*s", static_cast<int>(syslog_identifier.size()), syslog_identifier.data(), nullptr); + } + else + { + err = (sd_journal_send)("MESSAGE=%.*s", static_cast<int>(length), payload.data(), "PRIORITY=%d", syslog_level(msg.level), + "SYSLOG_IDENTIFIER=%.*s", static_cast<int>(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<levels_array::size_type>(l)); + } + + void flush_() override {} +}; + +using systemd_sink_mt = systemd_sink<std::mutex>; +using systemd_sink_st = systemd_sink<details::null_mutex>; +} // namespace sinks + +// Create and register a syslog logger +template<typename Factory = spdlog::synchronous_factory> +inline std::shared_ptr<logger> systemd_logger_mt( + const std::string &logger_name, const std::string &ident = "", bool enable_formatting = false) +{ + return Factory::template create<sinks::systemd_sink_mt>(logger_name, ident, enable_formatting); +} + +template<typename Factory = spdlog::synchronous_factory> +inline std::shared_ptr<logger> systemd_logger_st( + const std::string &logger_name, const std::string &ident = "", bool enable_formatting = false) +{ + return Factory::template create<sinks::systemd_sink_st>(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 0000000000000000000000000000000000000000..e0efb31d93c6a278b979a41a221991a479521de2 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/spdlog/sinks/tcp_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 <spdlog/common.h> +#include <spdlog/sinks/base_sink.h> +#include <spdlog/details/null_mutex.h> +#ifdef _WIN32 +# include <spdlog/details/tcp_client-windows.h> +#else +# include <spdlog/details/tcp_client.h> +#endif + +#include <mutex> +#include <string> +#include <chrono> +#include <functional> + +#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<typename Mutex> +class tcp_sink : public spdlog::sinks::base_sink<Mutex> +{ +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<Mutex>::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<std::mutex>; +using tcp_sink_st = tcp_sink<spdlog::details::null_mutex>; + +} // 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 0000000000000000000000000000000000000000..ccbce2be3f2c034fa277f0c6ae959893d3b47f59 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/spdlog/sinks/udp_sink.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 + +#include <spdlog/common.h> +#include <spdlog/sinks/base_sink.h> +#include <spdlog/details/null_mutex.h> +#ifdef _WIN32 +# include <spdlog/details/udp_client-windows.h> +#else +# include <spdlog/details/udp_client.h> +#endif + +#include <mutex> +#include <string> +#include <chrono> +#include <functional> + +// 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<typename Mutex> +class udp_sink : public spdlog::sinks::base_sink<Mutex> +{ +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<Mutex>::formatter_->format(msg, formatted); + client_.send(formatted.data(), formatted.size()); + } + + void flush_() override {} + details::udp_client client_; +}; + +using udp_sink_mt = udp_sink<std::mutex>; +using udp_sink_st = udp_sink<spdlog::details::null_mutex>; + +} // namespace sinks + +// +// factory functions +// +template<typename Factory = spdlog::synchronous_factory> +inline std::shared_ptr<logger> udp_logger_mt(const std::string &logger_name, sinks::udp_sink_config skin_config) +{ + return Factory::template create<sinks::udp_sink_mt>(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 0000000000000000000000000000000000000000..8a978a09176b5c4b7e65a2175e29136c0dae7bd3 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/spdlog/sinks/win_eventlog_sink.h @@ -0,0 +1,289 @@ +// 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. <log_name> should be replaced with your log name (e.g. your application name) +// 2. <source_name> 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\<log_name>] + +[HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\EventLog\<log_name>\<source_name>] +"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 <spdlog/details/null_mutex.h> +#include <spdlog/sinks/base_sink.h> + +#include <spdlog/details/windows_include.h> +#include <winbase.h> + +#include <mutex> +#include <string> +#include <vector> + +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<char> 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<unsigned char> buffer(static_cast<size_t>(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<typename Mutex> +class win_eventlog_sink : public base_sink<Mutex> +{ +private: + HANDLE hEventLog_{NULL}; + internal::sid_t current_user_sid_; + std::string source_; + WORD 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<Mutex>::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 = ::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 = ::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, WORD 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<std::mutex>; +using win_eventlog_sink_st = win_eventlog::win_eventlog_sink<details::null_mutex>; + +} // 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 0000000000000000000000000000000000000000..be3d80a20a7c3d09767b1375fe33a157bc7433fe --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/spdlog/sinks/wincolor_sink-inl.h @@ -0,0 +1,175 @@ +// 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 <spdlog/sinks/wincolor_sink.h> +#endif + +#include <spdlog/details/windows_include.h> +#include <wincon.h> + +#include <spdlog/common.h> +#include <spdlog/pattern_formatter.h> + +namespace spdlog { +namespace sinks { +template<typename ConsoleMutex> +SPDLOG_INLINE wincolor_sink<ConsoleMutex>::wincolor_sink(void *out_handle, color_mode mode) + : out_handle_(out_handle) + , mutex_(ConsoleMutex::mutex()) + , formatter_(details::make_unique<spdlog::pattern_formatter>()) +{ + + 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<typename ConsoleMutex> +SPDLOG_INLINE wincolor_sink<ConsoleMutex>::~wincolor_sink() +{ + this->flush(); +} + +// change the color for the given level +template<typename ConsoleMutex> +void SPDLOG_INLINE wincolor_sink<ConsoleMutex>::set_color(level::level_enum level, std::uint16_t color) +{ + std::lock_guard<mutex_t> lock(mutex_); + colors_[level] = color; +} + +template<typename ConsoleMutex> +void SPDLOG_INLINE wincolor_sink<ConsoleMutex>::log(const details::log_msg &msg) +{ + if (out_handle_ == nullptr || out_handle_ == INVALID_HANDLE_VALUE) + { + return; + } + + std::lock_guard<mutex_t> 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<WORD>(set_foreground_color_(colors_[msg.level])); + print_range_(formatted, msg.color_range_start, msg.color_range_end); + // reset to orig colors + ::SetConsoleTextAttribute(static_cast<HANDLE>(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<typename ConsoleMutex> +void SPDLOG_INLINE wincolor_sink<ConsoleMutex>::flush() +{ + // windows console always flushed? +} + +template<typename ConsoleMutex> +void SPDLOG_INLINE wincolor_sink<ConsoleMutex>::set_pattern(const std::string &pattern) +{ + std::lock_guard<mutex_t> lock(mutex_); + formatter_ = std::unique_ptr<spdlog::formatter>(new pattern_formatter(pattern)); +} + +template<typename ConsoleMutex> +void SPDLOG_INLINE wincolor_sink<ConsoleMutex>::set_formatter(std::unique_ptr<spdlog::formatter> sink_formatter) +{ + std::lock_guard<mutex_t> lock(mutex_); + formatter_ = std::move(sink_formatter); +} + +template<typename ConsoleMutex> +void SPDLOG_INLINE wincolor_sink<ConsoleMutex>::set_color_mode(color_mode mode) +{ + std::lock_guard<mutex_t> lock(mutex_); + set_color_mode_impl(mode); +} + +template<typename ConsoleMutex> +void SPDLOG_INLINE wincolor_sink<ConsoleMutex>::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<HANDLE>(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<typename ConsoleMutex> +std::uint16_t SPDLOG_INLINE wincolor_sink<ConsoleMutex>::set_foreground_color_(std::uint16_t attribs) +{ + CONSOLE_SCREEN_BUFFER_INFO orig_buffer_info; + if (!::GetConsoleScreenBufferInfo(static_cast<HANDLE>(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<WORD>(attribs) | (orig_buffer_info.wAttributes & 0xfff0); + auto ignored = ::SetConsoleTextAttribute(static_cast<HANDLE>(out_handle_), static_cast<WORD>(new_attribs)); + (void)(ignored); + return static_cast<std::uint16_t>(orig_buffer_info.wAttributes); // return orig attribs +} + +// print a range of formatted message to console +template<typename ConsoleMutex> +void SPDLOG_INLINE wincolor_sink<ConsoleMutex>::print_range_(const memory_buf_t &formatted, size_t start, size_t end) +{ + if (end > start) + { + auto size = static_cast<DWORD>(end - start); + auto ignored = ::WriteConsoleA(static_cast<HANDLE>(out_handle_), formatted.data() + start, size, nullptr, nullptr); + (void)(ignored); + } +} + +template<typename ConsoleMutex> +void SPDLOG_INLINE wincolor_sink<ConsoleMutex>::write_to_file_(const memory_buf_t &formatted) +{ + auto size = static_cast<DWORD>(formatted.size()); + DWORD bytes_written = 0; + auto ignored = ::WriteFile(static_cast<HANDLE>(out_handle_), formatted.data(), size, &bytes_written, nullptr); + (void)(ignored); +} + +// wincolor_stdout_sink +template<typename ConsoleMutex> +SPDLOG_INLINE wincolor_stdout_sink<ConsoleMutex>::wincolor_stdout_sink(color_mode mode) + : wincolor_sink<ConsoleMutex>(::GetStdHandle(STD_OUTPUT_HANDLE), mode) +{} + +// wincolor_stderr_sink +template<typename ConsoleMutex> +SPDLOG_INLINE wincolor_stderr_sink<ConsoleMutex>::wincolor_stderr_sink(color_mode mode) + : wincolor_sink<ConsoleMutex>(::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 0000000000000000000000000000000000000000..9b030fc13ac73a690cfa0b7d5b80ef16c46d990b --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/spdlog/sinks/wincolor_sink.h @@ -0,0 +1,85 @@ +// Copyright(c) 2015-present, Gabi Melman & spdlog contributors. +// Distributed under the MIT License (http://opensource.org/licenses/MIT) + +#pragma once + +#include <spdlog/common.h> +#include <spdlog/details/console_globals.h> +#include <spdlog/details/null_mutex.h> +#include <spdlog/sinks/sink.h> + +#include <memory> +#include <mutex> +#include <string> +#include <array> +#include <cstdint> + +namespace spdlog { +namespace sinks { +/* + * Windows color console sink. Uses WriteConsoleA to write to the console with + * colors + */ +template<typename ConsoleMutex> +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<spdlog::formatter> 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<spdlog::formatter> formatter_; + std::array<std::uint16_t, level::n_levels> 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<typename ConsoleMutex> +class wincolor_stdout_sink : public wincolor_sink<ConsoleMutex> +{ +public: + explicit wincolor_stdout_sink(color_mode mode = color_mode::automatic); +}; + +template<typename ConsoleMutex> +class wincolor_stderr_sink : public wincolor_sink<ConsoleMutex> +{ +public: + explicit wincolor_stderr_sink(color_mode mode = color_mode::automatic); +}; + +using wincolor_stdout_sink_mt = wincolor_stdout_sink<details::console_mutex>; +using wincolor_stdout_sink_st = wincolor_stdout_sink<details::console_nullmutex>; + +using wincolor_stderr_sink_mt = wincolor_stderr_sink<details::console_mutex>; +using wincolor_stderr_sink_st = wincolor_stderr_sink<details::console_nullmutex>; +} // 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 0000000000000000000000000000000000000000..2b875fae9a4ba48afe56048d018d4c6c7e70ff74 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/spdlog/spdlog-inl.h @@ -0,0 +1,125 @@ +// 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 <spdlog/spdlog.h> +#endif + +#include <spdlog/common.h> +#include <spdlog/pattern_formatter.h> + +namespace spdlog { + +SPDLOG_INLINE void initialize_logger(std::shared_ptr<logger> logger) +{ + details::registry::instance().initialize_logger(std::move(logger)); +} + +SPDLOG_INLINE std::shared_ptr<logger> get(const std::string &name) +{ + return details::registry::instance().get(name); +} + +SPDLOG_INLINE void set_formatter(std::unique_ptr<spdlog::formatter> 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<spdlog::formatter>(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 flush_every(std::chrono::seconds interval) +{ + details::registry::instance().flush_every(interval); +} + +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> logger) +{ + details::registry::instance().register_logger(std::move(logger)); +} + +SPDLOG_INLINE void apply_all(const std::function<void(std::shared_ptr<logger>)> &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<spdlog::logger> 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<spdlog::logger> default_logger) +{ + details::registry::instance().set_default_logger(std::move(default_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 0000000000000000000000000000000000000000..65d3e9d59f33126ad8ec9ee84f6322b595e4902b --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/spdlog/spdlog.h @@ -0,0 +1,345 @@ +// 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 <spdlog/common.h> +#include <spdlog/details/registry.h> +#include <spdlog/logger.h> +#include <spdlog/version.h> +#include <spdlog/details/synchronous_factory.h> + +#include <chrono> +#include <functional> +#include <memory> +#include <string> + +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<daily_file_sink_st>("logger_name", "dailylog_filename", 11, 59); +template<typename Sink, typename... SinkArgs> +inline std::shared_ptr<spdlog::logger> create(std::string logger_name, SinkArgs &&... sink_args) +{ + return default_factory::create<Sink>(std::move(logger_name), std::forward<SinkArgs>(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<spdlog::logger>("mylogger", ...); +// spdlog::initialize_logger(mylogger); +SPDLOG_API void initialize_logger(std::shared_ptr<logger> 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<logger> 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<spdlog::formatter> 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! +SPDLOG_API void flush_every(std::chrono::seconds 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> logger); + +// Apply a user defined function on all registered loggers +// Example: +// spdlog::apply_all([&](std::shared_ptr<spdlog::logger> l) {l->flush();}); +SPDLOG_API void apply_all(const std::function<void(std::shared_ptr<logger>)> &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<spdlog::logger> default_logger(); + +SPDLOG_API spdlog::logger *default_logger_raw(); + +SPDLOG_API void set_default_logger(std::shared_ptr<spdlog::logger> default_logger); + +template<typename... Args> +inline void log(source_loc source, level::level_enum lvl, format_string_t<Args...> fmt, Args &&... args) +{ + default_logger_raw()->log(source, lvl, fmt, std::forward<Args>(args)...); +} + +template<typename... Args> +inline void log(level::level_enum lvl, format_string_t<Args...> fmt, Args &&... args) +{ + default_logger_raw()->log(source_loc{}, lvl, fmt, std::forward<Args>(args)...); +} + +template<typename... Args> +inline void trace(format_string_t<Args...> fmt, Args &&... args) +{ + default_logger_raw()->trace(fmt, std::forward<Args>(args)...); +} + +template<typename... Args> +inline void debug(format_string_t<Args...> fmt, Args &&... args) +{ + default_logger_raw()->debug(fmt, std::forward<Args>(args)...); +} + +template<typename... Args> +inline void info(format_string_t<Args...> fmt, Args &&... args) +{ + default_logger_raw()->info(fmt, std::forward<Args>(args)...); +} + +template<typename... Args> +inline void warn(format_string_t<Args...> fmt, Args &&... args) +{ + default_logger_raw()->warn(fmt, std::forward<Args>(args)...); +} + +template<typename... Args> +inline void error(format_string_t<Args...> fmt, Args &&... args) +{ + default_logger_raw()->error(fmt, std::forward<Args>(args)...); +} + +template<typename... Args> +inline void critical(format_string_t<Args...> fmt, Args &&... args) +{ + default_logger_raw()->critical(fmt, std::forward<Args>(args)...); +} + +template<typename T> +inline void log(source_loc source, level::level_enum lvl, const T &msg) +{ + default_logger_raw()->log(source, lvl, msg); +} + +template<typename T> +inline void log(level::level_enum lvl, const T &msg) +{ + default_logger_raw()->log(lvl, msg); +} + +#ifdef SPDLOG_WCHAR_TO_UTF8_SUPPORT +template<typename... Args> +inline void log(source_loc source, level::level_enum lvl, wformat_string_t<Args...> fmt, Args &&... args) +{ + default_logger_raw()->log(source, lvl, fmt, std::forward<Args>(args)...); +} + +template<typename... Args> +inline void log(level::level_enum lvl, wformat_string_t<Args...> fmt, Args &&... args) +{ + default_logger_raw()->log(source_loc{}, lvl, fmt, std::forward<Args>(args)...); +} + +template<typename... Args> +inline void trace(wformat_string_t<Args...> fmt, Args &&... args) +{ + default_logger_raw()->trace(fmt, std::forward<Args>(args)...); +} + +template<typename... Args> +inline void debug(wformat_string_t<Args...> fmt, Args &&... args) +{ + default_logger_raw()->debug(fmt, std::forward<Args>(args)...); +} + +template<typename... Args> +inline void info(wformat_string_t<Args...> fmt, Args &&... args) +{ + default_logger_raw()->info(fmt, std::forward<Args>(args)...); +} + +template<typename... Args> +inline void warn(wformat_string_t<Args...> fmt, Args &&... args) +{ + default_logger_raw()->warn(fmt, std::forward<Args>(args)...); +} + +template<typename... Args> +inline void error(wformat_string_t<Args...> fmt, Args &&... args) +{ + default_logger_raw()->error(fmt, std::forward<Args>(args)...); +} + +template<typename... Args> +inline void critical(wformat_string_t<Args...> fmt, Args &&... args) +{ + default_logger_raw()->critical(fmt, std::forward<Args>(args)...); +} +#endif + +template<typename T> +inline void trace(const T &msg) +{ + default_logger_raw()->trace(msg); +} + +template<typename T> +inline void debug(const T &msg) +{ + default_logger_raw()->debug(msg); +} + +template<typename T> +inline void info(const T &msg) +{ + default_logger_raw()->info(msg); +} + +template<typename T> +inline void warn(const T &msg) +{ + default_logger_raw()->warn(msg); +} + +template<typename T> +inline void error(const T &msg) +{ + default_logger_raw()->error(msg); +} + +template<typename T> +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 +// + +#define SPDLOG_LOGGER_CALL(logger, level, ...) (logger)->log(spdlog::source_loc{__FILE__, __LINE__, SPDLOG_FUNCTION}, level, __VA_ARGS__) + +#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 0000000000000000000000000000000000000000..4e62259be21ce4692bef15e34291acf86eb98831 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/spdlog/stopwatch.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 + +#include <spdlog/fmt/fmt.h> + +// 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 <spdlog/fmt/chrono.h> +//.. +// using std::chrono::duration_cast; +// using std::chrono::milliseconds; +// spdlog::info("Elapsed {}", duration_cast<milliseconds>(sw.elapsed())); => "Elapsed 5ms" + +namespace spdlog { +class stopwatch +{ + using clock = std::chrono::steady_clock; + std::chrono::time_point<clock> start_tp_; + +public: + stopwatch() + : start_tp_{clock::now()} + {} + + std::chrono::duration<double> elapsed() const + { + return std::chrono::duration<double>(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<spdlog::stopwatch> : formatter<double> +{ + template<typename FormatContext> + auto format(const spdlog::stopwatch &sw, FormatContext &ctx) -> decltype(ctx.out()) + { + return formatter<double>::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 0000000000000000000000000000000000000000..8fa60e4ceddc520458518d0de8909d106b0f4275 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/spdlog/tweakme.h @@ -0,0 +1,134 @@ +// 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 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 <fmt/format.h> so set your -I flag +// accordingly. +// +// #define SPDLOG_FMT_EXTERNAL +/////////////////////////////////////////////////////////////////////////////// + +/////////////////////////////////////////////////////////////////////////////// +// Uncomment to use C++20 std::format instead of fmt. This removes compile +// time checking of format strings, but doesn't depend on the fmt library. +// +// #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 0000000000000000000000000000000000000000..732eb06a02e00678543ad226c8b8fc36a84d91cc --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/spdlog/version.h @@ -0,0 +1,10 @@ +// 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 10 +#define SPDLOG_VER_PATCH 0 + +#define SPDLOG_VERSION (SPDLOG_VER_MAJOR * 10000 + SPDLOG_VER_MINOR * 100 + SPDLOG_VER_PATCH) diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/include/stb_image_resize.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/stb_image_resize.h new file mode 100644 index 0000000000000000000000000000000000000000..ef9e6fe87049f96b8bf9cc1f63fce03effa6c899 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/stb_image_resize.h @@ -0,0 +1,2634 @@ +/* stb_image_resize - v0.97 - public domain image resizing + by Jorge L Rodriguez (@VinoBS) - 2014 + http://github.com/nothings/stb + + Written with emphasis on usability, portability, and efficiency. (No + SIMD or threads, so it be easily outperformed by libs that use those.) + Only scaling and translation is supported, no rotations or shears. + Easy API downsamples w/Mitchell filter, upsamples w/cubic interpolation. + + 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. + + QUICKSTART + stbir_resize_uint8( input_pixels , in_w , in_h , 0, + output_pixels, out_w, out_h, 0, num_channels) + stbir_resize_float(...) + stbir_resize_uint8_srgb( input_pixels , in_w , in_h , 0, + output_pixels, out_w, out_h, 0, + num_channels , alpha_chan , 0) + stbir_resize_uint8_srgb_edgemode( + input_pixels , in_w , in_h , 0, + output_pixels, out_w, out_h, 0, + num_channels , alpha_chan , 0, STBIR_EDGE_CLAMP) + // WRAP/REFLECT/ZERO + + FULL API + See the "header file" section of the source for API documentation. + + ADDITIONAL DOCUMENTATION + + SRGB & FLOATING POINT REPRESENTATION + The sRGB functions presume IEEE floating point. If you do not have + IEEE floating point, define STBIR_NON_IEEE_FLOAT. This will use + a slower implementation. + + MEMORY ALLOCATION + The resize functions here perform a single memory allocation using + malloc. To control the memory allocation, before the #include that + triggers the implementation, do: + + #define STBIR_MALLOC(size,context) ... + #define STBIR_FREE(ptr,context) ... + + Each resize function makes exactly one call to malloc/free, so to use + temp memory, store the temp memory in the context and return that. + + ASSERT + Define STBIR_ASSERT(boolval) to override assert() and not use assert.h + + OPTIMIZATION + Define STBIR_SATURATE_INT to compute clamp values in-range using + integer operations instead of float operations. This may be faster + on some platforms. + + 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 used. For a list of + supported filters see the stbir_filter enum. To add a new filter, + write a filter function and add it to stbir__filter_info_table. + + PROGRESS + For interactive use with slow resize operations, you can install + a progress-report callback: + + #define STBIR_PROGRESS_REPORT(val) some_func(val) + + The parameter val is a float which goes from 0 to 1 as progress is made. + + For example: + + static void my_progress_report(float progress); + #define STBIR_PROGRESS_REPORT(val) my_progress_report(val) + + #define STB_IMAGE_RESIZE_IMPLEMENTATION + #include "stb_image_resize.h" + + static void my_progress_report(float progress) + { + printf("Progress: %f%%\n", progress*100); + } + + MAX CHANNELS + If your image has more than 64 channels, define STBIR_MAX_CHANNELS + to the max you'll have. + + ALPHA CHANNEL + Most of the resizing functions provide the ability to control how + the alpha channel of an image is processed. The important things + to know about this: + + 1. The best mathematically-behaved version of alpha to use is + called "premultiplied alpha", in which the other color channels + have had the alpha value multiplied in. If you use premultiplied + alpha, linear filtering (such as image resampling done by this + library, or performed in texture units on GPUs) does the "right + thing". While premultiplied alpha is standard in the movie CGI + industry, it is still uncommon in the videogame/real-time world. + + If you linearly filter non-premultiplied alpha, strange effects + occur. (For example, the 50/50 average of 99% transparent bright green + and 1% transparent black produces 50% transparent dark green when + non-premultiplied, whereas premultiplied it produces 50% + transparent near-black. The former introduces green energy + that doesn't exist in the source image.) + + 2. Artists should not edit premultiplied-alpha images; artists + want non-premultiplied alpha images. Thus, art tools generally output + non-premultiplied alpha images. + + 3. You will get best results in most cases by converting images + to premultiplied alpha before processing them mathematically. + + 4. If you pass the flag STBIR_FLAG_ALPHA_PREMULTIPLIED, the + resizer does not do anything special for the alpha channel; + it is resampled identically to other channels. This produces + the correct results for premultiplied-alpha images, but produces + less-than-ideal results for non-premultiplied-alpha images. + + 5. If you do not pass the flag STBIR_FLAG_ALPHA_PREMULTIPLIED, + then the resizer weights the contribution of input pixels + based on their alpha values, or, equivalently, it multiplies + the alpha value into the color channels, resamples, then divides + by the resultant alpha value. Input pixels which have alpha=0 do + not contribute at all to output pixels unless _all_ of the input + pixels affecting that output pixel have alpha=0, in which case + the result for that pixel is the same as it would be without + STBIR_FLAG_ALPHA_PREMULTIPLIED. However, this is only true for + input images in integer formats. For input images in float format, + input pixels with alpha=0 have no effect, and output pixels + which have alpha=0 will be 0 in all channels. (For float images, + you can manually achieve the same result by adding a tiny epsilon + value to the alpha channel of every image, and then subtracting + or clamping it at the end.) + + 6. You can suppress the behavior described in #5 and make + all-0-alpha pixels have 0 in all channels by #defining + STBIR_NO_ALPHA_EPSILON. + + 7. You can separately control whether the alpha channel is + interpreted as linear or affected by the colorspace. By default + it is linear; you almost never want to apply the colorspace. + (For example, graphics hardware does not apply sRGB conversion + to the alpha channel.) + + CONTRIBUTORS + Jorge L Rodriguez: Implementation + Sean Barrett: API design, optimizations + Aras Pranckevicius: bugfix + Nathan Reed: warning fixes + + REVISIONS + 0.97 (2020-02-02) fixed warning + 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. + + TODO + Don't decode all of the image data when only processing a partial tile + Don't use full-width decode buffers when only processing a partial tile + When processing wide images, break processing into tiles so data fits in L1 cache + Installable filters? + Resize that respects alpha test coverage + (Reference code: FloatImage::alphaTestCoverage and FloatImage::scaleAlphaToCoverage: + https://code.google.com/p/nvidia-texture-tools/source/browse/trunk/src/nvimage/FloatImage.cpp ) +*/ + +#ifndef STBIR_INCLUDE_STB_IMAGE_RESIZE_H +#define STBIR_INCLUDE_STB_IMAGE_RESIZE_H + +#ifdef _MSC_VER +typedef unsigned char stbir_uint8; +typedef unsigned short stbir_uint16; +typedef unsigned int stbir_uint32; +#else +#include <stdint.h> +typedef uint8_t stbir_uint8; +typedef uint16_t stbir_uint16; +typedef uint32_t stbir_uint32; +#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 + +////////////////////////////////////////////////////////////////////////////// +// +// Easy-to-use API: +// +// * "input pixels" points to an array of image data with 'num_channels' channels (e.g. RGB=3, RGBA=4) +// * input_w is input image width (x-axis), input_h is input image height (y-axis) +// * stride is the offset between successive rows of image data in memory, in bytes. you can +// specify 0 to mean packed continuously in memory +// * alpha channel is treated identically to other channels. +// * colorspace is linear or sRGB as specified by function name +// * returned result is 1 for success or 0 in case of an error. +// #define STBIR_ASSERT() to trigger an assert on parameter validation errors. +// * Memory required grows approximately linearly with input and output size, but with +// discontinuities at input_w == output_w and input_h == output_h. +// * These functions use a "default" resampling filter defined at compile time. To change the filter, +// you can change the compile-time defaults by #defining STBIR_DEFAULT_FILTER_UPSAMPLE +// and STBIR_DEFAULT_FILTER_DOWNSAMPLE, or you can use the medium-complexity API. + +STBIRDEF int stbir_resize_uint8( 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, + int num_channels); + +STBIRDEF int stbir_resize_float( 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, + int num_channels); + + +// The following functions interpret image data as gamma-corrected sRGB. +// Specify STBIR_ALPHA_CHANNEL_NONE if you have no alpha channel, +// or otherwise provide the index of the alpha channel. Flags value +// of 0 will probably do the right thing if you're not sure what +// the flags mean. + +#define STBIR_ALPHA_CHANNEL_NONE -1 + +// Set this flag if your texture has premultiplied alpha. Otherwise, stbir will +// use alpha-weighted resampling (effectively premultiplying, resampling, +// then unpremultiplying). +#define STBIR_FLAG_ALPHA_PREMULTIPLIED (1 << 0) +// The specified alpha channel should be handled as gamma-corrected value even +// when doing sRGB operations. +#define STBIR_FLAG_ALPHA_USES_COLORSPACE (1 << 1) + +STBIRDEF int 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, + int num_channels, int alpha_channel, int flags); + + +typedef enum +{ + STBIR_EDGE_CLAMP = 1, + STBIR_EDGE_REFLECT = 2, + STBIR_EDGE_WRAP = 3, + STBIR_EDGE_ZERO = 4, +} stbir_edge; + +// This function adds the ability to specify how requests to sample off the edge of the image are handled. +STBIRDEF int stbir_resize_uint8_srgb_edgemode(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, + int num_channels, int alpha_channel, int flags, + stbir_edge edge_wrap_mode); + +////////////////////////////////////////////////////////////////////////////// +// +// Medium-complexity API +// +// This extends the easy-to-use API as follows: +// +// * Alpha-channel can be processed separately +// * If alpha_channel is not STBIR_ALPHA_CHANNEL_NONE +// * Alpha channel will not be gamma corrected (unless flags&STBIR_FLAG_GAMMA_CORRECT) +// * Filters will be weighted by alpha channel (unless flags&STBIR_FLAG_ALPHA_PREMULTIPLIED) +// * Filter can be selected explicitly +// * uint16 image type +// * sRGB colorspace available for all types +// * context parameter for passing to STBIR_MALLOC + +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; + +typedef enum +{ + STBIR_COLORSPACE_LINEAR, + STBIR_COLORSPACE_SRGB, + + STBIR_MAX_COLORSPACES, +} stbir_colorspace; + +// The following functions are all identical except for the type of the image data + +STBIRDEF int stbir_resize_uint8_generic( 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, + int num_channels, int alpha_channel, int flags, + stbir_edge edge_wrap_mode, stbir_filter filter, stbir_colorspace space, + void *alloc_context); + +STBIRDEF int stbir_resize_uint16_generic(const stbir_uint16 *input_pixels , int input_w , int input_h , int input_stride_in_bytes, + stbir_uint16 *output_pixels , int output_w, int output_h, int output_stride_in_bytes, + int num_channels, int alpha_channel, int flags, + stbir_edge edge_wrap_mode, stbir_filter filter, stbir_colorspace space, + void *alloc_context); + +STBIRDEF int stbir_resize_float_generic( 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, + int num_channels, int alpha_channel, int flags, + stbir_edge edge_wrap_mode, stbir_filter filter, stbir_colorspace space, + void *alloc_context); + + + +////////////////////////////////////////////////////////////////////////////// +// +// Full-complexity API +// +// This extends the medium API as follows: +// +// * uint32 image type +// * not typesafe +// * separate filter types for each axis +// * separate edge modes for each axis +// * can specify scale explicitly for subpixel correctness +// * can specify image source tile using texture coordinates + +typedef enum +{ + STBIR_TYPE_UINT8 , + STBIR_TYPE_UINT16, + STBIR_TYPE_UINT32, + STBIR_TYPE_FLOAT , + + STBIR_MAX_TYPES +} stbir_datatype; + +STBIRDEF int 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_datatype datatype, + int num_channels, int alpha_channel, int flags, + stbir_edge edge_mode_horizontal, stbir_edge edge_mode_vertical, + stbir_filter filter_horizontal, stbir_filter filter_vertical, + stbir_colorspace space, void *alloc_context); + +STBIRDEF int stbir_resize_subpixel(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_datatype datatype, + int num_channels, int alpha_channel, int flags, + stbir_edge edge_mode_horizontal, stbir_edge edge_mode_vertical, + stbir_filter filter_horizontal, stbir_filter filter_vertical, + stbir_colorspace space, void *alloc_context, + float x_scale, float y_scale, + float x_offset, float y_offset); + +STBIRDEF int stbir_resize_region( 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_datatype datatype, + int num_channels, int alpha_channel, int flags, + stbir_edge edge_mode_horizontal, stbir_edge edge_mode_vertical, + stbir_filter filter_horizontal, stbir_filter filter_vertical, + stbir_colorspace space, void *alloc_context, + float s0, float t0, float s1, float t1); +// (s0, t0) & (s1, t1) are the top-left and bottom right corner (uv addressing style: [0, 1]x[0, 1]) of a region of the input image to use. + +// +// +//// end header file ///////////////////////////////////////////////////// +#endif // STBIR_INCLUDE_STB_IMAGE_RESIZE_H + + + + + +#ifdef STB_IMAGE_RESIZE_IMPLEMENTATION + +#ifndef STBIR_ASSERT +#include <assert.h> +#define STBIR_ASSERT(x) assert(x) +#endif + +// For memset +#include <string.h> + +#include <math.h> + +#ifndef STBIR_MALLOC +#include <stdlib.h> +// use comma operator to evaluate c, to avoid "unused parameter" warnings +#define STBIR_MALLOC(size,c) ((void)(c), malloc(size)) +#define STBIR_FREE(ptr,c) ((void)(c), free(ptr)) +#endif + +#ifndef _MSC_VER +#ifdef __cplusplus +#define stbir__inline inline +#else +#define stbir__inline +#endif +#else +#define stbir__inline __forceinline +#endif + + +// should produce compiler error if size is wrong +typedef unsigned char stbir__validate_uint32[sizeof(stbir_uint32) == 4 ? 1 : -1]; + +#ifdef _MSC_VER +#define STBIR__NOTUSED(v) (void)(v) +#else +#define STBIR__NOTUSED(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_PROGRESS_REPORT +#define STBIR_PROGRESS_REPORT(float_0_to_1) +#endif + +#ifndef STBIR_MAX_CHANNELS +#define STBIR_MAX_CHANNELS 64 +#endif + +#if STBIR_MAX_CHANNELS > 65536 +#error "Too many channels; STBIR_MAX_CHANNELS must be no more than 65536." +// because we store the indices in 16-bit variables +#endif + +// This value is added to alpha just before premultiplication to avoid +// zeroing out color values. It is equivalent to 2^-80. If you don't want +// that behavior (it may interfere if you have floating point images with +// very small alpha values) then you can define STBIR_NO_ALPHA_EPSILON to +// disable it. +#ifndef STBIR_ALPHA_EPSILON +#define STBIR_ALPHA_EPSILON ((float)1 / (1 << 20) / (1 << 20) / (1 << 20) / (1 << 20)) +#endif + + + +#ifdef _MSC_VER +#define STBIR__UNUSED_PARAM(v) (void)(v) +#else +#define STBIR__UNUSED_PARAM(v) (void)sizeof(v) +#endif + +// must match stbir_datatype +static unsigned char stbir__type_size[] = { + 1, // STBIR_TYPE_UINT8 + 2, // STBIR_TYPE_UINT16 + 4, // STBIR_TYPE_UINT32 + 4, // STBIR_TYPE_FLOAT +}; + +// Kernel function centered at 0 +typedef float (stbir__kernel_fn)(float x, float scale); +typedef float (stbir__support_fn)(float scale); + +typedef struct +{ + stbir__kernel_fn* kernel; + stbir__support_fn* support; +} stbir__filter_info; + +// When upsampling, the contributors are which source pixels contribute. +// When downsampling, 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 +{ + const void* input_data; + int input_w; + int input_h; + int input_stride_bytes; + + void* output_data; + int output_w; + int output_h; + int output_stride_bytes; + + float s0, t0, s1, t1; + + float horizontal_shift; // Units: output pixels + float vertical_shift; // Units: output pixels + float horizontal_scale; + float vertical_scale; + + int channels; + int alpha_channel; + stbir_uint32 flags; + stbir_datatype type; + stbir_filter horizontal_filter; + stbir_filter vertical_filter; + stbir_edge edge_horizontal; + stbir_edge edge_vertical; + stbir_colorspace colorspace; + + stbir__contributors* horizontal_contributors; + float* horizontal_coefficients; + + stbir__contributors* vertical_contributors; + float* vertical_coefficients; + + int decode_buffer_pixels; + float* decode_buffer; + + float* horizontal_buffer; + + // cache these because ceil/floor are inexplicably showing up in profile + int horizontal_coefficient_width; + int vertical_coefficient_width; + int horizontal_filter_pixel_width; + int vertical_filter_pixel_width; + int horizontal_filter_pixel_margin; + int vertical_filter_pixel_margin; + int horizontal_num_contributors; + int vertical_num_contributors; + + 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. + 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 + float* ring_buffer; + + float* encode_buffer; // A temporary buffer to store floats so we don't lose precision while we do multiply-adds. + + int horizontal_contributors_size; + int horizontal_coefficients_size; + int vertical_contributors_size; + int vertical_coefficients_size; + int decode_buffer_size; + int horizontal_buffer_size; + int ring_buffer_size; + int encode_buffer_size; +} stbir__info; + + +static const float stbir__max_uint8_as_float = 255.0f; +static const float stbir__max_uint16_as_float = 65535.0f; +static const double stbir__max_uint32_as_float = 4294967295.0; + + +static stbir__inline int stbir__min(int a, int b) +{ + return a < b ? a : b; +} + +static stbir__inline float stbir__saturate(float x) +{ + if (x < 0) + return 0; + + if (x > 1) + return 1; + + return x; +} + +#ifdef STBIR_SATURATE_INT +static stbir__inline stbir_uint8 stbir__saturate8(int x) +{ + if ((unsigned int) x <= 255) + return x; + + if (x < 0) + return 0; + + return 255; +} + +static stbir__inline stbir_uint16 stbir__saturate16(int x) +{ + if ((unsigned int) x <= 65535) + return x; + + if (x < 0) + return 0; + + return 65535; +} +#endif + +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 +}; + +static float stbir__srgb_to_linear(float f) +{ + if (f <= 0.04045f) + return f / 12.92f; + else + return (float)pow((f + 0.055f) / 1.055f, 2.4f); +} + +static float stbir__linear_to_srgb(float f) +{ + if (f <= 0.0031308f) + return f * 12.92f; + else + return 1.055f * (float)pow(f, 1 / 2.4f) - 0.055f; +} + +#ifndef STBIR_NON_IEEE_FLOAT +// From https://gist.github.com/rygorous/2203834 + +typedef union +{ + stbir_uint32 u; + float f; +} stbir__FP32; + +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_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 + in = minval.f; + if (in > almostone.f) + in = almostone.f; + + // 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); +} + +#else +// sRGB transition values, scaled by 1<<28 +static int stbir__srgb_offset_to_linear_scaled[256] = +{ + 0, 40738, 122216, 203693, 285170, 366648, 448125, 529603, + 611080, 692557, 774035, 855852, 942009, 1033024, 1128971, 1229926, + 1335959, 1447142, 1563542, 1685229, 1812268, 1944725, 2082664, 2226148, + 2375238, 2529996, 2690481, 2856753, 3028870, 3206888, 3390865, 3580856, + 3776916, 3979100, 4187460, 4402049, 4622919, 4850123, 5083710, 5323731, + 5570236, 5823273, 6082892, 6349140, 6622065, 6901714, 7188133, 7481369, + 7781466, 8088471, 8402427, 8723380, 9051372, 9386448, 9728650, 10078021, + 10434603, 10798439, 11169569, 11548036, 11933879, 12327139, 12727857, 13136073, + 13551826, 13975156, 14406100, 14844697, 15290987, 15745007, 16206795, 16676389, + 17153826, 17639142, 18132374, 18633560, 19142734, 19659934, 20185196, 20718552, + 21260042, 21809696, 22367554, 22933648, 23508010, 24090680, 24681686, 25281066, + 25888850, 26505076, 27129772, 27762974, 28404716, 29055026, 29713942, 30381490, + 31057708, 31742624, 32436272, 33138682, 33849884, 34569912, 35298800, 36036568, + 36783260, 37538896, 38303512, 39077136, 39859796, 40651528, 41452360, 42262316, + 43081432, 43909732, 44747252, 45594016, 46450052, 47315392, 48190064, 49074096, + 49967516, 50870356, 51782636, 52704392, 53635648, 54576432, 55526772, 56486700, + 57456236, 58435408, 59424248, 60422780, 61431036, 62449032, 63476804, 64514376, + 65561776, 66619028, 67686160, 68763192, 69850160, 70947088, 72053992, 73170912, + 74297864, 75434880, 76581976, 77739184, 78906536, 80084040, 81271736, 82469648, + 83677792, 84896192, 86124888, 87363888, 88613232, 89872928, 91143016, 92423512, + 93714432, 95015816, 96327688, 97650056, 98982952, 100326408, 101680440, 103045072, + 104420320, 105806224, 107202800, 108610064, 110028048, 111456776, 112896264, 114346544, + 115807632, 117279552, 118762328, 120255976, 121760536, 123276016, 124802440, 126339832, + 127888216, 129447616, 131018048, 132599544, 134192112, 135795792, 137410592, 139036528, + 140673648, 142321952, 143981456, 145652208, 147334208, 149027488, 150732064, 152447968, + 154175200, 155913792, 157663776, 159425168, 161197984, 162982240, 164777968, 166585184, + 168403904, 170234160, 172075968, 173929344, 175794320, 177670896, 179559120, 181458992, + 183370528, 185293776, 187228736, 189175424, 191133888, 193104112, 195086128, 197079968, + 199085648, 201103184, 203132592, 205173888, 207227120, 209292272, 211369392, 213458480, + 215559568, 217672656, 219797792, 221934976, 224084240, 226245600, 228419056, 230604656, + 232802400, 235012320, 237234432, 239468736, 241715280, 243974080, 246245120, 248528464, + 250824112, 253132064, 255452368, 257785040, 260130080, 262487520, 264857376, 267239664, +}; + +static stbir_uint8 stbir__linear_to_srgb_uchar(float f) +{ + int x = (int) (f * (1 << 28)); // has headroom so you don't need to clamp + int v = 0; + int i; + + // Refine the guess with a short binary search. + i = v + 128; if (x >= stbir__srgb_offset_to_linear_scaled[i]) v = i; + i = v + 64; if (x >= stbir__srgb_offset_to_linear_scaled[i]) v = i; + i = v + 32; if (x >= stbir__srgb_offset_to_linear_scaled[i]) v = i; + i = v + 16; if (x >= stbir__srgb_offset_to_linear_scaled[i]) v = i; + i = v + 8; if (x >= stbir__srgb_offset_to_linear_scaled[i]) v = i; + i = v + 4; if (x >= stbir__srgb_offset_to_linear_scaled[i]) v = i; + i = v + 2; if (x >= stbir__srgb_offset_to_linear_scaled[i]) v = i; + i = v + 1; if (x >= stbir__srgb_offset_to_linear_scaled[i]) v = i; + + return (stbir_uint8) v; +} +#endif + +static float stbir__filter_trapezoid(float x, float scale) +{ + float halfscale = scale / 2; + float t = 0.5f + halfscale; + STBIR_ASSERT(scale <= 1); + + x = (float)fabs(x); + + if (x >= t) + return 0; + else + { + float r = 0.5f - halfscale; + if (x <= r) + return 1; + else + return (t - x) / scale; + } +} + +static float stbir__support_trapezoid(float scale) +{ + STBIR_ASSERT(scale <= 1); + return 0.5f + scale / 2; +} + +static float stbir__filter_triangle(float x, float s) +{ + STBIR__UNUSED_PARAM(s); + + x = (float)fabs(x); + + if (x <= 1.0f) + return 1 - x; + else + return 0; +} + +static float stbir__filter_cubic(float x, float s) +{ + STBIR__UNUSED_PARAM(s); + + x = (float)fabs(x); + + if (x < 1.0f) + return (4 + x*x*(3*x - 6))/6; + else if (x < 2.0f) + return (8 + x*(-12 + x*(6 - x)))/6; + + return (0.0f); +} + +static float stbir__filter_catmullrom(float x, float s) +{ + STBIR__UNUSED_PARAM(s); + + x = (float)fabs(x); + + if (x < 1.0f) + return 1 - x*x*(2.5f - 1.5f*x); + else if (x < 2.0f) + return 2 - x*(4 + x*(0.5f*x - 2.5f)); + + return (0.0f); +} + +static float stbir__filter_mitchell(float x, float s) +{ + STBIR__UNUSED_PARAM(s); + + x = (float)fabs(x); + + if (x < 1.0f) + return (16 + x*x*(21 * x - 36))/18; + else if (x < 2.0f) + return (32 + x*(-60 + x*(36 - 7*x)))/18; + + return (0.0f); +} + +static float stbir__support_zero(float s) +{ + STBIR__UNUSED_PARAM(s); + return 0; +} + +static float stbir__support_one(float s) +{ + STBIR__UNUSED_PARAM(s); + return 1; +} + +static float stbir__support_two(float s) +{ + STBIR__UNUSED_PARAM(s); + return 2; +} + +static stbir__filter_info stbir__filter_info_table[] = { + { NULL, stbir__support_zero }, + { stbir__filter_trapezoid, stbir__support_trapezoid }, + { stbir__filter_triangle, stbir__support_one }, + { stbir__filter_cubic, stbir__support_two }, + { stbir__filter_catmullrom, stbir__support_two }, + { stbir__filter_mitchell, stbir__support_two }, +}; + +stbir__inline static int stbir__use_upsampling(float ratio) +{ + return ratio > 1; +} + +stbir__inline static int stbir__use_width_upsampling(stbir__info* stbir_info) +{ + return stbir__use_upsampling(stbir_info->horizontal_scale); +} + +stbir__inline static int stbir__use_height_upsampling(stbir__info* stbir_info) +{ + return stbir__use_upsampling(stbir_info->vertical_scale); +} + +// This is the maximum number of input samples that can affect an output sample +// with the given filter +static int stbir__get_filter_pixel_width(stbir_filter filter, float scale) +{ + STBIR_ASSERT(filter != 0); + STBIR_ASSERT(filter < STBIR__ARRAY_SIZE(stbir__filter_info_table)); + + if (stbir__use_upsampling(scale)) + return (int)ceil(stbir__filter_info_table[filter].support(1/scale) * 2); + else + return (int)ceil(stbir__filter_info_table[filter].support(scale) * 2 / scale); +} + +// This is how much to expand buffers to account for filters seeking outside +// the image boundaries. +static int stbir__get_filter_pixel_margin(stbir_filter filter, float scale) +{ + return stbir__get_filter_pixel_width(filter, scale) / 2; +} + +static int stbir__get_coefficient_width(stbir_filter filter, float scale) +{ + if (stbir__use_upsampling(scale)) + return (int)ceil(stbir__filter_info_table[filter].support(1 / scale) * 2); + else + return (int)ceil(stbir__filter_info_table[filter].support(scale) * 2); +} + +static int stbir__get_contributors(float scale, stbir_filter filter, int input_size, int output_size) +{ + if (stbir__use_upsampling(scale)) + return output_size; + else + return (input_size + stbir__get_filter_pixel_margin(filter, scale) * 2); +} + +static int stbir__get_total_horizontal_coefficients(stbir__info* info) +{ + return info->horizontal_num_contributors + * stbir__get_coefficient_width (info->horizontal_filter, info->horizontal_scale); +} + +static int stbir__get_total_vertical_coefficients(stbir__info* info) +{ + return info->vertical_num_contributors + * stbir__get_coefficient_width (info->vertical_filter, info->vertical_scale); +} + +static stbir__contributors* stbir__get_contributor(stbir__contributors* contributors, int n) +{ + return &contributors[n]; +} + +// For perf reasons this code is duplicated in stbir__resample_horizontal_upsample/downsample, +// if you change it here change it there too. +static float* stbir__get_coefficient(float* coefficients, stbir_filter filter, float scale, int n, int c) +{ + int width = stbir__get_coefficient_width(filter, scale); + return &coefficients[width*n + c]; +} + +static int stbir__edge_wrap_slow(stbir_edge edge, int n, int max) +{ + switch (edge) + { + case STBIR_EDGE_ZERO: + return 0; // we'll decode the wrong pixel here, and then overwrite with 0s later + + case STBIR_EDGE_CLAMP: + if (n < 0) + return 0; + + if (n >= max) + return max - 1; + + return n; // NOTREACHED + + case STBIR_EDGE_REFLECT: + { + 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 + } + + case STBIR_EDGE_WRAP: + if (n >= 0) + return (n % max); + else + { + int m = (-n) % max; + + if (m != 0) + m = max - m; + + return (m); + } + // NOTREACHED + + default: + STBIR_ASSERT(!"Unimplemented edge type"); + return 0; + } +} + +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); +} + +// What input pixels contribute to this output pixel? +static void stbir__calculate_sample_range_upsample(int n, float out_filter_radius, float scale_ratio, float out_shift, int* in_first_pixel, int* in_last_pixel, float* in_center_of_out) +{ + float out_pixel_center = (float)n + 0.5f; + 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) / scale_ratio; + float in_pixel_influence_upperbound = (out_pixel_influence_upperbound + out_shift) / scale_ratio; + + *in_center_of_out = (out_pixel_center + out_shift) / scale_ratio; + *in_first_pixel = (int)(floor(in_pixel_influence_lowerbound + 0.5)); + *in_last_pixel = (int)(floor(in_pixel_influence_upperbound - 0.5)); +} + +// What output pixels does this input pixel contribute to? +static void stbir__calculate_sample_range_downsample(int n, float in_pixels_radius, float scale_ratio, float out_shift, int* out_first_pixel, int* out_last_pixel, float* out_center_of_in) +{ + float in_pixel_center = (float)n + 0.5f; + 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_ratio - out_shift; + float out_pixel_influence_upperbound = in_pixel_influence_upperbound * scale_ratio - out_shift; + + *out_center_of_in = in_pixel_center * scale_ratio - out_shift; + *out_first_pixel = (int)(floor(out_pixel_influence_lowerbound + 0.5)); + *out_last_pixel = (int)(floor(out_pixel_influence_upperbound - 0.5)); +} + +static void stbir__calculate_coefficients_upsample(stbir_filter filter, float scale, int in_first_pixel, int in_last_pixel, float in_center_of_out, stbir__contributors* contributor, float* coefficient_group) +{ + int i; + float total_filter = 0; + float filter_scale; + + STBIR_ASSERT(in_last_pixel - in_first_pixel <= (int)ceil(stbir__filter_info_table[filter].support(1/scale) * 2)); // Taken directly from stbir__get_coefficient_width() which we can't call because we don't know if we're horizontal or vertical. + + contributor->n0 = in_first_pixel; + contributor->n1 = in_last_pixel; + + STBIR_ASSERT(contributor->n1 >= contributor->n0); + + for (i = 0; i <= in_last_pixel - in_first_pixel; i++) + { + float in_pixel_center = (float)(i + in_first_pixel) + 0.5f; + coefficient_group[i] = stbir__filter_info_table[filter].kernel(in_center_of_out - in_pixel_center, 1 / scale); + + // If the coefficient is zero, skip it. (Don't do the <0 check here, we want the influence of those outside pixels.) + if (i == 0 && !coefficient_group[i]) + { + contributor->n0 = ++in_first_pixel; + i--; + continue; + } + + total_filter += coefficient_group[i]; + } + + // NOTE(fg): Not actually true in general, nor is there any reason to expect it should be. + // It would be true in exact math but is at best approximately true in floating-point math, + // and it would not make sense to try and put actual bounds on this here because it depends + // on the image aspect ratio which can get pretty extreme. + //STBIR_ASSERT(stbir__filter_info_table[filter].kernel((float)(in_last_pixel + 1) + 0.5f - in_center_of_out, 1/scale) == 0); + + STBIR_ASSERT(total_filter > 0.9); + STBIR_ASSERT(total_filter < 1.1f); // Make sure it's not way off. + + // Make sure the sum of all coefficients is 1. + filter_scale = 1 / total_filter; + + for (i = 0; i <= in_last_pixel - in_first_pixel; i++) + coefficient_group[i] *= filter_scale; + + for (i = in_last_pixel - in_first_pixel; i >= 0; i--) + { + if (coefficient_group[i]) + break; + + // This line has no weight. We can skip it. + contributor->n1 = contributor->n0 + i - 1; + } +} + +static void stbir__calculate_coefficients_downsample(stbir_filter filter, float scale_ratio, int out_first_pixel, int out_last_pixel, float out_center_of_in, stbir__contributors* contributor, float* coefficient_group) +{ + int i; + + STBIR_ASSERT(out_last_pixel - out_first_pixel <= (int)ceil(stbir__filter_info_table[filter].support(scale_ratio) * 2)); // Taken directly from stbir__get_coefficient_width() which we can't call because we don't know if we're horizontal or vertical. + + contributor->n0 = out_first_pixel; + contributor->n1 = out_last_pixel; + + STBIR_ASSERT(contributor->n1 >= contributor->n0); + + 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; + coefficient_group[i] = stbir__filter_info_table[filter].kernel(x, scale_ratio) * scale_ratio; + } + + // NOTE(fg): Not actually true in general, nor is there any reason to expect it should be. + // It would be true in exact math but is at best approximately true in floating-point math, + // and it would not make sense to try and put actual bounds on this here because it depends + // on the image aspect ratio which can get pretty extreme. + //STBIR_ASSERT(stbir__filter_info_table[filter].kernel((float)(out_last_pixel + 1) + 0.5f - out_center_of_in, scale_ratio) == 0); + + for (i = out_last_pixel - out_first_pixel; i >= 0; i--) + { + if (coefficient_group[i]) + break; + + // This line has no weight. We can skip it. + contributor->n1 = contributor->n0 + i - 1; + } +} + +static void stbir__normalize_downsample_coefficients(stbir__contributors* contributors, float* coefficients, stbir_filter filter, float scale_ratio, int input_size, int output_size) +{ + int num_contributors = stbir__get_contributors(scale_ratio, filter, input_size, output_size); + int num_coefficients = stbir__get_coefficient_width(filter, scale_ratio); + int i, j; + int skip; + + for (i = 0; i < output_size; i++) + { + float scale; + float total = 0; + + for (j = 0; j < num_contributors; j++) + { + if (i >= contributors[j].n0 && i <= contributors[j].n1) + { + float coefficient = *stbir__get_coefficient(coefficients, filter, scale_ratio, j, i - contributors[j].n0); + total += coefficient; + } + else if (i < contributors[j].n0) + break; + } + + STBIR_ASSERT(total > 0.9f); + STBIR_ASSERT(total < 1.1f); + + scale = 1 / total; + + for (j = 0; j < num_contributors; j++) + { + if (i >= contributors[j].n0 && i <= contributors[j].n1) + *stbir__get_coefficient(coefficients, filter, scale_ratio, j, i - contributors[j].n0) *= scale; + else if (i < contributors[j].n0) + break; + } + } + + // Optimize: Skip zero coefficients and contributions outside of image bounds. + // Do this after normalizing because normalization depends on the n0/n1 values. + for (j = 0; j < num_contributors; j++) + { + int range, max, width; + + skip = 0; + while (*stbir__get_coefficient(coefficients, filter, scale_ratio, j, skip) == 0) + skip++; + + contributors[j].n0 += skip; + + while (contributors[j].n0 < 0) + { + contributors[j].n0++; + skip++; + } + + range = contributors[j].n1 - contributors[j].n0 + 1; + max = stbir__min(num_coefficients, range); + + width = stbir__get_coefficient_width(filter, scale_ratio); + for (i = 0; i < max; i++) + { + if (i + skip >= width) + break; + + *stbir__get_coefficient(coefficients, filter, scale_ratio, j, i) = *stbir__get_coefficient(coefficients, filter, scale_ratio, j, i + skip); + } + + continue; + } + + // Using min to avoid writing into invalid pixels. + for (i = 0; i < num_contributors; i++) + contributors[i].n1 = stbir__min(contributors[i].n1, output_size - 1); +} + +// Each scan line uses the same kernel values so we should calculate the kernel +// values once and then we can use them for every scan line. +static void stbir__calculate_filters(stbir__contributors* contributors, float* coefficients, stbir_filter filter, float scale_ratio, float shift, int input_size, int output_size) +{ + int n; + int total_contributors = stbir__get_contributors(scale_ratio, filter, input_size, output_size); + + if (stbir__use_upsampling(scale_ratio)) + { + float out_pixels_radius = stbir__filter_info_table[filter].support(1 / scale_ratio) * scale_ratio; + + // Looping through out pixels + for (n = 0; n < total_contributors; n++) + { + float in_center_of_out; // Center of the current out pixel in the in pixel space + int in_first_pixel, in_last_pixel; + + stbir__calculate_sample_range_upsample(n, out_pixels_radius, scale_ratio, shift, &in_first_pixel, &in_last_pixel, &in_center_of_out); + + stbir__calculate_coefficients_upsample(filter, scale_ratio, in_first_pixel, in_last_pixel, in_center_of_out, stbir__get_contributor(contributors, n), stbir__get_coefficient(coefficients, filter, scale_ratio, n, 0)); + } + } + else + { + float in_pixels_radius = stbir__filter_info_table[filter].support(scale_ratio) / scale_ratio; + + // Looping through in pixels + for (n = 0; n < total_contributors; n++) + { + float out_center_of_in; // Center of the current out pixel in the in pixel space + int out_first_pixel, out_last_pixel; + int n_adjusted = n - stbir__get_filter_pixel_margin(filter, scale_ratio); + + stbir__calculate_sample_range_downsample(n_adjusted, in_pixels_radius, scale_ratio, shift, &out_first_pixel, &out_last_pixel, &out_center_of_in); + + stbir__calculate_coefficients_downsample(filter, scale_ratio, out_first_pixel, out_last_pixel, out_center_of_in, stbir__get_contributor(contributors, n), stbir__get_coefficient(coefficients, filter, scale_ratio, n, 0)); + } + + stbir__normalize_downsample_coefficients(contributors, coefficients, filter, scale_ratio, input_size, output_size); + } +} + +static float* stbir__get_decode_buffer(stbir__info* stbir_info) +{ + // The 0 index of the decode buffer starts after the margin. This makes + // it okay to use negative indexes on the decode buffer. + return &stbir_info->decode_buffer[stbir_info->horizontal_filter_pixel_margin * stbir_info->channels]; +} + +#define STBIR__DECODE(type, colorspace) ((int)(type) * (STBIR_MAX_COLORSPACES) + (int)(colorspace)) + +static void stbir__decode_scanline(stbir__info* stbir_info, int n) +{ + int c; + int channels = stbir_info->channels; + int alpha_channel = stbir_info->alpha_channel; + int type = stbir_info->type; + int colorspace = stbir_info->colorspace; + int input_w = stbir_info->input_w; + size_t input_stride_bytes = stbir_info->input_stride_bytes; + float* decode_buffer = stbir__get_decode_buffer(stbir_info); + stbir_edge edge_horizontal = stbir_info->edge_horizontal; + stbir_edge edge_vertical = stbir_info->edge_vertical; + size_t in_buffer_row_offset = stbir__edge_wrap(edge_vertical, n, stbir_info->input_h) * input_stride_bytes; + const void* input_data = (char *) stbir_info->input_data + in_buffer_row_offset; + int max_x = input_w + stbir_info->horizontal_filter_pixel_margin; + int decode = STBIR__DECODE(type, colorspace); + + int x = -stbir_info->horizontal_filter_pixel_margin; + + // special handling for STBIR_EDGE_ZERO because it needs to return an item that doesn't appear in the input, + // and we want to avoid paying overhead on every pixel if not STBIR_EDGE_ZERO + if (edge_vertical == STBIR_EDGE_ZERO && (n < 0 || n >= stbir_info->input_h)) + { + for (; x < max_x; x++) + for (c = 0; c < channels; c++) + decode_buffer[x*channels + c] = 0; + return; + } + + switch (decode) + { + case STBIR__DECODE(STBIR_TYPE_UINT8, STBIR_COLORSPACE_LINEAR): + for (; x < max_x; x++) + { + int decode_pixel_index = x * channels; + int input_pixel_index = stbir__edge_wrap(edge_horizontal, x, input_w) * channels; + for (c = 0; c < channels; c++) + decode_buffer[decode_pixel_index + c] = ((float)((const unsigned char*)input_data)[input_pixel_index + c]) / stbir__max_uint8_as_float; + } + break; + + case STBIR__DECODE(STBIR_TYPE_UINT8, STBIR_COLORSPACE_SRGB): + for (; x < max_x; x++) + { + int decode_pixel_index = x * channels; + int input_pixel_index = stbir__edge_wrap(edge_horizontal, x, input_w) * channels; + for (c = 0; c < channels; c++) + decode_buffer[decode_pixel_index + c] = stbir__srgb_uchar_to_linear_float[((const unsigned char*)input_data)[input_pixel_index + c]]; + + if (!(stbir_info->flags&STBIR_FLAG_ALPHA_USES_COLORSPACE)) + decode_buffer[decode_pixel_index + alpha_channel] = ((float)((const unsigned char*)input_data)[input_pixel_index + alpha_channel]) / stbir__max_uint8_as_float; + } + break; + + case STBIR__DECODE(STBIR_TYPE_UINT16, STBIR_COLORSPACE_LINEAR): + for (; x < max_x; x++) + { + int decode_pixel_index = x * channels; + int input_pixel_index = stbir__edge_wrap(edge_horizontal, x, input_w) * channels; + for (c = 0; c < channels; c++) + decode_buffer[decode_pixel_index + c] = ((float)((const unsigned short*)input_data)[input_pixel_index + c]) / stbir__max_uint16_as_float; + } + break; + + case STBIR__DECODE(STBIR_TYPE_UINT16, STBIR_COLORSPACE_SRGB): + for (; x < max_x; x++) + { + int decode_pixel_index = x * channels; + int input_pixel_index = stbir__edge_wrap(edge_horizontal, x, input_w) * channels; + for (c = 0; c < channels; c++) + decode_buffer[decode_pixel_index + c] = stbir__srgb_to_linear(((float)((const unsigned short*)input_data)[input_pixel_index + c]) / stbir__max_uint16_as_float); + + if (!(stbir_info->flags&STBIR_FLAG_ALPHA_USES_COLORSPACE)) + decode_buffer[decode_pixel_index + alpha_channel] = ((float)((const unsigned short*)input_data)[input_pixel_index + alpha_channel]) / stbir__max_uint16_as_float; + } + break; + + case STBIR__DECODE(STBIR_TYPE_UINT32, STBIR_COLORSPACE_LINEAR): + for (; x < max_x; x++) + { + int decode_pixel_index = x * channels; + int input_pixel_index = stbir__edge_wrap(edge_horizontal, x, input_w) * channels; + for (c = 0; c < channels; c++) + decode_buffer[decode_pixel_index + c] = (float)(((double)((const unsigned int*)input_data)[input_pixel_index + c]) / stbir__max_uint32_as_float); + } + break; + + case STBIR__DECODE(STBIR_TYPE_UINT32, STBIR_COLORSPACE_SRGB): + for (; x < max_x; x++) + { + int decode_pixel_index = x * channels; + int input_pixel_index = stbir__edge_wrap(edge_horizontal, x, input_w) * channels; + for (c = 0; c < channels; c++) + decode_buffer[decode_pixel_index + c] = stbir__srgb_to_linear((float)(((double)((const unsigned int*)input_data)[input_pixel_index + c]) / stbir__max_uint32_as_float)); + + if (!(stbir_info->flags&STBIR_FLAG_ALPHA_USES_COLORSPACE)) + decode_buffer[decode_pixel_index + alpha_channel] = (float)(((double)((const unsigned int*)input_data)[input_pixel_index + alpha_channel]) / stbir__max_uint32_as_float); + } + break; + + case STBIR__DECODE(STBIR_TYPE_FLOAT, STBIR_COLORSPACE_LINEAR): + for (; x < max_x; x++) + { + int decode_pixel_index = x * channels; + int input_pixel_index = stbir__edge_wrap(edge_horizontal, x, input_w) * channels; + for (c = 0; c < channels; c++) + decode_buffer[decode_pixel_index + c] = ((const float*)input_data)[input_pixel_index + c]; + } + break; + + case STBIR__DECODE(STBIR_TYPE_FLOAT, STBIR_COLORSPACE_SRGB): + for (; x < max_x; x++) + { + int decode_pixel_index = x * channels; + int input_pixel_index = stbir__edge_wrap(edge_horizontal, x, input_w) * channels; + for (c = 0; c < channels; c++) + decode_buffer[decode_pixel_index + c] = stbir__srgb_to_linear(((const float*)input_data)[input_pixel_index + c]); + + if (!(stbir_info->flags&STBIR_FLAG_ALPHA_USES_COLORSPACE)) + decode_buffer[decode_pixel_index + alpha_channel] = ((const float*)input_data)[input_pixel_index + alpha_channel]; + } + + break; + + default: + STBIR_ASSERT(!"Unknown type/colorspace/channels combination."); + break; + } + + if (!(stbir_info->flags & STBIR_FLAG_ALPHA_PREMULTIPLIED)) + { + for (x = -stbir_info->horizontal_filter_pixel_margin; x < max_x; x++) + { + int decode_pixel_index = x * channels; + + // If the alpha value is 0 it will clobber the color values. Make sure it's not. + float alpha = decode_buffer[decode_pixel_index + alpha_channel]; +#ifndef STBIR_NO_ALPHA_EPSILON + if (stbir_info->type != STBIR_TYPE_FLOAT) { + alpha += STBIR_ALPHA_EPSILON; + decode_buffer[decode_pixel_index + alpha_channel] = alpha; + } +#endif + for (c = 0; c < channels; c++) + { + if (c == alpha_channel) + continue; + + decode_buffer[decode_pixel_index + c] *= alpha; + } + } + } + + if (edge_horizontal == STBIR_EDGE_ZERO) + { + for (x = -stbir_info->horizontal_filter_pixel_margin; x < 0; x++) + { + for (c = 0; c < channels; c++) + decode_buffer[x*channels + c] = 0; + } + for (x = input_w; x < max_x; x++) + { + for (c = 0; c < channels; c++) + decode_buffer[x*channels + c] = 0; + } + } +} + +static float* stbir__get_ring_buffer_entry(float* ring_buffer, int index, int ring_buffer_length) +{ + return &ring_buffer[index * ring_buffer_length]; +} + +static float* stbir__add_empty_ring_buffer_entry(stbir__info* stbir_info, int n) +{ + int ring_buffer_index; + float* ring_buffer; + + stbir_info->ring_buffer_last_scanline = n; + + if (stbir_info->ring_buffer_begin_index < 0) + { + ring_buffer_index = stbir_info->ring_buffer_begin_index = 0; + stbir_info->ring_buffer_first_scanline = n; + } + else + { + ring_buffer_index = (stbir_info->ring_buffer_begin_index + (stbir_info->ring_buffer_last_scanline - stbir_info->ring_buffer_first_scanline)) % stbir_info->ring_buffer_num_entries; + STBIR_ASSERT(ring_buffer_index != stbir_info->ring_buffer_begin_index); + } + + ring_buffer = stbir__get_ring_buffer_entry(stbir_info->ring_buffer, ring_buffer_index, stbir_info->ring_buffer_length_bytes / sizeof(float)); + memset(ring_buffer, 0, stbir_info->ring_buffer_length_bytes); + + return ring_buffer; +} + + +static void stbir__resample_horizontal_upsample(stbir__info* stbir_info, float* output_buffer) +{ + int x, k; + int output_w = stbir_info->output_w; + int channels = stbir_info->channels; + float* decode_buffer = stbir__get_decode_buffer(stbir_info); + stbir__contributors* horizontal_contributors = stbir_info->horizontal_contributors; + float* horizontal_coefficients = stbir_info->horizontal_coefficients; + int coefficient_width = stbir_info->horizontal_coefficient_width; + + for (x = 0; x < output_w; x++) + { + int n0 = horizontal_contributors[x].n0; + int n1 = horizontal_contributors[x].n1; + + int out_pixel_index = x * channels; + int coefficient_group = coefficient_width * x; + int coefficient_counter = 0; + + STBIR_ASSERT(n1 >= n0); + STBIR_ASSERT(n0 >= -stbir_info->horizontal_filter_pixel_margin); + STBIR_ASSERT(n1 >= -stbir_info->horizontal_filter_pixel_margin); + STBIR_ASSERT(n0 < stbir_info->input_w + stbir_info->horizontal_filter_pixel_margin); + STBIR_ASSERT(n1 < stbir_info->input_w + stbir_info->horizontal_filter_pixel_margin); + + switch (channels) { + case 1: + for (k = n0; k <= n1; k++) + { + int in_pixel_index = k * 1; + float coefficient = horizontal_coefficients[coefficient_group + coefficient_counter++]; + STBIR_ASSERT(coefficient != 0); + output_buffer[out_pixel_index + 0] += decode_buffer[in_pixel_index + 0] * coefficient; + } + break; + case 2: + for (k = n0; k <= n1; k++) + { + int in_pixel_index = k * 2; + float coefficient = horizontal_coefficients[coefficient_group + coefficient_counter++]; + STBIR_ASSERT(coefficient != 0); + output_buffer[out_pixel_index + 0] += decode_buffer[in_pixel_index + 0] * coefficient; + output_buffer[out_pixel_index + 1] += decode_buffer[in_pixel_index + 1] * coefficient; + } + break; + case 3: + for (k = n0; k <= n1; k++) + { + int in_pixel_index = k * 3; + float coefficient = horizontal_coefficients[coefficient_group + coefficient_counter++]; + STBIR_ASSERT(coefficient != 0); + output_buffer[out_pixel_index + 0] += decode_buffer[in_pixel_index + 0] * coefficient; + output_buffer[out_pixel_index + 1] += decode_buffer[in_pixel_index + 1] * coefficient; + output_buffer[out_pixel_index + 2] += decode_buffer[in_pixel_index + 2] * coefficient; + } + break; + case 4: + for (k = n0; k <= n1; k++) + { + int in_pixel_index = k * 4; + float coefficient = horizontal_coefficients[coefficient_group + coefficient_counter++]; + STBIR_ASSERT(coefficient != 0); + output_buffer[out_pixel_index + 0] += decode_buffer[in_pixel_index + 0] * coefficient; + output_buffer[out_pixel_index + 1] += decode_buffer[in_pixel_index + 1] * coefficient; + output_buffer[out_pixel_index + 2] += decode_buffer[in_pixel_index + 2] * coefficient; + output_buffer[out_pixel_index + 3] += decode_buffer[in_pixel_index + 3] * coefficient; + } + break; + default: + for (k = n0; k <= n1; k++) + { + int in_pixel_index = k * channels; + float coefficient = horizontal_coefficients[coefficient_group + coefficient_counter++]; + int c; + STBIR_ASSERT(coefficient != 0); + for (c = 0; c < channels; c++) + output_buffer[out_pixel_index + c] += decode_buffer[in_pixel_index + c] * coefficient; + } + break; + } + } +} + +static void stbir__resample_horizontal_downsample(stbir__info* stbir_info, float* output_buffer) +{ + int x, k; + int input_w = stbir_info->input_w; + int channels = stbir_info->channels; + float* decode_buffer = stbir__get_decode_buffer(stbir_info); + stbir__contributors* horizontal_contributors = stbir_info->horizontal_contributors; + float* horizontal_coefficients = stbir_info->horizontal_coefficients; + int coefficient_width = stbir_info->horizontal_coefficient_width; + int filter_pixel_margin = stbir_info->horizontal_filter_pixel_margin; + int max_x = input_w + filter_pixel_margin * 2; + + STBIR_ASSERT(!stbir__use_width_upsampling(stbir_info)); + + switch (channels) { + case 1: + for (x = 0; x < max_x; x++) + { + int n0 = horizontal_contributors[x].n0; + int n1 = horizontal_contributors[x].n1; + + int in_x = x - filter_pixel_margin; + int in_pixel_index = in_x * 1; + int max_n = n1; + int coefficient_group = coefficient_width * x; + + for (k = n0; k <= max_n; k++) + { + int out_pixel_index = k * 1; + float coefficient = horizontal_coefficients[coefficient_group + k - n0]; + output_buffer[out_pixel_index + 0] += decode_buffer[in_pixel_index + 0] * coefficient; + } + } + break; + + case 2: + for (x = 0; x < max_x; x++) + { + int n0 = horizontal_contributors[x].n0; + int n1 = horizontal_contributors[x].n1; + + int in_x = x - filter_pixel_margin; + int in_pixel_index = in_x * 2; + int max_n = n1; + int coefficient_group = coefficient_width * x; + + for (k = n0; k <= max_n; k++) + { + int out_pixel_index = k * 2; + float coefficient = horizontal_coefficients[coefficient_group + k - n0]; + output_buffer[out_pixel_index + 0] += decode_buffer[in_pixel_index + 0] * coefficient; + output_buffer[out_pixel_index + 1] += decode_buffer[in_pixel_index + 1] * coefficient; + } + } + break; + + case 3: + for (x = 0; x < max_x; x++) + { + int n0 = horizontal_contributors[x].n0; + int n1 = horizontal_contributors[x].n1; + + int in_x = x - filter_pixel_margin; + int in_pixel_index = in_x * 3; + int max_n = n1; + int coefficient_group = coefficient_width * x; + + for (k = n0; k <= max_n; k++) + { + int out_pixel_index = k * 3; + float coefficient = horizontal_coefficients[coefficient_group + k - n0]; + output_buffer[out_pixel_index + 0] += decode_buffer[in_pixel_index + 0] * coefficient; + output_buffer[out_pixel_index + 1] += decode_buffer[in_pixel_index + 1] * coefficient; + output_buffer[out_pixel_index + 2] += decode_buffer[in_pixel_index + 2] * coefficient; + } + } + break; + + case 4: + for (x = 0; x < max_x; x++) + { + int n0 = horizontal_contributors[x].n0; + int n1 = horizontal_contributors[x].n1; + + int in_x = x - filter_pixel_margin; + int in_pixel_index = in_x * 4; + int max_n = n1; + int coefficient_group = coefficient_width * x; + + for (k = n0; k <= max_n; k++) + { + int out_pixel_index = k * 4; + float coefficient = horizontal_coefficients[coefficient_group + k - n0]; + output_buffer[out_pixel_index + 0] += decode_buffer[in_pixel_index + 0] * coefficient; + output_buffer[out_pixel_index + 1] += decode_buffer[in_pixel_index + 1] * coefficient; + output_buffer[out_pixel_index + 2] += decode_buffer[in_pixel_index + 2] * coefficient; + output_buffer[out_pixel_index + 3] += decode_buffer[in_pixel_index + 3] * coefficient; + } + } + break; + + default: + for (x = 0; x < max_x; x++) + { + int n0 = horizontal_contributors[x].n0; + int n1 = horizontal_contributors[x].n1; + + int in_x = x - filter_pixel_margin; + int in_pixel_index = in_x * channels; + int max_n = n1; + int coefficient_group = coefficient_width * x; + + for (k = n0; k <= max_n; k++) + { + int c; + int out_pixel_index = k * channels; + float coefficient = horizontal_coefficients[coefficient_group + k - n0]; + for (c = 0; c < channels; c++) + output_buffer[out_pixel_index + c] += decode_buffer[in_pixel_index + c] * coefficient; + } + } + break; + } +} + +static void stbir__decode_and_resample_upsample(stbir__info* stbir_info, int n) +{ + // Decode the nth scanline from the source image into the decode buffer. + stbir__decode_scanline(stbir_info, n); + + // Now resample it into the ring buffer. + if (stbir__use_width_upsampling(stbir_info)) + stbir__resample_horizontal_upsample(stbir_info, stbir__add_empty_ring_buffer_entry(stbir_info, n)); + else + stbir__resample_horizontal_downsample(stbir_info, stbir__add_empty_ring_buffer_entry(stbir_info, n)); + + // Now it's sitting in the ring buffer ready to be used as source for the vertical sampling. +} + +static void stbir__decode_and_resample_downsample(stbir__info* stbir_info, int n) +{ + // Decode the nth scanline from the source image into the decode buffer. + stbir__decode_scanline(stbir_info, n); + + memset(stbir_info->horizontal_buffer, 0, stbir_info->output_w * stbir_info->channels * sizeof(float)); + + // Now resample it into the horizontal buffer. + if (stbir__use_width_upsampling(stbir_info)) + stbir__resample_horizontal_upsample(stbir_info, stbir_info->horizontal_buffer); + else + stbir__resample_horizontal_downsample(stbir_info, stbir_info->horizontal_buffer); + + // Now it's sitting in the horizontal buffer ready to be distributed into the ring buffers. +} + +// Get the specified scan line from the ring buffer. +static float* stbir__get_ring_buffer_scanline(int get_scanline, float* ring_buffer, int begin_index, int first_scanline, int ring_buffer_num_entries, int ring_buffer_length) +{ + int ring_buffer_index = (begin_index + (get_scanline - first_scanline)) % ring_buffer_num_entries; + return stbir__get_ring_buffer_entry(ring_buffer, ring_buffer_index, ring_buffer_length); +} + + +static void stbir__encode_scanline(stbir__info* stbir_info, int num_pixels, void *output_buffer, float *encode_buffer, int channels, int alpha_channel, int decode) +{ + int x; + int n; + int num_nonalpha; + stbir_uint16 nonalpha[STBIR_MAX_CHANNELS]; + + if (!(stbir_info->flags&STBIR_FLAG_ALPHA_PREMULTIPLIED)) + { + for (x=0; x < num_pixels; ++x) + { + int pixel_index = x*channels; + + float alpha = encode_buffer[pixel_index + alpha_channel]; + float reciprocal_alpha = alpha ? 1.0f / alpha : 0; + + // unrolling this produced a 1% slowdown upscaling a large RGBA linear-space image on my machine - stb + for (n = 0; n < channels; n++) + if (n != alpha_channel) + encode_buffer[pixel_index + n] *= reciprocal_alpha; + + // We added in a small epsilon to prevent the color channel from being deleted with zero alpha. + // Because we only add it for integer types, it will automatically be discarded on integer + // conversion, so we don't need to subtract it back out (which would be problematic for + // numeric precision reasons). + } + } + + // build a table of all channels that need colorspace correction, so + // we don't perform colorspace correction on channels that don't need it. + for (x = 0, num_nonalpha = 0; x < channels; ++x) + { + if (x != alpha_channel || (stbir_info->flags & STBIR_FLAG_ALPHA_USES_COLORSPACE)) + { + nonalpha[num_nonalpha++] = (stbir_uint16)x; + } + } + + #define STBIR__ROUND_INT(f) ((int) ((f)+0.5)) + #define STBIR__ROUND_UINT(f) ((stbir_uint32) ((f)+0.5)) + + #ifdef STBIR__SATURATE_INT + #define STBIR__ENCODE_LINEAR8(f) stbir__saturate8 (STBIR__ROUND_INT((f) * stbir__max_uint8_as_float )) + #define STBIR__ENCODE_LINEAR16(f) stbir__saturate16(STBIR__ROUND_INT((f) * stbir__max_uint16_as_float)) + #else + #define STBIR__ENCODE_LINEAR8(f) (unsigned char ) STBIR__ROUND_INT(stbir__saturate(f) * stbir__max_uint8_as_float ) + #define STBIR__ENCODE_LINEAR16(f) (unsigned short) STBIR__ROUND_INT(stbir__saturate(f) * stbir__max_uint16_as_float) + #endif + + switch (decode) + { + case STBIR__DECODE(STBIR_TYPE_UINT8, STBIR_COLORSPACE_LINEAR): + for (x=0; x < num_pixels; ++x) + { + int pixel_index = x*channels; + + for (n = 0; n < channels; n++) + { + int index = pixel_index + n; + ((unsigned char*)output_buffer)[index] = STBIR__ENCODE_LINEAR8(encode_buffer[index]); + } + } + break; + + case STBIR__DECODE(STBIR_TYPE_UINT8, STBIR_COLORSPACE_SRGB): + for (x=0; x < num_pixels; ++x) + { + int pixel_index = x*channels; + + for (n = 0; n < num_nonalpha; n++) + { + int index = pixel_index + nonalpha[n]; + ((unsigned char*)output_buffer)[index] = stbir__linear_to_srgb_uchar(encode_buffer[index]); + } + + if (!(stbir_info->flags & STBIR_FLAG_ALPHA_USES_COLORSPACE)) + ((unsigned char *)output_buffer)[pixel_index + alpha_channel] = STBIR__ENCODE_LINEAR8(encode_buffer[pixel_index+alpha_channel]); + } + break; + + case STBIR__DECODE(STBIR_TYPE_UINT16, STBIR_COLORSPACE_LINEAR): + for (x=0; x < num_pixels; ++x) + { + int pixel_index = x*channels; + + for (n = 0; n < channels; n++) + { + int index = pixel_index + n; + ((unsigned short*)output_buffer)[index] = STBIR__ENCODE_LINEAR16(encode_buffer[index]); + } + } + break; + + case STBIR__DECODE(STBIR_TYPE_UINT16, STBIR_COLORSPACE_SRGB): + for (x=0; x < num_pixels; ++x) + { + int pixel_index = x*channels; + + for (n = 0; n < num_nonalpha; n++) + { + int index = pixel_index + nonalpha[n]; + ((unsigned short*)output_buffer)[index] = (unsigned short)STBIR__ROUND_INT(stbir__linear_to_srgb(stbir__saturate(encode_buffer[index])) * stbir__max_uint16_as_float); + } + + if (!(stbir_info->flags&STBIR_FLAG_ALPHA_USES_COLORSPACE)) + ((unsigned short*)output_buffer)[pixel_index + alpha_channel] = STBIR__ENCODE_LINEAR16(encode_buffer[pixel_index + alpha_channel]); + } + + break; + + case STBIR__DECODE(STBIR_TYPE_UINT32, STBIR_COLORSPACE_LINEAR): + for (x=0; x < num_pixels; ++x) + { + int pixel_index = x*channels; + + for (n = 0; n < channels; n++) + { + int index = pixel_index + n; + ((unsigned int*)output_buffer)[index] = (unsigned int)STBIR__ROUND_UINT(((double)stbir__saturate(encode_buffer[index])) * stbir__max_uint32_as_float); + } + } + break; + + case STBIR__DECODE(STBIR_TYPE_UINT32, STBIR_COLORSPACE_SRGB): + for (x=0; x < num_pixels; ++x) + { + int pixel_index = x*channels; + + for (n = 0; n < num_nonalpha; n++) + { + int index = pixel_index + nonalpha[n]; + ((unsigned int*)output_buffer)[index] = (unsigned int)STBIR__ROUND_UINT(((double)stbir__linear_to_srgb(stbir__saturate(encode_buffer[index]))) * stbir__max_uint32_as_float); + } + + if (!(stbir_info->flags&STBIR_FLAG_ALPHA_USES_COLORSPACE)) + ((unsigned int*)output_buffer)[pixel_index + alpha_channel] = (unsigned int)STBIR__ROUND_INT(((double)stbir__saturate(encode_buffer[pixel_index + alpha_channel])) * stbir__max_uint32_as_float); + } + break; + + case STBIR__DECODE(STBIR_TYPE_FLOAT, STBIR_COLORSPACE_LINEAR): + for (x=0; x < num_pixels; ++x) + { + int pixel_index = x*channels; + + for (n = 0; n < channels; n++) + { + int index = pixel_index + n; + ((float*)output_buffer)[index] = encode_buffer[index]; + } + } + break; + + case STBIR__DECODE(STBIR_TYPE_FLOAT, STBIR_COLORSPACE_SRGB): + for (x=0; x < num_pixels; ++x) + { + int pixel_index = x*channels; + + for (n = 0; n < num_nonalpha; n++) + { + int index = pixel_index + nonalpha[n]; + ((float*)output_buffer)[index] = stbir__linear_to_srgb(encode_buffer[index]); + } + + if (!(stbir_info->flags&STBIR_FLAG_ALPHA_USES_COLORSPACE)) + ((float*)output_buffer)[pixel_index + alpha_channel] = encode_buffer[pixel_index + alpha_channel]; + } + break; + + default: + STBIR_ASSERT(!"Unknown type/colorspace/channels combination."); + break; + } +} + +static void stbir__resample_vertical_upsample(stbir__info* stbir_info, int n) +{ + int x, k; + int output_w = stbir_info->output_w; + stbir__contributors* vertical_contributors = stbir_info->vertical_contributors; + float* vertical_coefficients = stbir_info->vertical_coefficients; + int channels = stbir_info->channels; + int alpha_channel = stbir_info->alpha_channel; + int type = stbir_info->type; + int colorspace = stbir_info->colorspace; + int ring_buffer_entries = stbir_info->ring_buffer_num_entries; + void* output_data = stbir_info->output_data; + float* encode_buffer = stbir_info->encode_buffer; + int decode = STBIR__DECODE(type, colorspace); + int coefficient_width = stbir_info->vertical_coefficient_width; + int coefficient_counter; + int contributor = n; + + float* ring_buffer = stbir_info->ring_buffer; + int ring_buffer_begin_index = stbir_info->ring_buffer_begin_index; + int ring_buffer_first_scanline = stbir_info->ring_buffer_first_scanline; + int ring_buffer_length = stbir_info->ring_buffer_length_bytes/sizeof(float); + + int n0,n1, output_row_start; + int coefficient_group = coefficient_width * contributor; + + n0 = vertical_contributors[contributor].n0; + n1 = vertical_contributors[contributor].n1; + + output_row_start = n * stbir_info->output_stride_bytes; + + STBIR_ASSERT(stbir__use_height_upsampling(stbir_info)); + + memset(encode_buffer, 0, output_w * sizeof(float) * channels); + + // I tried reblocking this for better cache usage of encode_buffer + // (using x_outer, k, x_inner), but it lost speed. -- stb + + coefficient_counter = 0; + switch (channels) { + case 1: + for (k = n0; k <= n1; k++) + { + int coefficient_index = coefficient_counter++; + float* ring_buffer_entry = stbir__get_ring_buffer_scanline(k, ring_buffer, ring_buffer_begin_index, ring_buffer_first_scanline, ring_buffer_entries, ring_buffer_length); + float coefficient = vertical_coefficients[coefficient_group + coefficient_index]; + for (x = 0; x < output_w; ++x) + { + int in_pixel_index = x * 1; + encode_buffer[in_pixel_index + 0] += ring_buffer_entry[in_pixel_index + 0] * coefficient; + } + } + break; + case 2: + for (k = n0; k <= n1; k++) + { + int coefficient_index = coefficient_counter++; + float* ring_buffer_entry = stbir__get_ring_buffer_scanline(k, ring_buffer, ring_buffer_begin_index, ring_buffer_first_scanline, ring_buffer_entries, ring_buffer_length); + float coefficient = vertical_coefficients[coefficient_group + coefficient_index]; + for (x = 0; x < output_w; ++x) + { + int in_pixel_index = x * 2; + encode_buffer[in_pixel_index + 0] += ring_buffer_entry[in_pixel_index + 0] * coefficient; + encode_buffer[in_pixel_index + 1] += ring_buffer_entry[in_pixel_index + 1] * coefficient; + } + } + break; + case 3: + for (k = n0; k <= n1; k++) + { + int coefficient_index = coefficient_counter++; + float* ring_buffer_entry = stbir__get_ring_buffer_scanline(k, ring_buffer, ring_buffer_begin_index, ring_buffer_first_scanline, ring_buffer_entries, ring_buffer_length); + float coefficient = vertical_coefficients[coefficient_group + coefficient_index]; + for (x = 0; x < output_w; ++x) + { + int in_pixel_index = x * 3; + encode_buffer[in_pixel_index + 0] += ring_buffer_entry[in_pixel_index + 0] * coefficient; + encode_buffer[in_pixel_index + 1] += ring_buffer_entry[in_pixel_index + 1] * coefficient; + encode_buffer[in_pixel_index + 2] += ring_buffer_entry[in_pixel_index + 2] * coefficient; + } + } + break; + case 4: + for (k = n0; k <= n1; k++) + { + int coefficient_index = coefficient_counter++; + float* ring_buffer_entry = stbir__get_ring_buffer_scanline(k, ring_buffer, ring_buffer_begin_index, ring_buffer_first_scanline, ring_buffer_entries, ring_buffer_length); + float coefficient = vertical_coefficients[coefficient_group + coefficient_index]; + for (x = 0; x < output_w; ++x) + { + int in_pixel_index = x * 4; + encode_buffer[in_pixel_index + 0] += ring_buffer_entry[in_pixel_index + 0] * coefficient; + encode_buffer[in_pixel_index + 1] += ring_buffer_entry[in_pixel_index + 1] * coefficient; + encode_buffer[in_pixel_index + 2] += ring_buffer_entry[in_pixel_index + 2] * coefficient; + encode_buffer[in_pixel_index + 3] += ring_buffer_entry[in_pixel_index + 3] * coefficient; + } + } + break; + default: + for (k = n0; k <= n1; k++) + { + int coefficient_index = coefficient_counter++; + float* ring_buffer_entry = stbir__get_ring_buffer_scanline(k, ring_buffer, ring_buffer_begin_index, ring_buffer_first_scanline, ring_buffer_entries, ring_buffer_length); + float coefficient = vertical_coefficients[coefficient_group + coefficient_index]; + for (x = 0; x < output_w; ++x) + { + int in_pixel_index = x * channels; + int c; + for (c = 0; c < channels; c++) + encode_buffer[in_pixel_index + c] += ring_buffer_entry[in_pixel_index + c] * coefficient; + } + } + break; + } + stbir__encode_scanline(stbir_info, output_w, (char *) output_data + output_row_start, encode_buffer, channels, alpha_channel, decode); +} + +static void stbir__resample_vertical_downsample(stbir__info* stbir_info, int n) +{ + int x, k; + int output_w = stbir_info->output_w; + stbir__contributors* vertical_contributors = stbir_info->vertical_contributors; + float* vertical_coefficients = stbir_info->vertical_coefficients; + int channels = stbir_info->channels; + int ring_buffer_entries = stbir_info->ring_buffer_num_entries; + float* horizontal_buffer = stbir_info->horizontal_buffer; + int coefficient_width = stbir_info->vertical_coefficient_width; + int contributor = n + stbir_info->vertical_filter_pixel_margin; + + float* ring_buffer = stbir_info->ring_buffer; + int ring_buffer_begin_index = stbir_info->ring_buffer_begin_index; + int ring_buffer_first_scanline = stbir_info->ring_buffer_first_scanline; + int ring_buffer_length = stbir_info->ring_buffer_length_bytes/sizeof(float); + int n0,n1; + + n0 = vertical_contributors[contributor].n0; + n1 = vertical_contributors[contributor].n1; + + STBIR_ASSERT(!stbir__use_height_upsampling(stbir_info)); + + for (k = n0; k <= n1; k++) + { + int coefficient_index = k - n0; + int coefficient_group = coefficient_width * contributor; + float coefficient = vertical_coefficients[coefficient_group + coefficient_index]; + + float* ring_buffer_entry = stbir__get_ring_buffer_scanline(k, ring_buffer, ring_buffer_begin_index, ring_buffer_first_scanline, ring_buffer_entries, ring_buffer_length); + + switch (channels) { + case 1: + for (x = 0; x < output_w; x++) + { + int in_pixel_index = x * 1; + ring_buffer_entry[in_pixel_index + 0] += horizontal_buffer[in_pixel_index + 0] * coefficient; + } + break; + case 2: + for (x = 0; x < output_w; x++) + { + int in_pixel_index = x * 2; + ring_buffer_entry[in_pixel_index + 0] += horizontal_buffer[in_pixel_index + 0] * coefficient; + ring_buffer_entry[in_pixel_index + 1] += horizontal_buffer[in_pixel_index + 1] * coefficient; + } + break; + case 3: + for (x = 0; x < output_w; x++) + { + int in_pixel_index = x * 3; + ring_buffer_entry[in_pixel_index + 0] += horizontal_buffer[in_pixel_index + 0] * coefficient; + ring_buffer_entry[in_pixel_index + 1] += horizontal_buffer[in_pixel_index + 1] * coefficient; + ring_buffer_entry[in_pixel_index + 2] += horizontal_buffer[in_pixel_index + 2] * coefficient; + } + break; + case 4: + for (x = 0; x < output_w; x++) + { + int in_pixel_index = x * 4; + ring_buffer_entry[in_pixel_index + 0] += horizontal_buffer[in_pixel_index + 0] * coefficient; + ring_buffer_entry[in_pixel_index + 1] += horizontal_buffer[in_pixel_index + 1] * coefficient; + ring_buffer_entry[in_pixel_index + 2] += horizontal_buffer[in_pixel_index + 2] * coefficient; + ring_buffer_entry[in_pixel_index + 3] += horizontal_buffer[in_pixel_index + 3] * coefficient; + } + break; + default: + for (x = 0; x < output_w; x++) + { + int in_pixel_index = x * channels; + + int c; + for (c = 0; c < channels; c++) + ring_buffer_entry[in_pixel_index + c] += horizontal_buffer[in_pixel_index + c] * coefficient; + } + break; + } + } +} + +static void stbir__buffer_loop_upsample(stbir__info* stbir_info) +{ + int y; + float scale_ratio = stbir_info->vertical_scale; + float out_scanlines_radius = stbir__filter_info_table[stbir_info->vertical_filter].support(1/scale_ratio) * scale_ratio; + + STBIR_ASSERT(stbir__use_height_upsampling(stbir_info)); + + for (y = 0; y < stbir_info->output_h; y++) + { + float in_center_of_out = 0; // Center of the current out scanline in the in scanline space + int in_first_scanline = 0, in_last_scanline = 0; + + stbir__calculate_sample_range_upsample(y, out_scanlines_radius, scale_ratio, stbir_info->vertical_shift, &in_first_scanline, &in_last_scanline, &in_center_of_out); + + STBIR_ASSERT(in_last_scanline - in_first_scanline + 1 <= stbir_info->ring_buffer_num_entries); + + if (stbir_info->ring_buffer_begin_index >= 0) + { + // Get rid of whatever we don't need anymore. + while (in_first_scanline > stbir_info->ring_buffer_first_scanline) + { + if (stbir_info->ring_buffer_first_scanline == stbir_info->ring_buffer_last_scanline) + { + // We just popped the last scanline off the ring buffer. + // Reset it to the empty state. + stbir_info->ring_buffer_begin_index = -1; + stbir_info->ring_buffer_first_scanline = 0; + stbir_info->ring_buffer_last_scanline = 0; + break; + } + else + { + stbir_info->ring_buffer_first_scanline++; + stbir_info->ring_buffer_begin_index = (stbir_info->ring_buffer_begin_index + 1) % stbir_info->ring_buffer_num_entries; + } + } + } + + // Load in new ones. + if (stbir_info->ring_buffer_begin_index < 0) + stbir__decode_and_resample_upsample(stbir_info, in_first_scanline); + + while (in_last_scanline > stbir_info->ring_buffer_last_scanline) + stbir__decode_and_resample_upsample(stbir_info, stbir_info->ring_buffer_last_scanline + 1); + + // Now all buffers should be ready to write a row of vertical sampling. + stbir__resample_vertical_upsample(stbir_info, y); + + STBIR_PROGRESS_REPORT((float)y / stbir_info->output_h); + } +} + +static void stbir__empty_ring_buffer(stbir__info* stbir_info, int first_necessary_scanline) +{ + int output_stride_bytes = stbir_info->output_stride_bytes; + int channels = stbir_info->channels; + int alpha_channel = stbir_info->alpha_channel; + int type = stbir_info->type; + int colorspace = stbir_info->colorspace; + int output_w = stbir_info->output_w; + void* output_data = stbir_info->output_data; + int decode = STBIR__DECODE(type, colorspace); + + float* ring_buffer = stbir_info->ring_buffer; + int ring_buffer_length = stbir_info->ring_buffer_length_bytes/sizeof(float); + + if (stbir_info->ring_buffer_begin_index >= 0) + { + // Get rid of whatever we don't need anymore. + while (first_necessary_scanline > stbir_info->ring_buffer_first_scanline) + { + if (stbir_info->ring_buffer_first_scanline >= 0 && stbir_info->ring_buffer_first_scanline < stbir_info->output_h) + { + int output_row_start = stbir_info->ring_buffer_first_scanline * output_stride_bytes; + float* ring_buffer_entry = stbir__get_ring_buffer_entry(ring_buffer, stbir_info->ring_buffer_begin_index, ring_buffer_length); + stbir__encode_scanline(stbir_info, output_w, (char *) output_data + output_row_start, ring_buffer_entry, channels, alpha_channel, decode); + STBIR_PROGRESS_REPORT((float)stbir_info->ring_buffer_first_scanline / stbir_info->output_h); + } + + if (stbir_info->ring_buffer_first_scanline == stbir_info->ring_buffer_last_scanline) + { + // We just popped the last scanline off the ring buffer. + // Reset it to the empty state. + stbir_info->ring_buffer_begin_index = -1; + stbir_info->ring_buffer_first_scanline = 0; + stbir_info->ring_buffer_last_scanline = 0; + break; + } + else + { + stbir_info->ring_buffer_first_scanline++; + stbir_info->ring_buffer_begin_index = (stbir_info->ring_buffer_begin_index + 1) % stbir_info->ring_buffer_num_entries; + } + } + } +} + +static void stbir__buffer_loop_downsample(stbir__info* stbir_info) +{ + int y; + float scale_ratio = stbir_info->vertical_scale; + int output_h = stbir_info->output_h; + float in_pixels_radius = stbir__filter_info_table[stbir_info->vertical_filter].support(scale_ratio) / scale_ratio; + int pixel_margin = stbir_info->vertical_filter_pixel_margin; + int max_y = stbir_info->input_h + pixel_margin; + + STBIR_ASSERT(!stbir__use_height_upsampling(stbir_info)); + + for (y = -pixel_margin; y < max_y; y++) + { + float out_center_of_in; // Center of the current out scanline in the in scanline space + int out_first_scanline, out_last_scanline; + + stbir__calculate_sample_range_downsample(y, in_pixels_radius, scale_ratio, stbir_info->vertical_shift, &out_first_scanline, &out_last_scanline, &out_center_of_in); + + STBIR_ASSERT(out_last_scanline - out_first_scanline + 1 <= stbir_info->ring_buffer_num_entries); + + if (out_last_scanline < 0 || out_first_scanline >= output_h) + continue; + + stbir__empty_ring_buffer(stbir_info, out_first_scanline); + + stbir__decode_and_resample_downsample(stbir_info, y); + + // Load in new ones. + if (stbir_info->ring_buffer_begin_index < 0) + stbir__add_empty_ring_buffer_entry(stbir_info, out_first_scanline); + + while (out_last_scanline > stbir_info->ring_buffer_last_scanline) + stbir__add_empty_ring_buffer_entry(stbir_info, stbir_info->ring_buffer_last_scanline + 1); + + // Now the horizontal buffer is ready to write to all ring buffer rows. + stbir__resample_vertical_downsample(stbir_info, y); + } + + stbir__empty_ring_buffer(stbir_info, stbir_info->output_h); +} + +static void stbir__setup(stbir__info *info, int input_w, int input_h, int output_w, int output_h, int channels) +{ + info->input_w = input_w; + info->input_h = input_h; + info->output_w = output_w; + info->output_h = output_h; + info->channels = channels; +} + +static void stbir__calculate_transform(stbir__info *info, float s0, float t0, float s1, float t1, float *transform) +{ + info->s0 = s0; + info->t0 = t0; + info->s1 = s1; + info->t1 = t1; + + if (transform) + { + info->horizontal_scale = transform[0]; + info->vertical_scale = transform[1]; + info->horizontal_shift = transform[2]; + info->vertical_shift = transform[3]; + } + else + { + info->horizontal_scale = ((float)info->output_w / info->input_w) / (s1 - s0); + info->vertical_scale = ((float)info->output_h / info->input_h) / (t1 - t0); + + info->horizontal_shift = s0 * info->output_w / (s1 - s0); + info->vertical_shift = t0 * info->output_h / (t1 - t0); + } +} + +static void stbir__choose_filter(stbir__info *info, stbir_filter h_filter, stbir_filter v_filter) +{ + if (h_filter == 0) + h_filter = stbir__use_upsampling(info->horizontal_scale) ? STBIR_DEFAULT_FILTER_UPSAMPLE : STBIR_DEFAULT_FILTER_DOWNSAMPLE; + if (v_filter == 0) + v_filter = stbir__use_upsampling(info->vertical_scale) ? STBIR_DEFAULT_FILTER_UPSAMPLE : STBIR_DEFAULT_FILTER_DOWNSAMPLE; + info->horizontal_filter = h_filter; + info->vertical_filter = v_filter; +} + +static stbir_uint32 stbir__calculate_memory(stbir__info *info) +{ + int pixel_margin = stbir__get_filter_pixel_margin(info->horizontal_filter, info->horizontal_scale); + int filter_height = stbir__get_filter_pixel_width(info->vertical_filter, info->vertical_scale); + + info->horizontal_num_contributors = stbir__get_contributors(info->horizontal_scale, info->horizontal_filter, info->input_w, info->output_w); + info->vertical_num_contributors = stbir__get_contributors(info->vertical_scale , info->vertical_filter , info->input_h, info->output_h); + + // One extra entry because floating point precision problems sometimes cause an extra to be necessary. + info->ring_buffer_num_entries = filter_height + 1; + + info->horizontal_contributors_size = info->horizontal_num_contributors * sizeof(stbir__contributors); + info->horizontal_coefficients_size = stbir__get_total_horizontal_coefficients(info) * sizeof(float); + info->vertical_contributors_size = info->vertical_num_contributors * sizeof(stbir__contributors); + info->vertical_coefficients_size = stbir__get_total_vertical_coefficients(info) * sizeof(float); + info->decode_buffer_size = (info->input_w + pixel_margin * 2) * info->channels * sizeof(float); + info->horizontal_buffer_size = info->output_w * info->channels * sizeof(float); + info->ring_buffer_size = info->output_w * info->channels * info->ring_buffer_num_entries * sizeof(float); + info->encode_buffer_size = info->output_w * info->channels * sizeof(float); + + STBIR_ASSERT(info->horizontal_filter != 0); + STBIR_ASSERT(info->horizontal_filter < STBIR__ARRAY_SIZE(stbir__filter_info_table)); // this now happens too late + STBIR_ASSERT(info->vertical_filter != 0); + STBIR_ASSERT(info->vertical_filter < STBIR__ARRAY_SIZE(stbir__filter_info_table)); // this now happens too late + + if (stbir__use_height_upsampling(info)) + // The horizontal buffer is for when we're downsampling the height and we + // can't output the result of sampling the decode buffer directly into the + // ring buffers. + info->horizontal_buffer_size = 0; + else + // The encode buffer is to retain precision in the height upsampling method + // and isn't used when height downsampling. + info->encode_buffer_size = 0; + + return info->horizontal_contributors_size + info->horizontal_coefficients_size + + info->vertical_contributors_size + info->vertical_coefficients_size + + info->decode_buffer_size + info->horizontal_buffer_size + + info->ring_buffer_size + info->encode_buffer_size; +} + +static int stbir__resize_allocated(stbir__info *info, + const void* input_data, int input_stride_in_bytes, + void* output_data, int output_stride_in_bytes, + int alpha_channel, stbir_uint32 flags, stbir_datatype type, + stbir_edge edge_horizontal, stbir_edge edge_vertical, stbir_colorspace colorspace, + void* tempmem, size_t tempmem_size_in_bytes) +{ + size_t memory_required = stbir__calculate_memory(info); + + int width_stride_input = input_stride_in_bytes ? input_stride_in_bytes : info->channels * info->input_w * stbir__type_size[type]; + int width_stride_output = output_stride_in_bytes ? output_stride_in_bytes : info->channels * info->output_w * stbir__type_size[type]; + +#ifdef STBIR_DEBUG_OVERWRITE_TEST +#define OVERWRITE_ARRAY_SIZE 8 + unsigned char overwrite_output_before_pre[OVERWRITE_ARRAY_SIZE]; + unsigned char overwrite_tempmem_before_pre[OVERWRITE_ARRAY_SIZE]; + unsigned char overwrite_output_after_pre[OVERWRITE_ARRAY_SIZE]; + unsigned char overwrite_tempmem_after_pre[OVERWRITE_ARRAY_SIZE]; + + size_t begin_forbidden = width_stride_output * (info->output_h - 1) + info->output_w * info->channels * stbir__type_size[type]; + memcpy(overwrite_output_before_pre, &((unsigned char*)output_data)[-OVERWRITE_ARRAY_SIZE], OVERWRITE_ARRAY_SIZE); + memcpy(overwrite_output_after_pre, &((unsigned char*)output_data)[begin_forbidden], OVERWRITE_ARRAY_SIZE); + memcpy(overwrite_tempmem_before_pre, &((unsigned char*)tempmem)[-OVERWRITE_ARRAY_SIZE], OVERWRITE_ARRAY_SIZE); + memcpy(overwrite_tempmem_after_pre, &((unsigned char*)tempmem)[tempmem_size_in_bytes], OVERWRITE_ARRAY_SIZE); +#endif + + STBIR_ASSERT(info->channels >= 0); + STBIR_ASSERT(info->channels <= STBIR_MAX_CHANNELS); + + if (info->channels < 0 || info->channels > STBIR_MAX_CHANNELS) + return 0; + + STBIR_ASSERT(info->horizontal_filter < STBIR__ARRAY_SIZE(stbir__filter_info_table)); + STBIR_ASSERT(info->vertical_filter < STBIR__ARRAY_SIZE(stbir__filter_info_table)); + + if (info->horizontal_filter >= STBIR__ARRAY_SIZE(stbir__filter_info_table)) + return 0; + if (info->vertical_filter >= STBIR__ARRAY_SIZE(stbir__filter_info_table)) + return 0; + + if (alpha_channel < 0) + flags |= STBIR_FLAG_ALPHA_USES_COLORSPACE | STBIR_FLAG_ALPHA_PREMULTIPLIED; + + if (!(flags&STBIR_FLAG_ALPHA_USES_COLORSPACE) || !(flags&STBIR_FLAG_ALPHA_PREMULTIPLIED)) { + STBIR_ASSERT(alpha_channel >= 0 && alpha_channel < info->channels); + } + + if (alpha_channel >= info->channels) + return 0; + + STBIR_ASSERT(tempmem); + + if (!tempmem) + return 0; + + STBIR_ASSERT(tempmem_size_in_bytes >= memory_required); + + if (tempmem_size_in_bytes < memory_required) + return 0; + + memset(tempmem, 0, tempmem_size_in_bytes); + + info->input_data = input_data; + info->input_stride_bytes = width_stride_input; + + info->output_data = output_data; + info->output_stride_bytes = width_stride_output; + + info->alpha_channel = alpha_channel; + info->flags = flags; + info->type = type; + info->edge_horizontal = edge_horizontal; + info->edge_vertical = edge_vertical; + info->colorspace = colorspace; + + info->horizontal_coefficient_width = stbir__get_coefficient_width (info->horizontal_filter, info->horizontal_scale); + info->vertical_coefficient_width = stbir__get_coefficient_width (info->vertical_filter , info->vertical_scale ); + info->horizontal_filter_pixel_width = stbir__get_filter_pixel_width (info->horizontal_filter, info->horizontal_scale); + info->vertical_filter_pixel_width = stbir__get_filter_pixel_width (info->vertical_filter , info->vertical_scale ); + info->horizontal_filter_pixel_margin = stbir__get_filter_pixel_margin(info->horizontal_filter, info->horizontal_scale); + info->vertical_filter_pixel_margin = stbir__get_filter_pixel_margin(info->vertical_filter , info->vertical_scale ); + + info->ring_buffer_length_bytes = info->output_w * info->channels * sizeof(float); + info->decode_buffer_pixels = info->input_w + info->horizontal_filter_pixel_margin * 2; + +#define STBIR__NEXT_MEMPTR(current, newtype) (newtype*)(((unsigned char*)current) + current##_size) + + info->horizontal_contributors = (stbir__contributors *) tempmem; + info->horizontal_coefficients = STBIR__NEXT_MEMPTR(info->horizontal_contributors, float); + info->vertical_contributors = STBIR__NEXT_MEMPTR(info->horizontal_coefficients, stbir__contributors); + info->vertical_coefficients = STBIR__NEXT_MEMPTR(info->vertical_contributors, float); + info->decode_buffer = STBIR__NEXT_MEMPTR(info->vertical_coefficients, float); + + if (stbir__use_height_upsampling(info)) + { + info->horizontal_buffer = NULL; + info->ring_buffer = STBIR__NEXT_MEMPTR(info->decode_buffer, float); + info->encode_buffer = STBIR__NEXT_MEMPTR(info->ring_buffer, float); + + STBIR_ASSERT((size_t)STBIR__NEXT_MEMPTR(info->encode_buffer, unsigned char) == (size_t)tempmem + tempmem_size_in_bytes); + } + else + { + info->horizontal_buffer = STBIR__NEXT_MEMPTR(info->decode_buffer, float); + info->ring_buffer = STBIR__NEXT_MEMPTR(info->horizontal_buffer, float); + info->encode_buffer = NULL; + + STBIR_ASSERT((size_t)STBIR__NEXT_MEMPTR(info->ring_buffer, unsigned char) == (size_t)tempmem + tempmem_size_in_bytes); + } + +#undef STBIR__NEXT_MEMPTR + + // This signals that the ring buffer is empty + info->ring_buffer_begin_index = -1; + + stbir__calculate_filters(info->horizontal_contributors, info->horizontal_coefficients, info->horizontal_filter, info->horizontal_scale, info->horizontal_shift, info->input_w, info->output_w); + stbir__calculate_filters(info->vertical_contributors, info->vertical_coefficients, info->vertical_filter, info->vertical_scale, info->vertical_shift, info->input_h, info->output_h); + + STBIR_PROGRESS_REPORT(0); + + if (stbir__use_height_upsampling(info)) + stbir__buffer_loop_upsample(info); + else + stbir__buffer_loop_downsample(info); + + STBIR_PROGRESS_REPORT(1); + +#ifdef STBIR_DEBUG_OVERWRITE_TEST + STBIR_ASSERT(memcmp(overwrite_output_before_pre, &((unsigned char*)output_data)[-OVERWRITE_ARRAY_SIZE], OVERWRITE_ARRAY_SIZE) == 0); + STBIR_ASSERT(memcmp(overwrite_output_after_pre, &((unsigned char*)output_data)[begin_forbidden], OVERWRITE_ARRAY_SIZE) == 0); + STBIR_ASSERT(memcmp(overwrite_tempmem_before_pre, &((unsigned char*)tempmem)[-OVERWRITE_ARRAY_SIZE], OVERWRITE_ARRAY_SIZE) == 0); + STBIR_ASSERT(memcmp(overwrite_tempmem_after_pre, &((unsigned char*)tempmem)[tempmem_size_in_bytes], OVERWRITE_ARRAY_SIZE) == 0); +#endif + + return 1; +} + + +static int stbir__resize_arbitrary( + void *alloc_context, + const void* input_data, int input_w, int input_h, int input_stride_in_bytes, + void* output_data, int output_w, int output_h, int output_stride_in_bytes, + float s0, float t0, float s1, float t1, float *transform, + int channels, int alpha_channel, stbir_uint32 flags, stbir_datatype type, + stbir_filter h_filter, stbir_filter v_filter, + stbir_edge edge_horizontal, stbir_edge edge_vertical, stbir_colorspace colorspace) +{ + stbir__info info; + int result; + size_t memory_required; + void* extra_memory; + + stbir__setup(&info, input_w, input_h, output_w, output_h, channels); + stbir__calculate_transform(&info, s0,t0,s1,t1,transform); + stbir__choose_filter(&info, h_filter, v_filter); + memory_required = stbir__calculate_memory(&info); + extra_memory = STBIR_MALLOC(memory_required, alloc_context); + + if (!extra_memory) + return 0; + + result = stbir__resize_allocated(&info, input_data, input_stride_in_bytes, + output_data, output_stride_in_bytes, + alpha_channel, flags, type, + edge_horizontal, edge_vertical, + colorspace, extra_memory, memory_required); + + STBIR_FREE(extra_memory, alloc_context); + + return result; +} + +STBIRDEF int stbir_resize_uint8( 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, + int num_channels) +{ + return stbir__resize_arbitrary(NULL, input_pixels, input_w, input_h, input_stride_in_bytes, + output_pixels, output_w, output_h, output_stride_in_bytes, + 0,0,1,1,NULL,num_channels,-1,0, STBIR_TYPE_UINT8, STBIR_FILTER_DEFAULT, STBIR_FILTER_DEFAULT, + STBIR_EDGE_CLAMP, STBIR_EDGE_CLAMP, STBIR_COLORSPACE_LINEAR); +} + +STBIRDEF int stbir_resize_float( 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, + int num_channels) +{ + return stbir__resize_arbitrary(NULL, input_pixels, input_w, input_h, input_stride_in_bytes, + output_pixels, output_w, output_h, output_stride_in_bytes, + 0,0,1,1,NULL,num_channels,-1,0, STBIR_TYPE_FLOAT, STBIR_FILTER_DEFAULT, STBIR_FILTER_DEFAULT, + STBIR_EDGE_CLAMP, STBIR_EDGE_CLAMP, STBIR_COLORSPACE_LINEAR); +} + +STBIRDEF int 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, + int num_channels, int alpha_channel, int flags) +{ + return stbir__resize_arbitrary(NULL, input_pixels, input_w, input_h, input_stride_in_bytes, + output_pixels, output_w, output_h, output_stride_in_bytes, + 0,0,1,1,NULL,num_channels,alpha_channel,flags, STBIR_TYPE_UINT8, STBIR_FILTER_DEFAULT, STBIR_FILTER_DEFAULT, + STBIR_EDGE_CLAMP, STBIR_EDGE_CLAMP, STBIR_COLORSPACE_SRGB); +} + +STBIRDEF int stbir_resize_uint8_srgb_edgemode(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, + int num_channels, int alpha_channel, int flags, + stbir_edge edge_wrap_mode) +{ + return stbir__resize_arbitrary(NULL, input_pixels, input_w, input_h, input_stride_in_bytes, + output_pixels, output_w, output_h, output_stride_in_bytes, + 0,0,1,1,NULL,num_channels,alpha_channel,flags, STBIR_TYPE_UINT8, STBIR_FILTER_DEFAULT, STBIR_FILTER_DEFAULT, + edge_wrap_mode, edge_wrap_mode, STBIR_COLORSPACE_SRGB); +} + +STBIRDEF int stbir_resize_uint8_generic( 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, + int num_channels, int alpha_channel, int flags, + stbir_edge edge_wrap_mode, stbir_filter filter, stbir_colorspace space, + void *alloc_context) +{ + return stbir__resize_arbitrary(alloc_context, input_pixels, input_w, input_h, input_stride_in_bytes, + output_pixels, output_w, output_h, output_stride_in_bytes, + 0,0,1,1,NULL,num_channels,alpha_channel,flags, STBIR_TYPE_UINT8, filter, filter, + edge_wrap_mode, edge_wrap_mode, space); +} + +STBIRDEF int stbir_resize_uint16_generic(const stbir_uint16 *input_pixels , int input_w , int input_h , int input_stride_in_bytes, + stbir_uint16 *output_pixels , int output_w, int output_h, int output_stride_in_bytes, + int num_channels, int alpha_channel, int flags, + stbir_edge edge_wrap_mode, stbir_filter filter, stbir_colorspace space, + void *alloc_context) +{ + return stbir__resize_arbitrary(alloc_context, input_pixels, input_w, input_h, input_stride_in_bytes, + output_pixels, output_w, output_h, output_stride_in_bytes, + 0,0,1,1,NULL,num_channels,alpha_channel,flags, STBIR_TYPE_UINT16, filter, filter, + edge_wrap_mode, edge_wrap_mode, space); +} + + +STBIRDEF int stbir_resize_float_generic( 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, + int num_channels, int alpha_channel, int flags, + stbir_edge edge_wrap_mode, stbir_filter filter, stbir_colorspace space, + void *alloc_context) +{ + return stbir__resize_arbitrary(alloc_context, input_pixels, input_w, input_h, input_stride_in_bytes, + output_pixels, output_w, output_h, output_stride_in_bytes, + 0,0,1,1,NULL,num_channels,alpha_channel,flags, STBIR_TYPE_FLOAT, filter, filter, + edge_wrap_mode, edge_wrap_mode, space); +} + + +STBIRDEF int 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_datatype datatype, + int num_channels, int alpha_channel, int flags, + stbir_edge edge_mode_horizontal, stbir_edge edge_mode_vertical, + stbir_filter filter_horizontal, stbir_filter filter_vertical, + stbir_colorspace space, void *alloc_context) +{ + return stbir__resize_arbitrary(alloc_context, input_pixels, input_w, input_h, input_stride_in_bytes, + output_pixels, output_w, output_h, output_stride_in_bytes, + 0,0,1,1,NULL,num_channels,alpha_channel,flags, datatype, filter_horizontal, filter_vertical, + edge_mode_horizontal, edge_mode_vertical, space); +} + + +STBIRDEF int stbir_resize_subpixel(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_datatype datatype, + int num_channels, int alpha_channel, int flags, + stbir_edge edge_mode_horizontal, stbir_edge edge_mode_vertical, + stbir_filter filter_horizontal, stbir_filter filter_vertical, + stbir_colorspace space, void *alloc_context, + float x_scale, float y_scale, + float x_offset, float y_offset) +{ + float transform[4]; + transform[0] = x_scale; + transform[1] = y_scale; + transform[2] = x_offset; + transform[3] = y_offset; + return stbir__resize_arbitrary(alloc_context, input_pixels, input_w, input_h, input_stride_in_bytes, + output_pixels, output_w, output_h, output_stride_in_bytes, + 0,0,1,1,transform,num_channels,alpha_channel,flags, datatype, filter_horizontal, filter_vertical, + edge_mode_horizontal, edge_mode_vertical, space); +} + +STBIRDEF int stbir_resize_region( 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_datatype datatype, + int num_channels, int alpha_channel, int flags, + stbir_edge edge_mode_horizontal, stbir_edge edge_mode_vertical, + stbir_filter filter_horizontal, stbir_filter filter_vertical, + stbir_colorspace space, void *alloc_context, + float s0, float t0, float s1, float t1) +{ + return stbir__resize_arbitrary(alloc_context, input_pixels, input_w, input_h, input_stride_in_bytes, + output_pixels, output_w, output_h, output_stride_in_bytes, + s0,t0,s1,t1,NULL,num_channels,alpha_channel,flags, datatype, filter_horizontal, filter_vertical, + edge_mode_horizontal, edge_mode_vertical, space); +} + +#endif // STB_IMAGE_RESIZE_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/tidy.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/tidy.h new file mode 100644 index 0000000000000000000000000000000000000000..0235636bf784aef9d8065a34b98c16448bc76a36 --- /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 0000000000000000000000000000000000000000..1c1b017df1e049f9a6da72f38c78054635a9ffea --- /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 0000000000000000000000000000000000000000..36407c1b0a1e7d4d3d38d2b7ff2e701c3f5ad218 --- /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 <br> 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 <![CDATA[]]> 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 <!CDATA[ ... ]]> 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 <?xml?> 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, /**< <!DOCTYPE html> */ + 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 <math> 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 0000000000000000000000000000000000000000..2fca4c413b493ffa4833ef6cb4e19508152444a7 --- /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 <ctype.h> +#include <stdio.h> +#include <setjmp.h> /* for longjmp on error exit */ +#include <stdlib.h> +#include <stdarg.h> /* may need <varargs.h> for Unix V */ +#include <string.h> +#include <assert.h> + +#ifdef NEEDS_MALLOC_H +# include <malloc.h> +#endif + +#ifdef SUPPORT_GETPWNAM +# include <pwd.h> +#endif + +#ifdef NEEDS_UNISTD_H +# include <unistd.h> /* 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 <utime.h> and the utime() function, or + * <sys/futime> and the futime() function then set PRESERVE_FILE_TIMES to 0. + * + * If your platform doesn't support <sys/utime.h> and the futime() function, + * then set HAS_FUTIME to 0. + * + * If your platform supports <utime.h> 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 <sys/types.h> +# include <sys/stat.h> +# else +# include <stat.h> +# endif + +# if HAS_FUTIME +# include <sys/utime.h> +# else +# include <utime.h> +# 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 <sys/types.h> +#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/types.h b/Plugins/CesiumForUnreal/Source/ThirdParty/include/types.h new file mode 100644 index 0000000000000000000000000000000000000000..47f7f2b007063fca173fdebd2486d7c0d7f77282 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/include/types.h @@ -0,0 +1,68 @@ +// Copyright 2010 Google Inc. All Rights Reserved. +// +// Use of this source code is governed by a BSD-style license +// that can be found in the COPYING file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. +// ----------------------------------------------------------------------------- +// +// Common types + memory wrappers +// +// Author: Skal (pascal.massimino@gmail.com) + +#ifndef WEBP_WEBP_TYPES_H_ +#define WEBP_WEBP_TYPES_H_ + +#include <stddef.h> // for size_t + +#ifndef _MSC_VER +#include <inttypes.h> +#if defined(__cplusplus) || !defined(__STRICT_ANSI__) || \ + (defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L) +#define WEBP_INLINE inline +#else +#define WEBP_INLINE +#endif +#else +typedef signed char int8_t; +typedef unsigned char uint8_t; +typedef signed short int16_t; +typedef unsigned short uint16_t; +typedef signed int int32_t; +typedef unsigned int uint32_t; +typedef unsigned long long int uint64_t; +typedef long long int int64_t; +#define WEBP_INLINE __forceinline +#endif /* _MSC_VER */ + +#ifndef WEBP_EXTERN +// This explicitly marks library functions and allows for changing the +// signature for e.g., Windows DLL builds. +# if defined(__GNUC__) && __GNUC__ >= 4 +# define WEBP_EXTERN extern __attribute__ ((visibility ("default"))) +# else +# define WEBP_EXTERN extern +# endif /* __GNUC__ >= 4 */ +#endif /* WEBP_EXTERN */ + +// Macro to check ABI compatibility (same major revision number) +#define WEBP_ABI_IS_INCOMPATIBLE(a, b) (((a) >> 8) != ((b) >> 8)) + +#ifdef __cplusplus +extern "C" { +#endif + +// Allocates 'size' bytes of memory. Returns NULL upon error. Memory +// must be deallocated by calling WebPFree(). This function is made available +// by the core 'libwebp' library. +WEBP_EXTERN void* WebPMalloc(size_t size); + +// Releases memory returned by the WebPDecode*() functions (from decode.h). +WEBP_EXTERN void WebPFree(void* ptr); + +#ifdef __cplusplus +} // extern "C" +#endif + +#endif // WEBP_WEBP_TYPES_H_ diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-xaarch64/libCesium3DTiles.a b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-xaarch64/libCesium3DTiles.a new file mode 100644 index 0000000000000000000000000000000000000000..29fb4ff29f261be288dbc2c3c558d48ecc604405 Binary files /dev/null and b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-xaarch64/libCesium3DTiles.a differ diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-xaarch64/libCesium3DTilesReader.a b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-xaarch64/libCesium3DTilesReader.a new file mode 100644 index 0000000000000000000000000000000000000000..7c4ca98256198504032c47ffeb97aa39f10d5a7a Binary files /dev/null and b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-xaarch64/libCesium3DTilesReader.a differ diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-xaarch64/libCesium3DTilesSelection.a b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-xaarch64/libCesium3DTilesSelection.a new file mode 100644 index 0000000000000000000000000000000000000000..9b8cbb1d567143ae87cc0a509335512988b9d5ce Binary files /dev/null and b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-xaarch64/libCesium3DTilesSelection.a differ diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-xaarch64/libCesium3DTilesWriter.a b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-xaarch64/libCesium3DTilesWriter.a new file mode 100644 index 0000000000000000000000000000000000000000..2d48dfb74887948adf557505fb57bb1d5613c79e Binary files /dev/null and b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-xaarch64/libCesium3DTilesWriter.a differ diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-xaarch64/libCesiumAsync.a b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-xaarch64/libCesiumAsync.a new file mode 100644 index 0000000000000000000000000000000000000000..327a76340148dd8663351eb3da40b4345dc953cd Binary files /dev/null and b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-xaarch64/libCesiumAsync.a differ diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-xaarch64/libCesiumGeometry.a b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-xaarch64/libCesiumGeometry.a new file mode 100644 index 0000000000000000000000000000000000000000..b5853c80a7d9d075010e994f35e0bab4601a9cdf Binary files /dev/null and b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-xaarch64/libCesiumGeometry.a differ diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-xaarch64/libCesiumGeospatial.a b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-xaarch64/libCesiumGeospatial.a new file mode 100644 index 0000000000000000000000000000000000000000..caecdee1eaa48b6b366604931b25d8fe9238703f Binary files /dev/null and b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-xaarch64/libCesiumGeospatial.a differ diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-xaarch64/libCesiumGltf.a b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-xaarch64/libCesiumGltf.a new file mode 100644 index 0000000000000000000000000000000000000000..a76ae9d9ca653c889f648d0e366f02262a83534b Binary files /dev/null and b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-xaarch64/libCesiumGltf.a differ diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-xaarch64/libCesiumGltfReader.a b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-xaarch64/libCesiumGltfReader.a new file mode 100644 index 0000000000000000000000000000000000000000..0ee4b4702b04932d7b2c62547177b7a0cf1a33da Binary files /dev/null and b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-xaarch64/libCesiumGltfReader.a differ diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-xaarch64/libCesiumGltfWriter.a b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-xaarch64/libCesiumGltfWriter.a new file mode 100644 index 0000000000000000000000000000000000000000..2792b9196776cda13a62653fa5e8dedaabf7612d Binary files /dev/null and b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-xaarch64/libCesiumGltfWriter.a differ diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-xaarch64/libCesiumIonClient.a b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-xaarch64/libCesiumIonClient.a new file mode 100644 index 0000000000000000000000000000000000000000..a77a2acdf34bd71ce38e4716537e2bb1821ab157 Binary files /dev/null and b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-xaarch64/libCesiumIonClient.a differ diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-xaarch64/libCesiumJsonReader.a b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-xaarch64/libCesiumJsonReader.a new file mode 100644 index 0000000000000000000000000000000000000000..4dc0d7ee77c41f3feb23bc4ab7d29b12a44987a6 Binary files /dev/null and b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-xaarch64/libCesiumJsonReader.a differ diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-xaarch64/libCesiumJsonWriter.a b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-xaarch64/libCesiumJsonWriter.a new file mode 100644 index 0000000000000000000000000000000000000000..d799a648392909478e960ac0ce6e1f55d0ef2cda Binary files /dev/null and b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-xaarch64/libCesiumJsonWriter.a differ diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-xaarch64/libCesiumUtility.a b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-xaarch64/libCesiumUtility.a new file mode 100644 index 0000000000000000000000000000000000000000..aa8ba75fa322472d58a445b304d1d8da5169424b Binary files /dev/null and b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-xaarch64/libCesiumUtility.a differ diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-xaarch64/libMikkTSpace.a b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-xaarch64/libMikkTSpace.a new file mode 100644 index 0000000000000000000000000000000000000000..5bd47c0550a48ce85befb7f3da194e3c8bf72d62 Binary files /dev/null and b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-xaarch64/libMikkTSpace.a differ diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-xaarch64/libasync++.a b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-xaarch64/libasync++.a new file mode 100644 index 0000000000000000000000000000000000000000..1b4e665424f9307a4b57363dac40ee52ae165c18 Binary files /dev/null and b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-xaarch64/libasync++.a differ diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-xaarch64/libcsprng.a b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-xaarch64/libcsprng.a new file mode 100644 index 0000000000000000000000000000000000000000..69cab053485813f1d6233498aad9b2072b517242 Binary files /dev/null and b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-xaarch64/libcsprng.a differ diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-xaarch64/libdraco.a b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-xaarch64/libdraco.a new file mode 100644 index 0000000000000000000000000000000000000000..0d55ed86236213b8cf06a5f69081176f9a6c0c64 Binary files /dev/null and b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-xaarch64/libdraco.a differ diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-xaarch64/libktx_read.a b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-xaarch64/libktx_read.a new file mode 100644 index 0000000000000000000000000000000000000000..932e5a61ad983ca8cc3dbd5c09c68f91f54b1e8a Binary files /dev/null and b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-xaarch64/libktx_read.a differ diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-xaarch64/libmodp_b64.a b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-xaarch64/libmodp_b64.a new file mode 100644 index 0000000000000000000000000000000000000000..cad34db6f8aad87673c137452b7a36b6d7ad8297 Binary files /dev/null and b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-xaarch64/libmodp_b64.a differ diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-xaarch64/libs2geometry.a b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-xaarch64/libs2geometry.a new file mode 100644 index 0000000000000000000000000000000000000000..63888b83ed007f12e001f7d6d8e4a44350236df9 Binary files /dev/null and b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-xaarch64/libs2geometry.a differ diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-xaarch64/libspdlog.a b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-xaarch64/libspdlog.a new file mode 100644 index 0000000000000000000000000000000000000000..bfede783c724007543eed8719f33e2549409bc7d Binary files /dev/null and b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-xaarch64/libspdlog.a differ diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-xaarch64/libsqlite3.a b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-xaarch64/libsqlite3.a new file mode 100644 index 0000000000000000000000000000000000000000..f0aaff3982c7f2e3e82a721a6cc6677c8a72d8d1 Binary files /dev/null and b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-xaarch64/libsqlite3.a differ diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-xaarch64/libtidy.a b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-xaarch64/libtidy.a new file mode 100644 index 0000000000000000000000000000000000000000..ee53fd6fb685874971613f62b67499a7a78bf286 Binary files /dev/null and b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-xaarch64/libtidy.a differ diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-xaarch64/libtinyxml2.a b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-xaarch64/libtinyxml2.a new file mode 100644 index 0000000000000000000000000000000000000000..574b4f998c7a16b6ae308dad7d9c2127ad3c2015 Binary files /dev/null and b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-xaarch64/libtinyxml2.a differ diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-xaarch64/liburiparser.a b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-xaarch64/liburiparser.a new file mode 100644 index 0000000000000000000000000000000000000000..8c6ab4149f0bb76e74f01cfafb26b905d0220598 Binary files /dev/null and b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-xaarch64/liburiparser.a differ diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-xaarch64/libwebpdecoder.a b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-xaarch64/libwebpdecoder.a new file mode 100644 index 0000000000000000000000000000000000000000..d29e138bc73da938ed608081cdef2eaa8f916ad2 Binary files /dev/null and b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-xaarch64/libwebpdecoder.a differ diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-xaarch64/pkgconfig/tidy.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-xaarch64/pkgconfig/tidy.pc new file mode 100644 index 0000000000000000000000000000000000000000..a27b336b25445c674d9c33c8afc297eb83826ab2 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Android-xaarch64/pkgconfig/tidy.pc @@ -0,0 +1,11 @@ +prefix=C:/actions-runner/_work/cesium-unreal/cesium-unreal/extern/../Source/ThirdParty +exec_prefix=${prefix} +libdir=${exec_prefix}/C:/actions-runner/_work/cesium-unreal/cesium-unreal/extern/../Source/ThirdParty/lib/Android-xaarch64 +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/Darwin-x64/libCesium3DTiles.a b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Darwin-x64/libCesium3DTiles.a new file mode 100644 index 0000000000000000000000000000000000000000..4110823062347ed607675e782b90adcc98b2bc4b Binary files /dev/null and b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Darwin-x64/libCesium3DTiles.a differ diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Darwin-x64/libCesium3DTilesReader.a b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Darwin-x64/libCesium3DTilesReader.a new file mode 100644 index 0000000000000000000000000000000000000000..9a4c4442aa4eef16a80009d95de782855f3742ce Binary files /dev/null and b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Darwin-x64/libCesium3DTilesReader.a differ diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Darwin-x64/libCesium3DTilesSelection.a b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Darwin-x64/libCesium3DTilesSelection.a new file mode 100644 index 0000000000000000000000000000000000000000..140507542650e58f9fa9a4de1b99ecda580c7095 Binary files /dev/null and b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Darwin-x64/libCesium3DTilesSelection.a differ diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Darwin-x64/libCesium3DTilesWriter.a b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Darwin-x64/libCesium3DTilesWriter.a new file mode 100644 index 0000000000000000000000000000000000000000..4c0f9d36ede9dcb4d72acd2f7a76c6a5ebbf60f2 Binary files /dev/null and b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Darwin-x64/libCesium3DTilesWriter.a differ diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Darwin-x64/libCesiumAsync.a b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Darwin-x64/libCesiumAsync.a new file mode 100644 index 0000000000000000000000000000000000000000..6b56d9bf201f5e2ed09d74a01f52ad25d751d6d6 Binary files /dev/null and b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Darwin-x64/libCesiumAsync.a differ diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Darwin-x64/libCesiumGeometry.a b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Darwin-x64/libCesiumGeometry.a new file mode 100644 index 0000000000000000000000000000000000000000..769ea80afbdb5ad4d6e5226dddc744d09ad6c477 Binary files /dev/null and b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Darwin-x64/libCesiumGeometry.a differ diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Darwin-x64/libCesiumGeospatial.a b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Darwin-x64/libCesiumGeospatial.a new file mode 100644 index 0000000000000000000000000000000000000000..025366f9b4af15ba2cd597e4b368b51b3c6895fc Binary files /dev/null and b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Darwin-x64/libCesiumGeospatial.a differ diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Darwin-x64/libCesiumGltf.a b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Darwin-x64/libCesiumGltf.a new file mode 100644 index 0000000000000000000000000000000000000000..d325f65c3042bc0d4d463627da7b21d1bd590c8d Binary files /dev/null and b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Darwin-x64/libCesiumGltf.a differ diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Darwin-x64/libCesiumGltfReader.a b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Darwin-x64/libCesiumGltfReader.a new file mode 100644 index 0000000000000000000000000000000000000000..d1263b27ee75582f18bc9224eb2cc343d5769160 Binary files /dev/null and b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Darwin-x64/libCesiumGltfReader.a differ diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Darwin-x64/libCesiumGltfWriter.a b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Darwin-x64/libCesiumGltfWriter.a new file mode 100644 index 0000000000000000000000000000000000000000..c4ace0c3bd854d8fa788dbe692609c453ea945af Binary files /dev/null and b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Darwin-x64/libCesiumGltfWriter.a differ diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Darwin-x64/libCesiumIonClient.a b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Darwin-x64/libCesiumIonClient.a new file mode 100644 index 0000000000000000000000000000000000000000..1e0281296df2e606216a614d6574cf9dbc2f8c4f Binary files /dev/null and b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Darwin-x64/libCesiumIonClient.a differ diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Darwin-x64/libCesiumJsonReader.a b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Darwin-x64/libCesiumJsonReader.a new file mode 100644 index 0000000000000000000000000000000000000000..92c177c6066640d0a22fc606959d5a36ff3b975e Binary files /dev/null and b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Darwin-x64/libCesiumJsonReader.a differ diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Darwin-x64/libCesiumJsonWriter.a b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Darwin-x64/libCesiumJsonWriter.a new file mode 100644 index 0000000000000000000000000000000000000000..600c7501ecc97c408ae07154d89f2fe9dbdae314 Binary files /dev/null and b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Darwin-x64/libCesiumJsonWriter.a differ diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Darwin-x64/libCesiumUtility.a b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Darwin-x64/libCesiumUtility.a new file mode 100644 index 0000000000000000000000000000000000000000..5205d823f832862645896871598d6c48d9d518d0 Binary files /dev/null and b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Darwin-x64/libCesiumUtility.a differ diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Darwin-x64/libasync++.a b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Darwin-x64/libasync++.a new file mode 100644 index 0000000000000000000000000000000000000000..85613bbb796bcf762b9f3b1dac1c4b727ae85dfd Binary files /dev/null and b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Darwin-x64/libasync++.a differ diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Darwin-x64/libcsprng.a b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Darwin-x64/libcsprng.a new file mode 100644 index 0000000000000000000000000000000000000000..183b7df67bc6eafc72f425e43e89e02d86d50cfd Binary files /dev/null and b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Darwin-x64/libcsprng.a differ diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Darwin-x64/libdraco.a b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Darwin-x64/libdraco.a new file mode 100644 index 0000000000000000000000000000000000000000..3f3afec5f2b88d5aff82927a2c55e692b1c5ce0c Binary files /dev/null and b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Darwin-x64/libdraco.a differ diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Darwin-x64/libktx_read.a b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Darwin-x64/libktx_read.a new file mode 100644 index 0000000000000000000000000000000000000000..f944764dc9d7611a4e9d9f49fb16ff4cc53e1d89 Binary files /dev/null and b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Darwin-x64/libktx_read.a differ diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Darwin-x64/libmodp_b64.a b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Darwin-x64/libmodp_b64.a new file mode 100644 index 0000000000000000000000000000000000000000..afbc1dd6394cfa5ce2481ea0308a7a42dd541e2e Binary files /dev/null and b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Darwin-x64/libmodp_b64.a differ diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Darwin-x64/libs2geometry.a b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Darwin-x64/libs2geometry.a new file mode 100644 index 0000000000000000000000000000000000000000..7774107e6022253f19ac48e5355b95397836fcd8 Binary files /dev/null and b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Darwin-x64/libs2geometry.a differ diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Darwin-x64/libspdlog.a b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Darwin-x64/libspdlog.a new file mode 100644 index 0000000000000000000000000000000000000000..6c1d559cafc1c4da856a641f2289db932e81eb38 Binary files /dev/null and b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Darwin-x64/libspdlog.a differ diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Darwin-x64/libsqlite3.a b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Darwin-x64/libsqlite3.a new file mode 100644 index 0000000000000000000000000000000000000000..9ed5dedc550b3b081fb0260ca8b70c7742e2ade6 Binary files /dev/null and b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Darwin-x64/libsqlite3.a differ diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Darwin-x64/libtidy.a b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Darwin-x64/libtidy.a new file mode 100644 index 0000000000000000000000000000000000000000..3e422aaeb9391c0971f838e4dccb61af2230eeb4 Binary files /dev/null and b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Darwin-x64/libtidy.a differ diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Darwin-x64/libtinyxml2.a b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Darwin-x64/libtinyxml2.a new file mode 100644 index 0000000000000000000000000000000000000000..de5fe4d5c7cd60ff67adec0762405d4b6534d204 Binary files /dev/null and b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Darwin-x64/libtinyxml2.a differ diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Darwin-x64/liburiparser.a b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Darwin-x64/liburiparser.a new file mode 100644 index 0000000000000000000000000000000000000000..fb334adb7a1a1e8feb5a9a451b73c4195de7fef0 Binary files /dev/null and b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Darwin-x64/liburiparser.a differ diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Darwin-x64/libwebpdecoder.a b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Darwin-x64/libwebpdecoder.a new file mode 100644 index 0000000000000000000000000000000000000000..41a859e1f5521637bad1aafa7d0d7a680ef5e715 Binary files /dev/null and b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Darwin-x64/libwebpdecoder.a differ diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Darwin-x64/pkgconfig/tidy.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Darwin-x64/pkgconfig/tidy.pc new file mode 100644 index 0000000000000000000000000000000000000000..e23fa8c510d9f5b7182bb3960cf5a00b64b9b8eb --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Darwin-x64/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/Darwin-x64 +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-x64/libCesium3DTiles.a b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x64/libCesium3DTiles.a new file mode 100644 index 0000000000000000000000000000000000000000..f57c4b9fb0e0fabccb5f005224f832e59fe50eee Binary files /dev/null and b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x64/libCesium3DTiles.a differ diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x64/libCesium3DTilesReader.a b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x64/libCesium3DTilesReader.a new file mode 100644 index 0000000000000000000000000000000000000000..66b4b83f0e181cc3dbf39a923020a736256b333c Binary files /dev/null and b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x64/libCesium3DTilesReader.a differ diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x64/libCesium3DTilesSelection.a b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x64/libCesium3DTilesSelection.a new file mode 100644 index 0000000000000000000000000000000000000000..f2f8625b0ea51b87909f865a22e1f7991e222f2a Binary files /dev/null and b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x64/libCesium3DTilesSelection.a differ diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x64/libCesium3DTilesWriter.a b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x64/libCesium3DTilesWriter.a new file mode 100644 index 0000000000000000000000000000000000000000..4d17716886e8898f68a4c063ad785b0b964acc57 Binary files /dev/null and b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x64/libCesium3DTilesWriter.a differ diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x64/libCesiumAsync.a b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x64/libCesiumAsync.a new file mode 100644 index 0000000000000000000000000000000000000000..281f285954a5d0b037a5fade468638617c87409c Binary files /dev/null and b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x64/libCesiumAsync.a differ diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x64/libCesiumGeometry.a b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x64/libCesiumGeometry.a new file mode 100644 index 0000000000000000000000000000000000000000..f2b491aede33f3a8443957b790cef5bc028c7dc1 Binary files /dev/null and b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x64/libCesiumGeometry.a differ diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x64/libCesiumGeospatial.a b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x64/libCesiumGeospatial.a new file mode 100644 index 0000000000000000000000000000000000000000..5f8bc0899964cda29d2888560c00e719cca3d740 Binary files /dev/null and b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x64/libCesiumGeospatial.a differ diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x64/libCesiumGltf.a b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x64/libCesiumGltf.a new file mode 100644 index 0000000000000000000000000000000000000000..79fb875985382c8b84b5e2b6563af5c7788c162c Binary files /dev/null and b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x64/libCesiumGltf.a differ diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x64/libCesiumGltfReader.a b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x64/libCesiumGltfReader.a new file mode 100644 index 0000000000000000000000000000000000000000..a177ded9f4e62a0e5c6f31c030583c9e119fd2d0 Binary files /dev/null and b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x64/libCesiumGltfReader.a differ diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x64/libCesiumGltfWriter.a b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x64/libCesiumGltfWriter.a new file mode 100644 index 0000000000000000000000000000000000000000..26207390abe812f96ecaed86838e98cf5f8b0d3f Binary files /dev/null and b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x64/libCesiumGltfWriter.a differ diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x64/libCesiumIonClient.a b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x64/libCesiumIonClient.a new file mode 100644 index 0000000000000000000000000000000000000000..d006e3b2576bbbbb9b46d1617e88d9e6696752d0 Binary files /dev/null and b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x64/libCesiumIonClient.a differ diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x64/libCesiumJsonReader.a b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x64/libCesiumJsonReader.a new file mode 100644 index 0000000000000000000000000000000000000000..e4aee38353d2b93573fe0cb14f2aa38ac0dbad22 Binary files /dev/null and b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x64/libCesiumJsonReader.a differ diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x64/libCesiumJsonWriter.a b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x64/libCesiumJsonWriter.a new file mode 100644 index 0000000000000000000000000000000000000000..3c64baab193cac2fa0c5c9124bbab21d10112972 Binary files /dev/null and b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x64/libCesiumJsonWriter.a differ diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x64/libCesiumUtility.a b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x64/libCesiumUtility.a new file mode 100644 index 0000000000000000000000000000000000000000..f6ce2242aa5d4a5a78d18cb59d7b9850f9d3d48a Binary files /dev/null and b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x64/libCesiumUtility.a differ diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x64/libasync++.a b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x64/libasync++.a new file mode 100644 index 0000000000000000000000000000000000000000..abfbfd4f88c5b9d426ed1f958e0d16fa6bdaa365 Binary files /dev/null and b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x64/libasync++.a differ diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x64/libcsprng.a b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x64/libcsprng.a new file mode 100644 index 0000000000000000000000000000000000000000..aa19428a7d20a9d08b5748040a168dc0d9da39d4 Binary files /dev/null and b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x64/libcsprng.a differ diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x64/libdraco.a b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x64/libdraco.a new file mode 100644 index 0000000000000000000000000000000000000000..ddac7dec17d0fde634562e4cee604dd5f6e2891d Binary files /dev/null and b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x64/libdraco.a differ diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x64/libktx_read.a b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x64/libktx_read.a new file mode 100644 index 0000000000000000000000000000000000000000..d4f85a3b72539319453b387665f30f8d4f1da5ed Binary files /dev/null and b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x64/libktx_read.a differ diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x64/libmodp_b64.a b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x64/libmodp_b64.a new file mode 100644 index 0000000000000000000000000000000000000000..5cf9ebeb917ba32ed4bc79f71a06b9a7378e16bc Binary files /dev/null and b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x64/libmodp_b64.a differ diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x64/libs2geometry.a b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x64/libs2geometry.a new file mode 100644 index 0000000000000000000000000000000000000000..18ad21e7fca3c57ccde19a506b5a994cf8bd1104 Binary files /dev/null and b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x64/libs2geometry.a differ diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x64/libspdlog.a b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x64/libspdlog.a new file mode 100644 index 0000000000000000000000000000000000000000..4d3fbdd68e8130c75b7df6d1a897af645cf917d0 Binary files /dev/null and b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x64/libspdlog.a differ diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x64/libsqlite3.a b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x64/libsqlite3.a new file mode 100644 index 0000000000000000000000000000000000000000..8ddee88593f5e2c8ba2c0cee01844aa5a637074e Binary files /dev/null and b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x64/libsqlite3.a differ diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x64/libtidy.a b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x64/libtidy.a new file mode 100644 index 0000000000000000000000000000000000000000..747aaf856cbff2f375d0458027c9cec83b11f347 Binary files /dev/null and b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x64/libtidy.a differ diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x64/libtinyxml2.a b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x64/libtinyxml2.a new file mode 100644 index 0000000000000000000000000000000000000000..00f96f1522cf699d551789cd7f58b780999ccaf3 Binary files /dev/null and b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x64/libtinyxml2.a differ diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x64/liburiparser.a b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x64/liburiparser.a new file mode 100644 index 0000000000000000000000000000000000000000..e257bf3f753ffe50750819a6173db2aae6b1c42e Binary files /dev/null and b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x64/liburiparser.a differ diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x64/libwebpdecoder.a b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x64/libwebpdecoder.a new file mode 100644 index 0000000000000000000000000000000000000000..ff33d774e7315ef70568f189e9dee568a01d4143 Binary files /dev/null and b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x64/libwebpdecoder.a differ diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x64/pkgconfig/tidy.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x64/pkgconfig/tidy.pc new file mode 100644 index 0000000000000000000000000000000000000000..320721a4e95cfa4333dbcd8409a0a5b72d4cb297 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Linux-x64/pkgconfig/tidy.pc @@ -0,0 +1,11 @@ +prefix=C:/actions-runner/_work/cesium-unreal/cesium-unreal/extern/../Source/ThirdParty +exec_prefix=${prefix} +libdir=${exec_prefix}/C:/actions-runner/_work/cesium-unreal/cesium-unreal/extern/../Source/ThirdParty/lib/Linux-x64 +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-x64/Cesium3DTiles.lib b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-x64/Cesium3DTiles.lib new file mode 100644 index 0000000000000000000000000000000000000000..12c67dc8df405e35e21a39a11d90a82617f39c68 Binary files /dev/null and b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-x64/Cesium3DTiles.lib differ diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-x64/Cesium3DTilesReader.lib b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-x64/Cesium3DTilesReader.lib new file mode 100644 index 0000000000000000000000000000000000000000..ca6f05692509ad2dcbf49b70b2d6a00308032c34 Binary files /dev/null and b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-x64/Cesium3DTilesReader.lib differ diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-x64/Cesium3DTilesSelection.lib b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-x64/Cesium3DTilesSelection.lib new file mode 100644 index 0000000000000000000000000000000000000000..61acd9314ed6e09ac2978475eabaf7be992d56f6 Binary files /dev/null and b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-x64/Cesium3DTilesSelection.lib differ diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-x64/Cesium3DTilesWriter.lib b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-x64/Cesium3DTilesWriter.lib new file mode 100644 index 0000000000000000000000000000000000000000..b516c4df7b31664c4b3bd6884338c837e5276781 Binary files /dev/null and b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-x64/Cesium3DTilesWriter.lib differ diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-x64/CesiumAsync.lib b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-x64/CesiumAsync.lib new file mode 100644 index 0000000000000000000000000000000000000000..ee6f6f705fb0e64d86b400421dca22841d8f7478 Binary files /dev/null and b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-x64/CesiumAsync.lib differ diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-x64/CesiumGeometry.lib b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-x64/CesiumGeometry.lib new file mode 100644 index 0000000000000000000000000000000000000000..a624338d6e175061d8293ea8c752f2d079d066cc Binary files /dev/null and b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-x64/CesiumGeometry.lib differ diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-x64/CesiumGeospatial.lib b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-x64/CesiumGeospatial.lib new file mode 100644 index 0000000000000000000000000000000000000000..ed9e6728b68c16e72486021d7df2c1a57871ae8a Binary files /dev/null and b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-x64/CesiumGeospatial.lib differ diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-x64/CesiumGltf.lib b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-x64/CesiumGltf.lib new file mode 100644 index 0000000000000000000000000000000000000000..e264c091b02ed3dfc409158f0044290f6e052878 Binary files /dev/null and b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-x64/CesiumGltf.lib differ diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-x64/CesiumGltfReader.lib b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-x64/CesiumGltfReader.lib new file mode 100644 index 0000000000000000000000000000000000000000..f448c5aa099906865568eec88ea46cc45ed1068e Binary files /dev/null and b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-x64/CesiumGltfReader.lib differ diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-x64/CesiumGltfWriter.lib b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-x64/CesiumGltfWriter.lib new file mode 100644 index 0000000000000000000000000000000000000000..112b77ac9350f02c4a118c0e58726fc35f586908 Binary files /dev/null and b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-x64/CesiumGltfWriter.lib differ diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-x64/CesiumIonClient.lib b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-x64/CesiumIonClient.lib new file mode 100644 index 0000000000000000000000000000000000000000..f3e1a6d992e5adbfc584c349f21b41985ce528c8 Binary files /dev/null and b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-x64/CesiumIonClient.lib differ diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-x64/CesiumJsonReader.lib b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-x64/CesiumJsonReader.lib new file mode 100644 index 0000000000000000000000000000000000000000..0e5f9021503c6ed9d9673dde3176c73720c4d550 Binary files /dev/null and b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-x64/CesiumJsonReader.lib differ diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-x64/CesiumJsonWriter.lib b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-x64/CesiumJsonWriter.lib new file mode 100644 index 0000000000000000000000000000000000000000..2850778fe89a1b849f0b21248176989257d3883a Binary files /dev/null and b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-x64/CesiumJsonWriter.lib differ diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-x64/CesiumUtility.lib b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-x64/CesiumUtility.lib new file mode 100644 index 0000000000000000000000000000000000000000..9b4a3e69b84b1e3d098a737c92761573eed22842 Binary files /dev/null and b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-x64/CesiumUtility.lib differ diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-x64/async++.lib b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-x64/async++.lib new file mode 100644 index 0000000000000000000000000000000000000000..434d8ecdf45744eea51ced48db49d82cf323de6b Binary files /dev/null and b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-x64/async++.lib differ diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-x64/csprng.lib b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-x64/csprng.lib new file mode 100644 index 0000000000000000000000000000000000000000..6520777120ca054bab66ceec565183ef0be41afa Binary files /dev/null and b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-x64/csprng.lib differ diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-x64/draco.lib b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-x64/draco.lib new file mode 100644 index 0000000000000000000000000000000000000000..30a08c581eb98803fec2003de30239bcbb99f621 Binary files /dev/null and b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-x64/draco.lib differ diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-x64/ktx_read.lib b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-x64/ktx_read.lib new file mode 100644 index 0000000000000000000000000000000000000000..a35760e3561dfadac2437ff5571954937ecceda4 Binary files /dev/null and b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-x64/ktx_read.lib differ diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-x64/modp_b64.lib b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-x64/modp_b64.lib new file mode 100644 index 0000000000000000000000000000000000000000..d41ba9d976a6e254dbbb2ae524b7d4f9d46b94b2 Binary files /dev/null and b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-x64/modp_b64.lib differ diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-x64/pkgconfig/tidy.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-x64/pkgconfig/tidy.pc new file mode 100644 index 0000000000000000000000000000000000000000..0bcfe2cd3bc003353282676ab34dbf5784eca64c --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-x64/pkgconfig/tidy.pc @@ -0,0 +1,11 @@ +prefix=C:/actions-runner/_work/cesium-unreal/cesium-unreal/extern/../Source/ThirdParty +exec_prefix=${prefix} +libdir=${exec_prefix}/C:/actions-runner/_work/cesium-unreal/cesium-unreal/extern/../Source/ThirdParty/lib/Windows-x64 +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-x64/s2geometry.lib b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-x64/s2geometry.lib new file mode 100644 index 0000000000000000000000000000000000000000..7e08ca03f68dc032ddc2acea27751942cb62bf3c Binary files /dev/null and b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-x64/s2geometry.lib differ diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-x64/spdlog.lib b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-x64/spdlog.lib new file mode 100644 index 0000000000000000000000000000000000000000..cb204efd78c83ff284bc3396707743a599e896db Binary files /dev/null and b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-x64/spdlog.lib differ diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-x64/sqlite3.lib b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-x64/sqlite3.lib new file mode 100644 index 0000000000000000000000000000000000000000..f3e540cb20d3634483658e66ddfd1a39cf4c7181 Binary files /dev/null and b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-x64/sqlite3.lib differ diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-x64/tidy_static.lib b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-x64/tidy_static.lib new file mode 100644 index 0000000000000000000000000000000000000000..70d470b4579e3b194d1f774641549e7bcf2bdbe8 Binary files /dev/null and b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-x64/tidy_static.lib differ diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-x64/tinyxml2.lib b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-x64/tinyxml2.lib new file mode 100644 index 0000000000000000000000000000000000000000..7c7abe9e053b24183fea7e05ee655c0ba942bd8d Binary files /dev/null and b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-x64/tinyxml2.lib differ diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-x64/uriparser.lib b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-x64/uriparser.lib new file mode 100644 index 0000000000000000000000000000000000000000..2fabbea5e5501e2be0314bc7224ed2b69c45efae Binary files /dev/null and b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-x64/uriparser.lib differ diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-x64/webpdecoder.lib b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-x64/webpdecoder.lib new file mode 100644 index 0000000000000000000000000000000000000000..d0028d7e5d3481acea7d3094929ca1e15a541433 Binary files /dev/null and b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/Windows-x64/webpdecoder.lib differ diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-xarm64/libCesium3DTiles.a b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-xarm64/libCesium3DTiles.a new file mode 100644 index 0000000000000000000000000000000000000000..cd365bec3b04cd03d7ec09a654321bee52c4cada Binary files /dev/null and b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-xarm64/libCesium3DTiles.a differ diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-xarm64/libCesium3DTilesReader.a b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-xarm64/libCesium3DTilesReader.a new file mode 100644 index 0000000000000000000000000000000000000000..30d3a257d808e59c0871ea745efe9c4e24211985 Binary files /dev/null and b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-xarm64/libCesium3DTilesReader.a differ diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-xarm64/libCesium3DTilesSelection.a b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-xarm64/libCesium3DTilesSelection.a new file mode 100644 index 0000000000000000000000000000000000000000..2ed1311f48c4d38c46e00e52bbdf1ef1fa9a5492 Binary files /dev/null and b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-xarm64/libCesium3DTilesSelection.a differ diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-xarm64/libCesium3DTilesWriter.a b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-xarm64/libCesium3DTilesWriter.a new file mode 100644 index 0000000000000000000000000000000000000000..33300bd6f7e41a55224dfd2d27faebee56648df1 Binary files /dev/null and b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-xarm64/libCesium3DTilesWriter.a differ diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-xarm64/libCesiumAsync.a b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-xarm64/libCesiumAsync.a new file mode 100644 index 0000000000000000000000000000000000000000..23098166ffc20ec9a1ce3d5d540887799678580d Binary files /dev/null and b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-xarm64/libCesiumAsync.a differ diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-xarm64/libCesiumGeometry.a b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-xarm64/libCesiumGeometry.a new file mode 100644 index 0000000000000000000000000000000000000000..3750131fd14e21d685ae313c8a863d074e58eaba Binary files /dev/null and b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-xarm64/libCesiumGeometry.a differ diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-xarm64/libCesiumGeospatial.a b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-xarm64/libCesiumGeospatial.a new file mode 100644 index 0000000000000000000000000000000000000000..756a8aa339d271c1f13763996f573108a5f56ded Binary files /dev/null and b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-xarm64/libCesiumGeospatial.a differ diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-xarm64/libCesiumGltf.a b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-xarm64/libCesiumGltf.a new file mode 100644 index 0000000000000000000000000000000000000000..78f4ac97899c5e8716c98b6ec2bf76bc656a1d48 Binary files /dev/null and b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-xarm64/libCesiumGltf.a differ diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-xarm64/libCesiumGltfReader.a b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-xarm64/libCesiumGltfReader.a new file mode 100644 index 0000000000000000000000000000000000000000..40654a451edf11f0d50d99b2eb850f28d2d52239 Binary files /dev/null and b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-xarm64/libCesiumGltfReader.a differ diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-xarm64/libCesiumGltfWriter.a b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-xarm64/libCesiumGltfWriter.a new file mode 100644 index 0000000000000000000000000000000000000000..61cb3f7e9fdff8061bb175a00e90ce60b67b82d3 Binary files /dev/null and b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-xarm64/libCesiumGltfWriter.a differ diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-xarm64/libCesiumIonClient.a b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-xarm64/libCesiumIonClient.a new file mode 100644 index 0000000000000000000000000000000000000000..43d0e8050a5a57b7978d5ad3dccae0d188140f6d Binary files /dev/null and b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-xarm64/libCesiumIonClient.a differ diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-xarm64/libCesiumJsonReader.a b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-xarm64/libCesiumJsonReader.a new file mode 100644 index 0000000000000000000000000000000000000000..26c179f35e8dc7a1218e5c27ce5dfb662e929f1a Binary files /dev/null and b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-xarm64/libCesiumJsonReader.a differ diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-xarm64/libCesiumJsonWriter.a b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-xarm64/libCesiumJsonWriter.a new file mode 100644 index 0000000000000000000000000000000000000000..23a66f8cab8dd77412b96436fb77b3bcccf5d382 Binary files /dev/null and b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-xarm64/libCesiumJsonWriter.a differ diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-xarm64/libCesiumUtility.a b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-xarm64/libCesiumUtility.a new file mode 100644 index 0000000000000000000000000000000000000000..3134c5e4d177ced9c1e1509a0d0fff33fd82ea7f Binary files /dev/null and b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-xarm64/libCesiumUtility.a differ diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-xarm64/libMikkTSpace.a b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-xarm64/libMikkTSpace.a new file mode 100644 index 0000000000000000000000000000000000000000..c1bdd876075cfdb7cdcdef6e33f3f61f5aba1484 Binary files /dev/null and b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-xarm64/libMikkTSpace.a differ diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-xarm64/libasync++.a b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-xarm64/libasync++.a new file mode 100644 index 0000000000000000000000000000000000000000..eba9daeee446f9e2f83e46e049ecf05a2b2941b1 Binary files /dev/null and b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-xarm64/libasync++.a differ diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-xarm64/libcsprng.a b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-xarm64/libcsprng.a new file mode 100644 index 0000000000000000000000000000000000000000..441a33dc951963d638d20860a9d0ce44238c8dbc Binary files /dev/null and b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-xarm64/libcsprng.a differ diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-xarm64/libdraco.a b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-xarm64/libdraco.a new file mode 100644 index 0000000000000000000000000000000000000000..02780b5825686508b0628a0aaa29b123320063b7 Binary files /dev/null and b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-xarm64/libdraco.a differ diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-xarm64/libktx_read.a b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-xarm64/libktx_read.a new file mode 100644 index 0000000000000000000000000000000000000000..5fb2648d6f783620af0113ff54dd80c65a54bf3f Binary files /dev/null and b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-xarm64/libktx_read.a differ diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-xarm64/libmodp_b64.a b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-xarm64/libmodp_b64.a new file mode 100644 index 0000000000000000000000000000000000000000..fda9780623f2d7ac691276b4aacc812ec3c03455 Binary files /dev/null and b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-xarm64/libmodp_b64.a differ diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-xarm64/libs2geometry.a b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-xarm64/libs2geometry.a new file mode 100644 index 0000000000000000000000000000000000000000..853c3e2ff1bd8660de6f859147a6bd3ed4534bf6 Binary files /dev/null and b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-xarm64/libs2geometry.a differ diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-xarm64/libspdlog.a b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-xarm64/libspdlog.a new file mode 100644 index 0000000000000000000000000000000000000000..3729174815b74a6c5b98344ce5d077e4ef1f60a9 Binary files /dev/null and b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-xarm64/libspdlog.a differ diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-xarm64/libsqlite3.a b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-xarm64/libsqlite3.a new file mode 100644 index 0000000000000000000000000000000000000000..151008c2649a0d679b7520ac72c55fb49fc9d7f9 Binary files /dev/null and b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-xarm64/libsqlite3.a differ diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-xarm64/libtidy.a b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-xarm64/libtidy.a new file mode 100644 index 0000000000000000000000000000000000000000..ceb2e12707227327205041e0a77820f705b72a0d Binary files /dev/null and b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-xarm64/libtidy.a differ diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-xarm64/libtinyxml2.a b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-xarm64/libtinyxml2.a new file mode 100644 index 0000000000000000000000000000000000000000..76fe341565f056191eddf5a75929c6faf43be07f Binary files /dev/null and b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-xarm64/libtinyxml2.a differ diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-xarm64/liburiparser.a b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-xarm64/liburiparser.a new file mode 100644 index 0000000000000000000000000000000000000000..791e9da2197af140c4185a4b53f54227b478af6b Binary files /dev/null and b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-xarm64/liburiparser.a differ diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-xarm64/libwebpdecoder.a b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-xarm64/libwebpdecoder.a new file mode 100644 index 0000000000000000000000000000000000000000..71c65923346a35da5dbc3511628284bef63215e4 Binary files /dev/null and b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-xarm64/libwebpdecoder.a differ diff --git a/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-xarm64/pkgconfig/tidy.pc b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-xarm64/pkgconfig/tidy.pc new file mode 100644 index 0000000000000000000000000000000000000000..df20b63f04504f14cc5a433167c61b490b12a911 --- /dev/null +++ b/Plugins/CesiumForUnreal/Source/ThirdParty/lib/iOS-xarm64/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-xarm64 +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/ThirdParty.json b/Plugins/CesiumForUnreal/ThirdParty.json new file mode 100644 index 0000000000000000000000000000000000000000..c22712de1213a6d9341a53b8a78b7919caece14e --- /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"] + } +]