Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,9 @@ Additionally the repository includes a command line tool that uses these steps i

## Features
The current release includes code for:
- Packing PBR material textures using [DirectXTex](http://github.com/Microsoft/DirectXTex) for use with the [MSFT_packing_occlusionRoughnessMetallic](https://github.com/sbtron/glTF/tree/MSFT_lod/extensions/Vendor/MSFT_packing_occlusionRoughnessMetallic) extension.
- Compressing textures as BC3, BC5 and BC7 and generate mip maps using [DirectXTex](http://github.com/Microsoft/DirectXTex) for use with the [MSFT_texture_dds](https://github.com/sbtron/glTF/tree/MSFT_lod/extensions/Vendor/MSFT_texture_dds) extension.
- Merging multiple glTF assets into a asset with multiple levels of detail using the [MSFT_lod](https://github.com/sbtron/glTF/tree/MSFT_lod/extensions/Vendor/MSFT_lod) extension.
- Packing PBR material textures using [DirectXTex](http://github.com/Microsoft/DirectXTex) for use with the [MSFT_packing_occlusionRoughnessMetallic](https://github.com/KhronosGroup/glTF/tree/master/extensions/2.0/Vendor/MSFT_packing_occlusionRoughnessMetallic) and [MSFT_packing_normalRoughnessMetallic](https://github.com/KhronosGroup/glTF/tree/master/extensions/2.0/Vendor/MSFT_packing_normalRoughnessMetallic) extensions.
- Compressing textures as BC3, BC5 and BC7 and generate mip maps using [DirectXTex](http://github.com/Microsoft/DirectXTex) for use with the [MSFT_texture_dds](https://github.com/KhronosGroup/glTF/tree/master/extensions/2.0/Vendor/MSFT_texture_dds) extension.
- Merging multiple glTF assets into a asset with multiple levels of detail using the [MSFT_lod](https://github.com/KhronosGroup/glTF/tree/master/extensions/2.0/Vendor/MSFT_lod) extension.
- A command line tool that combines these components to create optimized glTF assets for the Windows Mixed Reality Home
- A UWP compatible Windows Runtime component to perform conversions between GLTF and GLB, as well as optimize assets for Windows Mixed Reality at runtime

Expand Down
87 changes: 82 additions & 5 deletions WindowsMRAssetConverter/CommandLine.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -12,10 +12,25 @@ const wchar_t * PARAM_LOD = L"-lod";
const wchar_t * PARAM_SCREENCOVERAGE = L"-screen-coverage";
const wchar_t * PARAM_MAXTEXTURESIZE = L"-max-texture-size";
const wchar_t * PARAM_SHARE_MATERIALS = L"-share-materials";
const wchar_t * PARAM_MIN_VERSION = L"-min-version";
const wchar_t * PARAM_PLATFORM = L"-platform";
const wchar_t * PARAM_REPLACE_TEXTURES = L"-replace-textures";
const wchar_t * PARAM_VALUE_VERSION_1709 = L"1709";
const wchar_t * PARAM_VALUE_VERSION_1803 = L"1803";
const wchar_t * PARAM_VALUE_VERSION_RS3 = L"rs3";
const wchar_t * PARAM_VALUE_VERSION_RS4 = L"rs4";
const wchar_t * PARAM_VALUE_VERSION_LATEST = L"latest";
const wchar_t * PARAM_VALUE_HOLOGRAPHIC = L"holographic";
const wchar_t * PARAM_VALUE_HOLOLENS= L"hololens";
const wchar_t * PARAM_VALUE_DESKTOP = L"desktop";
const wchar_t * PARAM_VALUE_PC = L"pc";
const wchar_t * PARAM_VALUE_ALL = L"all";
const wchar_t * SUFFIX_CONVERTED = L"_converted";
const wchar_t * CLI_INDENT = L" ";
const size_t MAXTEXTURESIZE_DEFAULT = 512;
const size_t MAXTEXTURESIZE_MAX = 4096;
const CommandLine::Version MIN_VERSION_DEFAULT = CommandLine::Version::Version1709;
const CommandLine::Platform PLATFORM_DEFAULT = CommandLine::Platform::Desktop;

enum class CommandLineParsingState
{
Expand All @@ -25,7 +40,9 @@ enum class CommandLineParsingState
ReadTmpDir,
ReadLods,
ReadScreenCoverage,
ReadMaxTextureSize
ReadMaxTextureSize,
ReadMinVersion,
ReadPlatform
};

void CommandLine::PrintHelp()
Expand All @@ -41,11 +58,14 @@ void CommandLine::PrintHelp()
<< std::endl
<< L"Optional arguments:" << std::endl
<< indent << "[" << std::wstring(PARAM_OUTFILE) << L" <output file path>]" << std::endl
<< indent << "[" << std::wstring(PARAM_TMPDIR) << L" <temporary folder, default is the system temp folder for the user>]" << std::endl
<< indent << "[" << std::wstring(PARAM_TMPDIR) << L" <temporary folder>] - default is the system temp folder for the user" << std::endl
<< indent << "[" << std::wstring(PARAM_PLATFORM) << " <" << PARAM_VALUE_ALL << " | " << PARAM_VALUE_HOLOGRAPHIC << " | " << PARAM_VALUE_DESKTOP << ">] - defaults to " << PARAM_VALUE_DESKTOP << std::endl
<< indent << "[" << std::wstring(PARAM_MIN_VERSION) << " <" << PARAM_VALUE_VERSION_1709 << " | " << PARAM_VALUE_VERSION_1803 << " | " << PARAM_VALUE_VERSION_LATEST << ">] - defaults to " << PARAM_VALUE_VERSION_1709 << std::endl
<< indent << "[" << std::wstring(PARAM_LOD) << " <path to each lower LOD asset in descending order of quality>]" << std::endl
<< indent << "[" << std::wstring(PARAM_SCREENCOVERAGE) << " <LOD screen coverage values>]" << std::endl
<< indent << "[" << std::wstring(PARAM_MAXTEXTURESIZE) << " <Max texture size in pixels, defaults to 512>]" << std::endl
<< indent << "[" << std::wstring(PARAM_SHARE_MATERIALS) << " defaults to false" << std::endl
<< indent << "[" << std::wstring(PARAM_SHARE_MATERIALS) << "] - disabled if not present" << std::endl
<< indent << "[" << std::wstring(PARAM_MAXTEXTURESIZE) << " <Max texture size in pixels>] - defaults to 512" << std::endl
<< indent << "[" << std::wstring(PARAM_REPLACE_TEXTURES) << "] - disabled if not present" << std::endl
<< std::endl
<< "Example:" << std::endl
<< indent << "WindowsMRAssetConverter FileToConvert.gltf "
Expand All @@ -65,7 +85,7 @@ void CommandLine::ParseCommandLineArguments(
int argc, wchar_t *argv[],
std::wstring& inputFilePath, AssetType& inputAssetType, std::wstring& outFilePath, std::wstring& tempDirectory,
std::vector<std::wstring>& lodFilePaths, std::vector<double>& screenCoveragePercentages, size_t& maxTextureSize,
bool& shareMaterials)
bool& shareMaterials, Version& minVersion, Platform& targetPlatforms, bool& replaceTextures)
{
CommandLineParsingState state = CommandLineParsingState::Initial;

Expand All @@ -80,6 +100,9 @@ void CommandLine::ParseCommandLineArguments(
screenCoveragePercentages.clear();
maxTextureSize = MAXTEXTURESIZE_DEFAULT;
shareMaterials = false;
minVersion = MIN_VERSION_DEFAULT;
targetPlatforms = PLATFORM_DEFAULT;
replaceTextures = false;

state = CommandLineParsingState::InputRead;

Expand Down Expand Up @@ -117,6 +140,22 @@ void CommandLine::ParseCommandLineArguments(
else if (param == PARAM_SHARE_MATERIALS)
{
shareMaterials = true;
state = CommandLineParsingState::InputRead;
}
else if (param == PARAM_MIN_VERSION)
{
minVersion = MIN_VERSION_DEFAULT;
state = CommandLineParsingState::ReadMinVersion;
}
else if (param == PARAM_PLATFORM)
{
targetPlatforms = PLATFORM_DEFAULT;
state = CommandLineParsingState::ReadPlatform;
}
else if (param == PARAM_REPLACE_TEXTURES)
{
replaceTextures = true;

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should set state to initial here.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed

state = CommandLineParsingState::InputRead;
}
else
{
Expand All @@ -142,6 +181,44 @@ void CommandLine::ParseCommandLineArguments(
case CommandLineParsingState::ReadMaxTextureSize:
maxTextureSize = std::min(static_cast<size_t>(std::stoul(param.c_str())), MAXTEXTURESIZE_MAX);
break;
case CommandLineParsingState::ReadMinVersion:
if (_wcsicmp(param.c_str(), PARAM_VALUE_VERSION_1709) == 0 || _wcsicmp(param.c_str(), PARAM_VALUE_VERSION_RS3) == 0)
{
minVersion = Version::Version1709;
}
else if (_wcsicmp(param.c_str(), PARAM_VALUE_VERSION_1803) == 0 || _wcsicmp(param.c_str(), PARAM_VALUE_VERSION_RS4) == 0)
{
minVersion = Version::Version1803;
}
else if (_wcsicmp(param.c_str(), PARAM_VALUE_VERSION_LATEST) == 0)
{
minVersion = Version::Latest;
}
else
{
throw std::invalid_argument("Invalid min version specified. For help, try the command again without parameters.");
}
state = CommandLineParsingState::InputRead;
break;
case CommandLineParsingState::ReadPlatform:
if (_wcsicmp(param.c_str(), PARAM_VALUE_ALL) == 0)
{
targetPlatforms = (Platform) (Platform::Desktop | Platform::Holographic);
}
else if (_wcsicmp(param.c_str(), PARAM_VALUE_HOLOGRAPHIC) == 0 || _wcsicmp(param.c_str(), PARAM_VALUE_HOLOLENS) == 0)
{
targetPlatforms = Platform::Holographic;
}
else if (_wcsicmp(param.c_str(), PARAM_VALUE_DESKTOP) == 0 || _wcsicmp(param.c_str(), PARAM_VALUE_PC) == 0)
{
targetPlatforms = Platform::Desktop;
}
else
{
throw std::invalid_argument("Invalid platform specified. For help, try the command again without parameters.");
}
state = CommandLineParsingState::InputRead;
break;
case CommandLineParsingState::Initial:
case CommandLineParsingState::InputRead:
default:
Expand Down
16 changes: 15 additions & 1 deletion WindowsMRAssetConverter/CommandLine.h
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,26 @@

namespace CommandLine
{
enum Platform
{
None = 0x0,
Holographic = 0x1,
Desktop = 0x2
};

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It seems as though we should not define the tool interface by platform instead of on the packing type(s) desired. If we also desire to have quick parameters also add platform/minversion.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The interface of the library uses the packing types. This is a lot more user-friendly, so that the dev doesn't have to study the docs to figure out which packing to use.
Here I'm using -compatibility-mode <on|off> and -platform <holographic|desktop|all> in combination to get assets with the right packing (NRM or ORM, but also supporting NRM+ORM, ORM+RMO and NRM+RMO+ORM combos).
What would be your proposal?

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also provide a option for packing types to add if the customer wants to define this themselves for use outside of Windows MR.

Simplifying with platform is great but a target minversion would be better than compatibility as our requirements/options evolve over time. Even better maybe to parse an appx manifest.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If the user wants to use their asset outside of Windows MR then this is the wrong tool. It's very easy to use the library and pack up a tool for your own scenario, but this tool specifically doesn't allow you to choose the packing/compression parameters besides what's supported for WMR.

I thought about the min version but that also adds complexity. I was trying to avoid as much as possible the user of the tool having to learn implementation details in order to use it. I agree that compatibility-mode is a very generic way of saying "support RS3 as well". I guess I'd be OK with changing that parameter to "-min-version " and number could be a build number (e.g. 16299.0) or a version number (1803) and it would do the right thing on either case.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed


enum class Version
{
Version1709, // Fall Creators Update (RS3)
Version1803, // Spring Creators Update (RS4)
Latest = Version1803
};

void PrintHelp();

void ParseCommandLineArguments(
int argc, wchar_t *argv[],
std::wstring& inputFilePath, AssetType& inputAssetType, std::wstring& outFilePath, std::wstring& tempDirectory,
std::vector<std::wstring>& lodFilePaths, std::vector<double>& screenCoveragePercentages, size_t& maxTextureSize,
bool& sharedMaterials);
bool& sharedMaterials, Version& minVersion, Platform& targetPlatforms, bool& replaceTextures);
};

47 changes: 36 additions & 11 deletions WindowsMRAssetConverter/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,42 +9,67 @@ WindowsMRAssetConverter _&lt;path to GLTF/GLB&gt;_

## Optional arguments
- `-o <output file path>`
- Specifies the output file name and directory for the output GLB
- Specifies the output file name and directory for the output GLB.
- If the file is a GLB and the output name is not specified, the tool defaults to the same name as input + "_converted.glb".

- `-platform <all | desktop | holographic>`
- **Default:** `desktop`
- `desktop`: optimizes assets for immersive PC-based headsets using the [MSFT_packing_occlusionRoughnessMetallic](https://github.com/KhronosGroup/glTF/tree/master/extensions/2.0/Vendor/MSFT_packing_occlusionRoughnessMetallic) extension.
- `holographic`: optimizes assets for HoloLens using the [MSFT_packing_normalRoughnessMetallic](https://github.com/KhronosGroup/glTF/tree/master/extensions/2.0/Vendor/MSFT_packing_normalRoughnessMetallic) extension.
- `all`: creates assets optimized for both holographic and desktop devices, but with a larger file size.

- `-min-version <1709 | 1803 | latest>`
- **Default:** `1709`
- Specifies the minimum version of Windows 10 supported by this asset.
- The current options are `1709` (Fall Creators Update) and `1803` (Spring Creators Update), as well as `latest` which is currently the same as `1803`.
- Supporting Windows 10 version 1709 results in assets with a larger file size. If your app is compatible with Windows 10 1803+ only, it is recommended to set `-min-version 1803`.
- This setting does not have any effect on the Holographic platform.

- `-lod <path to each lower LOD asset in descending order of quality>`
- Specifies a list of assets that represent levels of detail, from higher to lower, that should be merged with the main asset and used as alternates when the asset is displayed from a distance (with limited screen coverage).

- `-screen-coverage <LOD screen coverage values>`
- Specifies the maximum screen coverage values for each of the levels of detail, according to the [MSFT_lod](https://github.com/sbtron/glTF/tree/MSFT_lod/extensions/Vendor/MSFT_lod) extension specification.
- Specifies the maximum screen coverage values for each of the levels of detail, according to the [MSFT_lod](https://github.com/KhronosGroup/glTF/tree/master/extensions/2.0/Vendor/MSFT_lod) extension specification.

- `-share-materials`
- If enabled, creates assets that share materials between different levels of detail.
- This assumes all LOD documents use the same indices for each material, and uses the textures from the most detailed level.

- `-temp-directory <temporary folder, default is the system temp folder for the user>`
- `-temp-directory <temporary folder>`
- **Default:** system temp folder for the user
- Allows overriding the temporary folder where intermediate files (packed/compressed textures, converted GLBs) will be placed.

- `-max-texture-size <Max texture size in pixels, default is 512>`
- `-max-texture-size <Max texture size in pixels>`
- **Default:** 512
- Allows overriding the maximum texture dimension (width/height) when compressing textures. The recommended maximum dimension in the [documentation](https://developer.microsoft.com/en-us/windows/mixed-reality/creating_3d_models_for_use_in_the_windows_mixed_reality_home#texture_resolutions_and_workflow) is 512, and the allowed maximum is 4096.

- `-replace-textures`
- If enabled, replaces all textures with their DDS compressed equivalents during the compression step.
- This results in a smaller file size, but the resulting file will not be compatible with most glTF viewers.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This also sounds sort of like 'compatibility-mode', as in one might expect that when 'compatibility-mode' is off this flag would get applied automatically.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Makes sense. I think I'll get rid of -compatibility-mode entirely given this comment and @najadojo 's comments above.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed



## Example
`WindowsMRAssetConverter FileToConvert.gltf -o ConvertedFile.glb -lod Lod1.gltf Lod2.gltf -screen-coverage 0.5 0.2 0.01`
`WindowsMRAssetConverter FileToConvert.gltf -o ConvertedFile.glb -platform all -lod Lod1.gltf Lod2.gltf -screen-coverage 0.5 0.2 0.01`

The above will convert _FileToConvert.gltf_ into _ConvertedFile.glb_ in the current directory.

## Pipeline overview

Each asset goes through the following steps when converting for compatibility with the Windows Mixed Reality home:

1. **Conversion from GLB** - any GLB files are converted to loose glTF + assets, to simplify the code for reading resources
1. **Texture packing** - The textures that are relevant for the Windows MR home are packed according to the [documentation](https://developer.microsoft.com/en-us/windows/mixed-reality/creating_3d_models_for_use_in_the_windows_mixed_reality_home#materials) using the [MSFT\_packing\_occlusionRoughnessMetallic](https://github.com/sbtron/glTF/tree/MSFT_lod/extensions/Vendor/MSFT_packing_occlusionRoughnessMetallic) extension if necessary
1. **Conversion from GLB** - Any GLB files are converted to loose glTF + assets, to simplify the code for reading resources
1. **Texture packing** - The textures that are relevant for the Windows MR home are packed according to the [documentation](https://developer.microsoft.com/en-us/windows/mixed-reality/creating_3d_models_for_use_in_the_windows_mixed_reality_home#materials) using the [MSFT\_packing\_occlusionRoughnessMetallic](https://github.com/KhronosGroup/glTF/tree/master/extensions/2.0/Vendor/MSFT_packing_occlusionRoughnessMetallic) and [MSFT\_packing\_normalRoughnessMetallic](https://github.com/KhronosGroup/glTF/tree/master/extensions/2.0/Vendor/MSFT_packing_normalRoughnessMetallic) extensions as necessary
1. **Texture compression** - All textures that are used in the Windows MR home must be compressed as DDS BC5 or BC7 according to the [documentation](https://developer.microsoft.com/en-us/windows/mixed-reality/creating_3d_models_for_use_in_the_windows_mixed_reality_home#materials). This step also generates mip maps for the textures, and resizes them down if necessary
1. **LOD merging** - All assets that represent levels of detail are merged into the main asset using the [MSFT_lod](https://github.com/sbtron/glTF/tree/MSFT_lod/extensions/Vendor/MSFT_lod) extension
1. **LOD merging** - All assets that represent levels of detail are merged into the main asset using the [MSFT_lod](https://github.com/KhronosGroup/glTF/tree/master/extensions/2.0/Vendor/MSFT_lod) extension
1. **GLB export** - The resulting assets are exported as a GLB with all resources. As part of this step, accessors are modified to conform to the [glTF implementation notes in the documentation](https://developer.microsoft.com/en-us/windows/mixed-reality/creating_3d_models_for_use_in_the_windows_mixed_reality_home#gltf_implementation_notes): component types are converted to types supported by the Windows MR home, and the min and max values are calculated before serializing the accessors to the GLB

## Additional resources

- [Creating 3D models for use in the Windows Mixed Reality home](https://developer.microsoft.com/en-us/windows/mixed-reality/creating_3d_models_for_use_in_the_windows_mixed_reality_home)
- [Microsoft glTF LOD Extension Specification](https://github.com/sbtron/glTF/tree/MSFT_lod/extensions/Vendor/MSFT_lod)
- [PC Mixed Reality Texture Packing Extensions Specification](https://github.com/sbtron/glTF/tree/MSFT_lod/extensions/Vendor/MSFT_packing_occlusionRoughnessMetallic)
- [Microsoft DDS Textures glTF extensions specification](https://github.com/sbtron/glTF/tree/MSFT_lod/extensions/Vendor/MSFT_texture_dds)
- [Microsoft glTF LOD Extension Specification](https://github.com/KhronosGroup/glTF/tree/master/extensions/2.0/Vendor/MSFT_lod)
- [PC Mixed Reality Texture Packing Extensions Specification](https://github.com/KhronosGroup/glTF/tree/master/extensions/2.0/Vendor/MSFT_packing_occlusionRoughnessMetallic)
- [Holographic Mixed Reality Texture Packing Extensions Specification](https://github.com/KhronosGroup/glTF/tree/master/extensions/2.0/Vendor/MSFT_packing_normalRoughnessMetallic)
- [Microsoft DDS Textures glTF extensions specification](https://github.com/KhronosGroup/glTF/tree/master/extensions/2.0/Vendor/MSFT_texture_dds)
- [Implementing 3D app launchers](https://developer.microsoft.com/en-us/windows/mixed-reality/implementing_3d_app_launchers)
- [Implementing 3D deep links for your app in the Windows Mixed Reality home](https://developer.microsoft.com/en-us/windows/mixed-reality/implementing_3d_deep_links_for_your_app_in_the_windows_mixed_reality_home)
- [Navigating the Windows Mixed Reality home](https://developer.microsoft.com/en-us/windows/mixed-reality/navigating_the_windows_mixed_reality_home)
Loading