Skip to content

Commit

Permalink
Initial code drop - migrating from internal repo to GitHub (#1)
Browse files Browse the repository at this point in the history
Initial commit
  • Loading branch information
robertos authored Dec 5, 2017
1 parent 63a91fe commit ef9305b
Show file tree
Hide file tree
Showing 73 changed files with 6,279 additions and 1 deletion.
32 changes: 31 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,29 @@
# Microsoft glTF Toolkit

# Contributing
This project contains a collection of tools and libraries to modify and optimize glTF assets.

## 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.

It also includes a command line tool that uses these steps in sequence in order to convert a glTF 2.0 core asset for use in the Windows Mixed Reality home, following the published [documentation](https://developer.microsoft.com/en-us/windows/mixed-reality/creating_3d_models_for_use_in_the_windows_mixed_reality_home).

## Dependencies

This project consumes the following projects through NuGet packages:
- Microsoft GLTF SDK, licensed under the MIT license
- [DirectXTex](http://github.com/Microsoft/DirectXTex), licensed under the MIT license
- [RapidJSON](https://github.com/Tencent/rapidjson/), licensed under the MIT license


## Building

This project can be built using Visual Studio 2017 Update 4 on Windows 10 Fall Creators Update (16299.0).

## Contributing

This project welcomes contributions and suggestions. Most contributions require you to agree to a
Contributor License Agreement (CLA) declaring that you have the right to, and actually do, grant us
Expand All @@ -12,3 +36,9 @@ provided by the bot. You will only need to do this once across all repos using o
This project has adopted the [Microsoft Open Source Code of Conduct](https://opensource.microsoft.com/codeofconduct/).
For more information see the [Code of Conduct FAQ](https://opensource.microsoft.com/codeofconduct/faq/) or
contact [[email protected]](mailto:[email protected]) with any additional questions or comments.

## License

Copyright (c) Microsoft Corporation. All rights reserved.

Licensed under the [MIT License](LICENSE).
30 changes: 30 additions & 0 deletions WindowsMRAssetConverter/AssetType.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License. See LICENSE in the project root for license information.

#include "stdafx.h"
#include "AssetType.h"

const wchar_t * EXTENSION_GLTF = L".gltf";
const wchar_t * EXTENSION_GLB = L".glb";

AssetType AssetTypeUtils::AssetTypeFromFilePath(const std::wstring& assetPath)
{
const wchar_t *inputExtensionRaw = nullptr;
if (FAILED(PathCchFindExtension(assetPath.c_str(), assetPath.length() + 1, &inputExtensionRaw)))
{
throw std::invalid_argument("Invalid input file extension.");
}

if (_wcsicmp(inputExtensionRaw, EXTENSION_GLTF) == 0)
{
return AssetType::GLTF;
}
else if (_wcsicmp(inputExtensionRaw, EXTENSION_GLB) == 0)
{
return AssetType::GLB;
}
else
{
throw std::invalid_argument("Invalid file, please provide a GLTF or GLB.");
}
}
18 changes: 18 additions & 0 deletions WindowsMRAssetConverter/AssetType.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License. See LICENSE in the project root for license information.

#pragma once

extern const wchar_t * EXTENSION_GLTF;
extern const wchar_t * EXTENSION_GLB;

enum class AssetType
{
GLTF,
GLB
};

namespace AssetTypeUtils
{
AssetType AssetTypeFromFilePath(const std::wstring& assetPath);
}
172 changes: 172 additions & 0 deletions WindowsMRAssetConverter/CommandLine.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,172 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License. See LICENSE in the project root for license information.

#include "stdafx.h"
#include "CommandLine.h"
#include "FileSystem.h"

// Constants
const wchar_t * PARAM_OUTFILE = L"-o";
const wchar_t * PARAM_TMPDIR = L"-temp-directory";
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 * SUFFIX_CONVERTED = L"_converted";
const wchar_t * CLI_INDENT = L" ";
const size_t MAXTEXTURESIZE_DEFAULT = 512;
const size_t MAXTEXTURESIZE_MAX = 4096;

enum class CommandLineParsingState
{
Initial,
InputRead,
ReadOutFile,
ReadTmpDir,
ReadLods,
ReadScreenCoverage,
ReadMaxTextureSize
};

void CommandLine::PrintHelp()
{
auto indent = std::wstring(CLI_INDENT);
std::wcerr << std::endl
<< L"Windows Mixed Reality Asset Converter" << std::endl
<< L"=====================================" << std::endl
<< std::endl
<< L"A command line tool to convert core GLTF 2.0 assets for use in "
<< L"the Windows Mixed Reality home, with the proper texture packing, compression and merged LODs." << std::endl << std::endl
<< L"Usage: WindowsMRAssetConverter <path to GLTF/GLB>" << std::endl
<< 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_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
<< std::endl
<< "Example:" << std::endl
<< indent << "WindowsMRAssetConverter FileToConvert.gltf "
<< std::wstring(PARAM_OUTFILE) << " ConvertedFile.glb "
<< std::wstring(PARAM_LOD) << " Lod1.gltf Lod2.gltf "
<< std::wstring(PARAM_SCREENCOVERAGE) << " 0.5 0.2 0.01" << std::endl
<< std::endl
<< "The above will convert \"FileToConvert.gltf\" into \"ConvertedFile.glb\" in the "
<< "current directory." << std::endl
<< std::endl
<< "If the file is a GLB and the output name is not specified, defaults to the same name as input "
<< "+ \"_converted.glb\"." << std::endl
<< std::endl;
}

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)
{
CommandLineParsingState state = CommandLineParsingState::Initial;

inputFilePath = FileSystem::GetFullPath(std::wstring(argv[1]));

inputAssetType = AssetTypeUtils::AssetTypeFromFilePath(inputFilePath);

// Reset input parameters
outFilePath = L"";
tempDirectory = L"";
lodFilePaths.clear();
screenCoveragePercentages.clear();
maxTextureSize = MAXTEXTURESIZE_DEFAULT;

state = CommandLineParsingState::InputRead;

std::wstring outFile;
std::wstring tmpDir;
for (int i = 2; i < argc; i++)
{
std::wstring param = argv[i];

if (param == PARAM_OUTFILE)
{
outFile = L"";
state = CommandLineParsingState::ReadOutFile;
}
else if (param == PARAM_TMPDIR)
{
tmpDir = L"";
state = CommandLineParsingState::ReadTmpDir;
}
else if (param == PARAM_LOD)
{
lodFilePaths.clear();
state = CommandLineParsingState::ReadLods;
}
else if (param == PARAM_SCREENCOVERAGE)
{
screenCoveragePercentages.clear();
state = CommandLineParsingState::ReadScreenCoverage;
}
else if (param == PARAM_MAXTEXTURESIZE)
{
maxTextureSize = MAXTEXTURESIZE_DEFAULT;
state = CommandLineParsingState::ReadMaxTextureSize;
}
else
{
switch (state)
{
case CommandLineParsingState::ReadOutFile:
outFile = FileSystem::GetFullPath(param);
state = CommandLineParsingState::InputRead;
break;
case CommandLineParsingState::ReadTmpDir:
tmpDir = FileSystem::GetFullPath(param);
state = CommandLineParsingState::InputRead;
break;
case CommandLineParsingState::ReadLods:
lodFilePaths.push_back(FileSystem::GetFullPath(param));
break;
case CommandLineParsingState::ReadScreenCoverage:
{
auto paramA = std::string(param.begin(), param.end());
screenCoveragePercentages.push_back(std::atof(paramA.c_str()));
break;
}
case CommandLineParsingState::ReadMaxTextureSize:
maxTextureSize = std::min(static_cast<size_t>(std::stoul(param.c_str())), MAXTEXTURESIZE_MAX);
break;
case CommandLineParsingState::Initial:
case CommandLineParsingState::InputRead:
default:
// Invalid argument detected
throw std::invalid_argument("Invalid usage. For help, try the command again without parameters.");
}
}
}

if (outFile.empty())
{
std::wstring inputFilePathWithoutExtension = inputFilePath;
if (FAILED(PathCchRemoveExtension(&inputFilePathWithoutExtension[0], inputFilePathWithoutExtension.length() + 1)))
{
throw std::invalid_argument("Invalid input file extension.");
}

outFile = std::wstring(&inputFilePathWithoutExtension[0]);

if (inputAssetType == AssetType::GLB)
{
outFile += SUFFIX_CONVERTED;
}

outFile += EXTENSION_GLB;
}

outFilePath = outFile;

if (tmpDir.empty())
{
tmpDir = FileSystem::CreateTempFolder();
}

tempDirectory = tmpDir;
}
18 changes: 18 additions & 0 deletions WindowsMRAssetConverter/CommandLine.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License. See LICENSE in the project root for license information.

#pragma once

#include <vector>
#include "AssetType.h"

namespace CommandLine
{
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);
};

75 changes: 75 additions & 0 deletions WindowsMRAssetConverter/FileSystem.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License. See LICENSE in the project root for license information.

#include "stdafx.h"
#include "FileSystem.h"

std::wstring FileSystem::GetBasePath(const std::wstring& path)
{
std::wstring pathCopy(path);
wchar_t *basePath = &pathCopy[0];
if (FAILED(PathCchRemoveFileSpec(basePath, pathCopy.length() + 1)))
{
throw std::invalid_argument("Invalid input path.");
}

return std::move(std::wstring(basePath));
}


std::wstring FileSystem::GetFullPath(const std::wstring& path)
{
wchar_t fullPath[MAX_PATH];
if (GetFullPathName(path.c_str(), ARRAYSIZE(fullPath), fullPath, NULL) == 0)
{
throw std::invalid_argument("Invalid input file path.");
}
return std::move(std::wstring(fullPath));
}

std::wstring FileSystem::CreateSubFolder(const std::wstring& parentPath, const std::wstring& subFolderName)
{
std::wstring errorMessageW = L"Could not create a sub-folder of " + parentPath + L".";
std::string errorMessage(errorMessageW.begin(), errorMessageW.end());

wchar_t subFolderPath[MAX_PATH];
if (FAILED(PathCchCombine(subFolderPath, ARRAYSIZE(subFolderPath), parentPath.c_str(), (subFolderName + L"\\").c_str())))
{
throw std::runtime_error(errorMessage);
}

if (CreateDirectory(subFolderPath, NULL) == 0 && GetLastError() != ERROR_ALREADY_EXISTS)
{
throw std::runtime_error(errorMessage);
}

return std::move(std::wstring(subFolderPath));
}

std::wstring FileSystem::CreateTempFolder()
{
std::wstring errorMessageW = L"Could not get a temporary folder. Try specifying one in the command line.";
std::string errorMessage(errorMessageW.begin(), errorMessageW.end());

wchar_t tmpDirRaw[MAX_PATH];
auto returnValue = GetTempPath(MAX_PATH, tmpDirRaw);
if (returnValue > MAX_PATH || (returnValue == 0))
{
throw std::runtime_error(errorMessage);
}

// Get a random folder to drop the files
GUID guid = { 0 };
if (FAILED(CoCreateGuid(&guid)))
{
throw std::runtime_error(errorMessage);
}

wchar_t guidRaw[MAX_PATH];
if (StringFromGUID2(guid, guidRaw, ARRAYSIZE(guidRaw)) == 0)
{
throw std::runtime_error(errorMessage);
}

return std::move(CreateSubFolder(tmpDirRaw, guidRaw));
}
13 changes: 13 additions & 0 deletions WindowsMRAssetConverter/FileSystem.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License. See LICENSE in the project root for license information.

#pragma once

namespace FileSystem
{
std::wstring GetBasePath(const std::wstring& path);
std::wstring GetFullPath(const std::wstring& path);
std::wstring CreateSubFolder(const std::wstring& parentPath, const std::wstring& subFolderName);
std::wstring CreateTempFolder();
};

Loading

0 comments on commit ef9305b

Please sign in to comment.