UVAtlas tool: added -fn, -fuv, and -fc switches

This commit is contained in:
Chuck Walbourn 2020-08-04 22:25:47 -07:00
parent 424c2ca6bd
commit 2b2334aff2
4 changed files with 392 additions and 185 deletions

View File

@ -32,11 +32,11 @@ using namespace DirectX;
namespace
{
struct handle_closer { void operator()(HANDLE h) { if (h) CloseHandle(h); } };
struct handle_closer { void operator()(HANDLE h) noexcept { if (h) CloseHandle(h); } };
using ScopedHandle = std::unique_ptr<void, handle_closer>;
inline HANDLE safe_handle(HANDLE h) { return (h == INVALID_HANDLE_VALUE) ? nullptr : h; }
inline HANDLE safe_handle(HANDLE h) noexcept { return (h == INVALID_HANDLE_VALUE) ? nullptr : h; }
template<typename T> inline HRESULT write_file(HANDLE hFile, const T& value)
{
@ -122,7 +122,7 @@ Mesh& Mesh::operator= (Mesh&& moveFrom) noexcept
//--------------------------------------------------------------------------------------
void Mesh::Clear()
void Mesh::Clear() noexcept
{
mnFaces = mnVerts = 0;
@ -145,7 +145,7 @@ void Mesh::Clear()
//--------------------------------------------------------------------------------------
_Use_decl_annotations_
HRESULT Mesh::SetIndexData(size_t nFaces, const uint16_t* indices, uint32_t* attributes)
HRESULT Mesh::SetIndexData(size_t nFaces, const uint16_t* indices, uint32_t* attributes) noexcept
{
if (!nFaces || !indices)
return E_INVALIDARG;
@ -192,7 +192,7 @@ HRESULT Mesh::SetIndexData(size_t nFaces, const uint16_t* indices, uint32_t* att
}
_Use_decl_annotations_
HRESULT Mesh::SetIndexData(size_t nFaces, const uint32_t* indices, uint32_t* attributes)
HRESULT Mesh::SetIndexData(size_t nFaces, const uint32_t* indices, uint32_t* attributes) noexcept
{
if (!nFaces || !indices)
return E_INVALIDARG;
@ -229,7 +229,7 @@ HRESULT Mesh::SetIndexData(size_t nFaces, const uint32_t* indices, uint32_t* att
//--------------------------------------------------------------------------------------
HRESULT Mesh::SetVertexData(_Inout_ DirectX::VBReader& reader, _In_ size_t nVerts)
HRESULT Mesh::SetVertexData(_Inout_ DirectX::VBReader& reader, _In_ size_t nVerts) noexcept
{
if (!nVerts)
return E_INVALIDARG;
@ -369,7 +369,7 @@ HRESULT Mesh::SetVertexData(_Inout_ DirectX::VBReader& reader, _In_ size_t nVert
//--------------------------------------------------------------------------------------
_Use_decl_annotations_
HRESULT Mesh::Validate(DirectX::VALIDATE_FLAGS flags, std::wstring* msgs) const
HRESULT Mesh::Validate(DirectX::VALIDATE_FLAGS flags, std::wstring* msgs) const noexcept
{
if (!mnFaces || !mIndices || !mnVerts)
return E_UNEXPECTED;
@ -379,7 +379,7 @@ HRESULT Mesh::Validate(DirectX::VALIDATE_FLAGS flags, std::wstring* msgs) const
//--------------------------------------------------------------------------------------
HRESULT Mesh::Clean(_In_ bool breakBowties)
HRESULT Mesh::Clean(_In_ bool breakBowties) noexcept
{
if (!mnFaces || !mIndices || !mnVerts || !mPositions)
return E_UNEXPECTED;
@ -531,7 +531,7 @@ HRESULT Mesh::Clean(_In_ bool breakBowties)
//--------------------------------------------------------------------------------------
HRESULT Mesh::GenerateAdjacency(_In_ float epsilon)
HRESULT Mesh::GenerateAdjacency(_In_ float epsilon) noexcept
{
if (!mnFaces || !mIndices || !mnVerts || !mPositions)
return E_UNEXPECTED;
@ -548,7 +548,7 @@ HRESULT Mesh::GenerateAdjacency(_In_ float epsilon)
//--------------------------------------------------------------------------------------
HRESULT Mesh::ComputeNormals(_In_ DirectX::CNORM_FLAGS flags)
HRESULT Mesh::ComputeNormals(_In_ DirectX::CNORM_FLAGS flags) noexcept
{
if (!mnFaces || !mIndices || !mnVerts || !mPositions)
return E_UNEXPECTED;
@ -562,7 +562,7 @@ HRESULT Mesh::ComputeNormals(_In_ DirectX::CNORM_FLAGS flags)
//--------------------------------------------------------------------------------------
HRESULT Mesh::ComputeTangentFrame(_In_ bool bitangents)
HRESULT Mesh::ComputeTangentFrame(_In_ bool bitangents) noexcept
{
if (!mnFaces || !mIndices || !mnVerts || !mPositions || !mNormals || !mTexCoords)
return E_UNEXPECTED;
@ -605,7 +605,7 @@ HRESULT Mesh::ComputeTangentFrame(_In_ bool bitangents)
//--------------------------------------------------------------------------------------
_Use_decl_annotations_
HRESULT Mesh::UpdateFaces(size_t nFaces, const uint32_t* indices)
HRESULT Mesh::UpdateFaces(size_t nFaces, const uint32_t* indices) noexcept
{
if (!nFaces || !indices)
return E_INVALIDARG;
@ -627,7 +627,7 @@ HRESULT Mesh::UpdateFaces(size_t nFaces, const uint32_t* indices)
//--------------------------------------------------------------------------------------
_Use_decl_annotations_
HRESULT Mesh::UpdateAttributes(size_t nFaces, const uint32_t* attributes)
HRESULT Mesh::UpdateAttributes(size_t nFaces, const uint32_t* attributes) noexcept
{
if (!nFaces || !attributes)
return E_INVALIDARG;
@ -678,7 +678,7 @@ HRESULT Mesh::UpdateAttributes(size_t nFaces, const uint32_t* attributes)
//--------------------------------------------------------------------------------------
_Use_decl_annotations_
HRESULT Mesh::UpdateUVs(size_t nVerts, const XMFLOAT2* uvs)
HRESULT Mesh::UpdateUVs(size_t nVerts, const XMFLOAT2* uvs) noexcept
{
if (!nVerts || !uvs)
return E_INVALIDARG;
@ -711,7 +711,7 @@ HRESULT Mesh::UpdateUVs(size_t nVerts, const XMFLOAT2* uvs)
//--------------------------------------------------------------------------------------
_Use_decl_annotations_
HRESULT Mesh::VertexRemap(const uint32_t* remap, size_t nNewVerts)
HRESULT Mesh::VertexRemap(const uint32_t* remap, size_t nNewVerts) noexcept
{
if (!remap || !nNewVerts)
return E_INVALIDARG;
@ -829,7 +829,7 @@ HRESULT Mesh::VertexRemap(const uint32_t* remap, size_t nNewVerts)
//--------------------------------------------------------------------------------------
HRESULT Mesh::ReverseWinding()
HRESULT Mesh::ReverseWinding() noexcept
{
if (!mIndices || !mnFaces)
return E_UNEXPECTED;
@ -846,7 +846,7 @@ HRESULT Mesh::ReverseWinding()
//--------------------------------------------------------------------------------------
HRESULT Mesh::InvertUTexCoord()
HRESULT Mesh::InvertUTexCoord() noexcept
{
if (!mTexCoords)
return E_UNEXPECTED;
@ -862,7 +862,7 @@ HRESULT Mesh::InvertUTexCoord()
//--------------------------------------------------------------------------------------
HRESULT Mesh::InvertVTexCoord()
HRESULT Mesh::InvertVTexCoord() noexcept
{
if (!mTexCoords)
return E_UNEXPECTED;
@ -878,7 +878,7 @@ HRESULT Mesh::InvertVTexCoord()
//--------------------------------------------------------------------------------------
HRESULT Mesh::ReverseHandedness()
HRESULT Mesh::ReverseHandedness() noexcept
{
if (!mPositions)
return E_UNEXPECTED;
@ -903,7 +903,7 @@ HRESULT Mesh::ReverseHandedness()
//--------------------------------------------------------------------------------------
HRESULT Mesh::VisualizeUVs()
HRESULT Mesh::VisualizeUVs() noexcept
{
if (!mnVerts || !mPositions || !mTexCoords)
return E_UNEXPECTED;
@ -934,7 +934,7 @@ HRESULT Mesh::VisualizeUVs()
//--------------------------------------------------------------------------------------
bool Mesh::Is16BitIndexBuffer() const
bool Mesh::Is16BitIndexBuffer() const noexcept
{
if (!mIndices || !mnFaces)
return false;
@ -958,7 +958,7 @@ bool Mesh::Is16BitIndexBuffer() const
//--------------------------------------------------------------------------------------
std::unique_ptr<uint16_t[]> Mesh::GetIndexBuffer16() const
std::unique_ptr<uint16_t[]> Mesh::GetIndexBuffer16() const noexcept
{
std::unique_ptr<uint16_t[]> ib;
@ -998,7 +998,7 @@ std::unique_ptr<uint16_t[]> Mesh::GetIndexBuffer16() const
//--------------------------------------------------------------------------------------
HRESULT Mesh::GetVertexBuffer(_Inout_ DirectX::VBWriter& writer) const
HRESULT Mesh::GetVertexBuffer(_Inout_ DirectX::VBWriter& writer) const noexcept
{
if (!mnVerts || !mPositions)
return E_UNEXPECTED;
@ -1012,7 +1012,8 @@ HRESULT Mesh::GetVertexBuffer(_Inout_ DirectX::VBWriter& writer) const
auto e = writer.GetElement11("NORMAL", 0);
if (e)
{
hr = writer.Write(mNormals.get(), "NORMAL", 0, mnVerts);
bool x2bias = (e->Format == DXGI_FORMAT_R11G11B10_FLOAT);
hr = writer.Write(mNormals.get(), "NORMAL", 0, mnVerts, x2bias);
if (FAILED(hr))
return hr;
}
@ -1023,7 +1024,8 @@ HRESULT Mesh::GetVertexBuffer(_Inout_ DirectX::VBWriter& writer) const
auto e = writer.GetElement11("TANGENT", 0);
if (e)
{
hr = writer.Write(mTangents.get(), "TANGENT", 0, mnVerts);
bool x2bias = (e->Format == DXGI_FORMAT_R11G11B10_FLOAT);
hr = writer.Write(mTangents.get(), "TANGENT", 0, mnVerts, x2bias);
if (FAILED(hr))
return hr;
}
@ -1034,7 +1036,8 @@ HRESULT Mesh::GetVertexBuffer(_Inout_ DirectX::VBWriter& writer) const
auto e = writer.GetElement11("BINORMAL", 0);
if (e)
{
hr = writer.Write(mBiTangents.get(), "BINORMAL", 0, mnVerts);
bool x2bias = (e->Format == DXGI_FORMAT_R11G11B10_FLOAT);
hr = writer.Write(mBiTangents.get(), "BINORMAL", 0, mnVerts, x2bias);
if (FAILED(hr))
return hr;
}
@ -1119,7 +1122,7 @@ namespace VBO
//--------------------------------------------------------------------------------------
_Use_decl_annotations_
HRESULT Mesh::ExportToVBO(const wchar_t* szFileName) const
HRESULT Mesh::ExportToVBO(const wchar_t* szFileName) const noexcept
{
using namespace VBO;
@ -1211,7 +1214,7 @@ HRESULT Mesh::ExportToVBO(const wchar_t* szFileName) const
//--------------------------------------------------------------------------------------
_Use_decl_annotations_
HRESULT Mesh::CreateFromVBO(const wchar_t* szFileName, std::unique_ptr<Mesh>& result)
HRESULT Mesh::CreateFromVBO(const wchar_t* szFileName, std::unique_ptr<Mesh>& result) noexcept
{
using namespace VBO;
@ -1489,7 +1492,7 @@ static_assert(sizeof(VSD3DStarter::Keyframe) == 72, "CMO Mesh structure size inc
//--------------------------------------------------------------------------------------
_Use_decl_annotations_
HRESULT Mesh::ExportToCMO(const wchar_t* szFileName, size_t nMaterials, const Material* materials) const
HRESULT Mesh::ExportToCMO(const wchar_t* szFileName, size_t nMaterials, const Material* materials) const noexcept
{
using namespace VSD3DStarter;
@ -1862,7 +1865,13 @@ HRESULT Mesh::ExportToCMO(const wchar_t* szFileName, size_t nMaterials, const Ma
//======================================================================================
_Use_decl_annotations_
HRESULT Mesh::ExportToSDKMESH(const wchar_t* szFileName, size_t nMaterials, const Material* materials, bool force32bit, bool version2) const
HRESULT Mesh::ExportToSDKMESH(const wchar_t* szFileName,
size_t nMaterials, const Material* materials,
bool force32bit,
bool version2,
DXGI_FORMAT normalFormat,
DXGI_FORMAT uvFormat,
DXGI_FORMAT colorFormat) const noexcept
{
using namespace DXUT;
@ -1906,6 +1915,65 @@ HRESULT Mesh::ExportToSDKMESH(const wchar_t* szFileName, size_t nMaterials, cons
static_assert((_countof(s_elements) + 1) == _countof(s_decls), "InputLayouts and Vertex Decls disagree");
uint8_t normalType;
size_t normalStride;
switch (normalFormat)
{
case DXGI_FORMAT_R16G16B16A16_FLOAT:
normalType = D3DDECLTYPE_FLOAT16_4; normalStride = sizeof(PackedVector::XMHALF4);
break;
case DXGI_FORMAT_R11G11B10_FLOAT: // Biased in GetVertexBuffer
normalType = D3DDECLTYPE_DXGI_R11G11B10_FLOAT; normalStride = sizeof(UINT);
break;
default:
normalFormat = DXGI_FORMAT_R32G32B32_FLOAT; normalType = D3DDECLTYPE_FLOAT3; normalStride = sizeof(XMFLOAT3);
break;
}
uint8_t uvType;
size_t uvStride;
switch (uvFormat)
{
case DXGI_FORMAT_R16G16_FLOAT:
uvType = D3DDECLTYPE_FLOAT16_2; uvStride = sizeof(PackedVector::XMHALF2);
break;
default:
uvFormat = DXGI_FORMAT_R32G32_FLOAT; uvType = D3DDECLTYPE_FLOAT2; uvStride = sizeof(XMFLOAT2);
break;
}
uint8_t colorType;
size_t colorStride;
switch (colorFormat)
{
case DXGI_FORMAT_R32G32B32A32_FLOAT:
colorType = D3DDECLTYPE_FLOAT4; colorStride = sizeof(XMFLOAT4);
break;
case DXGI_FORMAT_R16G16B16A16_FLOAT:
colorType = D3DDECLTYPE_FLOAT16_4; colorStride = sizeof(PackedVector::XMHALF4);
break;
case DXGI_FORMAT_R11G11B10_FLOAT:
colorType = D3DDECLTYPE_DXGI_R11G11B10_FLOAT; colorStride = sizeof(UINT);
break;
case DXGI_FORMAT_R10G10B10A2_UNORM:
colorType = D3DDECLTYPE_DXGI_R10G10B10A2_UNORM; colorStride = sizeof(UINT);
break;
case DXGI_FORMAT_R8G8B8A8_UNORM:
colorType = D3DDECLTYPE_UBYTE4N; colorStride = sizeof(UINT);
break;
default:
colorFormat = DXGI_FORMAT_B8G8R8A8_UNORM; colorType = D3DDECLTYPE_D3DCOLOR; colorStride = sizeof(UINT);
break;
}
SDKMESH_VERTEX_BUFFER_HEADER vbHeader = {};
vbHeader.NumVertices = mnVerts;
vbHeader.Decl[0] = s_decls[0];
@ -1936,46 +2004,56 @@ HRESULT Mesh::ExportToSDKMESH(const wchar_t* szFileName, size_t nMaterials, cons
if (mNormals)
{
vbHeader.Decl[nDecl] = s_decls[1];
vbHeader.Decl[nDecl].Type = normalType;
vbHeader.Decl[nDecl].Offset = static_cast<WORD>(stride);
inputLayout[nDecl] = s_elements[1];
inputLayout[nDecl].Format = normalFormat;
++nDecl;
stride += sizeof(XMFLOAT3);
stride += normalStride;
}
if (mColors)
{
vbHeader.Decl[nDecl] = s_decls[2];
vbHeader.Decl[nDecl].Type = colorType;
vbHeader.Decl[nDecl].Offset = static_cast<WORD>(stride);
inputLayout[nDecl] = s_elements[2];
inputLayout[nDecl].Format = colorFormat;
++nDecl;
stride += sizeof(UINT);
stride += colorStride;
}
if (mTexCoords)
{
vbHeader.Decl[nDecl] = s_decls[5];
vbHeader.Decl[nDecl].Type = uvType;
vbHeader.Decl[nDecl].Offset = static_cast<WORD>(stride);
inputLayout[nDecl] = s_elements[5];
inputLayout[nDecl].Format = uvFormat;
++nDecl;
stride += sizeof(XMFLOAT2);
stride += uvStride;
}
if (mTangents)
{
vbHeader.Decl[nDecl] = s_decls[3];
vbHeader.Decl[nDecl].Type = normalType;
vbHeader.Decl[nDecl].Offset = static_cast<WORD>(stride);
inputLayout[nDecl] = s_elements[3];
inputLayout[nDecl].Format = normalFormat;
++nDecl;
stride += sizeof(XMFLOAT3);
stride += normalStride;
}
if (mBiTangents)
{
vbHeader.Decl[nDecl] = s_decls[4];
vbHeader.Decl[nDecl].Type = normalType;
vbHeader.Decl[nDecl].Offset = static_cast<WORD>(stride);
inputLayout[nDecl] = s_elements[4];
inputLayout[nDecl].Format = normalFormat;
++nDecl;
stride += sizeof(XMFLOAT3);
stride += normalStride;
}
assert(nDecl < MAX_VERTEX_ELEMENTS);

View File

@ -39,60 +39,60 @@ public:
Mesh& operator= (Mesh const&) = delete;
// Methods
void Clear();
void Clear() noexcept;
void SetMTLFileName(const std::wstring& name) { mtlFileName = name; }
void SetMTLFileName(const std::wstring& name) noexcept { mtlFileName = name; }
HRESULT SetIndexData(_In_ size_t nFaces, _In_reads_(nFaces * 3) const uint16_t* indices, _In_reads_opt_(nFaces) uint32_t* attributes = nullptr);
HRESULT SetIndexData(_In_ size_t nFaces, _In_reads_(nFaces * 3) const uint32_t* indices, _In_reads_opt_(nFaces) uint32_t* attributes = nullptr);
HRESULT SetIndexData(_In_ size_t nFaces, _In_reads_(nFaces * 3) const uint16_t* indices, _In_reads_opt_(nFaces) uint32_t* attributes = nullptr) noexcept;
HRESULT SetIndexData(_In_ size_t nFaces, _In_reads_(nFaces * 3) const uint32_t* indices, _In_reads_opt_(nFaces) uint32_t* attributes = nullptr) noexcept;
HRESULT SetVertexData(_Inout_ DirectX::VBReader& reader, _In_ size_t nVerts);
HRESULT SetVertexData(_Inout_ DirectX::VBReader& reader, _In_ size_t nVerts) noexcept;
HRESULT Validate(_In_ DirectX::VALIDATE_FLAGS flags, _In_opt_ std::wstring* msgs) const;
HRESULT Validate(_In_ DirectX::VALIDATE_FLAGS flags, _In_opt_ std::wstring* msgs) const noexcept;
HRESULT Clean(_In_ bool breakBowties = false);
HRESULT Clean(_In_ bool breakBowties = false) noexcept;
HRESULT GenerateAdjacency(_In_ float epsilon);
HRESULT GenerateAdjacency(_In_ float epsilon) noexcept;
HRESULT ComputeNormals(_In_ DirectX::CNORM_FLAGS flags);
HRESULT ComputeNormals(_In_ DirectX::CNORM_FLAGS flags) noexcept;
HRESULT ComputeTangentFrame(_In_ bool bitangents);
HRESULT ComputeTangentFrame(_In_ bool bitangents) noexcept;
HRESULT UpdateFaces(_In_ size_t nFaces, _In_reads_(nFaces * 3) const uint32_t* indices);
HRESULT UpdateFaces(_In_ size_t nFaces, _In_reads_(nFaces * 3) const uint32_t* indices) noexcept;
HRESULT UpdateAttributes(_In_ size_t nFaces, _In_reads_(nFaces * 3) const uint32_t* attributes);
HRESULT UpdateAttributes(_In_ size_t nFaces, _In_reads_(nFaces * 3) const uint32_t* attributes) noexcept;
HRESULT UpdateUVs(_In_ size_t nVerts, _In_reads_(nVerts) const DirectX::XMFLOAT2* uvs);
HRESULT UpdateUVs(_In_ size_t nVerts, _In_reads_(nVerts) const DirectX::XMFLOAT2* uvs) noexcept;
HRESULT VertexRemap(_In_reads_(nNewVerts) const uint32_t* remap, _In_ size_t nNewVerts);
HRESULT VertexRemap(_In_reads_(nNewVerts) const uint32_t* remap, _In_ size_t nNewVerts) noexcept;
HRESULT ReverseWinding();
HRESULT ReverseWinding() noexcept;
HRESULT InvertUTexCoord();
HRESULT InvertVTexCoord();
HRESULT InvertUTexCoord() noexcept;
HRESULT InvertVTexCoord() noexcept;
HRESULT ReverseHandedness();
HRESULT ReverseHandedness() noexcept;
HRESULT VisualizeUVs();
HRESULT VisualizeUVs() noexcept;
// Accessors
const uint32_t* GetAttributeBuffer() const { return mAttributes.get(); }
const uint32_t* GetAdjacencyBuffer() const { return mAdjacency.get(); }
const DirectX::XMFLOAT3* GetPositionBuffer() const { return mPositions.get(); }
const DirectX::XMFLOAT3* GetNormalBuffer() const { return mNormals.get(); }
const DirectX::XMFLOAT2* GetTexCoordBuffer() const { return mTexCoords.get(); }
const DirectX::XMFLOAT4* GetTangentBuffer() const { return mTangents.get(); }
const DirectX::XMFLOAT4* GetColorBuffer() const { return mColors.get(); }
const uint32_t* GetAttributeBuffer() const noexcept { return mAttributes.get(); }
const uint32_t* GetAdjacencyBuffer() const noexcept { return mAdjacency.get(); }
const DirectX::XMFLOAT3* GetPositionBuffer() const noexcept { return mPositions.get(); }
const DirectX::XMFLOAT3* GetNormalBuffer() const noexcept { return mNormals.get(); }
const DirectX::XMFLOAT2* GetTexCoordBuffer() const noexcept { return mTexCoords.get(); }
const DirectX::XMFLOAT4* GetTangentBuffer() const noexcept { return mTangents.get(); }
const DirectX::XMFLOAT4* GetColorBuffer() const noexcept { return mColors.get(); }
size_t GetFaceCount() const { return mnFaces; }
size_t GetVertexCount() const { return mnVerts; }
size_t GetFaceCount() const noexcept { return mnFaces; }
size_t GetVertexCount() const noexcept { return mnVerts; }
bool Is16BitIndexBuffer() const;
bool Is16BitIndexBuffer() const noexcept;
const uint32_t* GetIndexBuffer() const { return mIndices.get(); }
std::unique_ptr<uint16_t[]> GetIndexBuffer16() const;
const uint32_t* GetIndexBuffer() const noexcept { return mIndices.get(); }
std::unique_ptr<uint16_t[]> GetIndexBuffer16() const noexcept;
HRESULT GetVertexBuffer(_Inout_ DirectX::VBWriter& writer) const;
HRESULT GetVertexBuffer(_Inout_ DirectX::VBWriter& writer) const noexcept;
// Save mesh to file
struct Material
@ -146,12 +146,18 @@ public:
};
HRESULT ExportToOBJ(const wchar_t* szFileName, _In_ size_t nMaterials, _In_reads_opt_(nMaterials) const Material* materials) const;
HRESULT ExportToVBO(_In_z_ const wchar_t* szFileName) const;
HRESULT ExportToCMO(_In_z_ const wchar_t* szFileName, _In_ size_t nMaterials, _In_reads_opt_(nMaterials) const Material* materials) const;
HRESULT ExportToSDKMESH(_In_z_ const wchar_t* szFileName, _In_ size_t nMaterials, _In_reads_opt_(nMaterials) const Material* materials, bool force32bit = false, bool version2 = false) const;
HRESULT ExportToVBO(_In_z_ const wchar_t* szFileName) const noexcept;
HRESULT ExportToCMO(_In_z_ const wchar_t* szFileName, _In_ size_t nMaterials, _In_reads_opt_(nMaterials) const Material* materials) const noexcept;
HRESULT ExportToSDKMESH(_In_z_ const wchar_t* szFileName,
_In_ size_t nMaterials, _In_reads_opt_(nMaterials) const Material* materials,
bool force32bit = false,
bool version2 = false,
DXGI_FORMAT normalFormat = DXGI_FORMAT_R32G32B32_FLOAT,
DXGI_FORMAT uvFormat = DXGI_FORMAT_R32G32_FLOAT,
DXGI_FORMAT colorFormat = DXGI_FORMAT_B8G8R8A8_UNORM) const noexcept;
// Create mesh from file
static HRESULT CreateFromVBO(_In_z_ const wchar_t* szFileName, _Inout_ std::unique_ptr<Mesh>& result);
static HRESULT CreateFromVBO(_In_z_ const wchar_t* szFileName, _Inout_ std::unique_ptr<Mesh>& result) noexcept;
private:
size_t mnFaces;

View File

@ -46,122 +46,166 @@
using namespace DirectX;
enum OPTIONS
namespace
{
OPT_RECURSIVE = 1,
OPT_QUALITY,
OPT_MAXCHARTS,
OPT_MAXSTRETCH,
OPT_GUTTER,
OPT_WIDTH,
OPT_HEIGHT,
OPT_TOPOLOGICAL_ADJ,
OPT_GEOMETRIC_ADJ,
OPT_NORMALS,
OPT_WEIGHT_BY_AREA,
OPT_WEIGHT_BY_EQUAL,
OPT_TANGENTS,
OPT_CTF,
OPT_COLOR_MESH,
OPT_UV_MESH,
OPT_IMT_TEXFILE,
OPT_IMT_VERTEX,
OPT_SDKMESH,
OPT_SDKMESH_V2,
OPT_CMO,
OPT_VBO,
OPT_WAVEFRONT_OBJ,
OPT_OUTPUTFILE,
OPT_TOLOWER,
OPT_CLOCKWISE,
OPT_FORCE_32BIT_IB,
OPT_OVERWRITE,
OPT_NODDS,
OPT_FLIP,
OPT_FLIPU,
OPT_FLIPV,
OPT_FLIPZ,
OPT_NOLOGO,
OPT_FILELIST,
OPT_MAX
};
enum OPTIONS
{
OPT_RECURSIVE = 1,
OPT_QUALITY,
OPT_MAXCHARTS,
OPT_MAXSTRETCH,
OPT_GUTTER,
OPT_WIDTH,
OPT_HEIGHT,
OPT_TOPOLOGICAL_ADJ,
OPT_GEOMETRIC_ADJ,
OPT_NORMALS,
OPT_WEIGHT_BY_AREA,
OPT_WEIGHT_BY_EQUAL,
OPT_TANGENTS,
OPT_CTF,
OPT_COLOR_MESH,
OPT_UV_MESH,
OPT_IMT_TEXFILE,
OPT_IMT_VERTEX,
OPT_OUTPUTFILE,
OPT_TOLOWER,
OPT_SDKMESH,
OPT_SDKMESH_V2,
OPT_CMO,
OPT_VBO,
OPT_WAVEFRONT_OBJ,
OPT_CLOCKWISE,
OPT_FORCE_32BIT_IB,
OPT_OVERWRITE,
OPT_NODDS,
OPT_FLIP,
OPT_FLIPU,
OPT_FLIPV,
OPT_FLIPZ,
OPT_VERT_NORMAL_FORMAT,
OPT_VERT_UV_FORMAT,
OPT_VERT_COLOR_FORMAT,
OPT_NOLOGO,
OPT_FILELIST,
OPT_MAX
};
static_assert(OPT_MAX <= 64, "dwOptions is a DWORD64 bitfield");
static_assert(OPT_MAX <= 64, "dwOptions is a DWORD64 bitfield");
enum CHANNELS
{
CHANNEL_NONE = 0,
CHANNEL_NORMAL,
CHANNEL_COLOR,
CHANNEL_TEXCOORD,
};
enum CHANNELS
{
CHANNEL_NONE = 0,
CHANNEL_NORMAL,
CHANNEL_COLOR,
CHANNEL_TEXCOORD,
};
struct SConversion
{
wchar_t szSrc[MAX_PATH];
};
struct SConversion
{
wchar_t szSrc[MAX_PATH];
};
struct SValue
{
LPCWSTR pName;
DWORD dwValue;
};
struct SValue
{
LPCWSTR pName;
DWORD dwValue;
};
static const XMFLOAT3 g_ColorList[8] =
{
XMFLOAT3(1.0f, 0.5f, 0.5f),
XMFLOAT3(0.5f, 1.0f, 0.5f),
XMFLOAT3(1.0f, 1.0f, 0.5f),
XMFLOAT3(0.5f, 1.0f, 1.0f),
XMFLOAT3(1.0f, 0.5f, 0.75f),
XMFLOAT3(0.0f, 0.5f, 0.75f),
XMFLOAT3(0.5f, 0.5f, 0.75f),
XMFLOAT3(0.5f, 0.5f, 1.0f),
};
const XMFLOAT3 g_ColorList[8] =
{
XMFLOAT3(1.0f, 0.5f, 0.5f),
XMFLOAT3(0.5f, 1.0f, 0.5f),
XMFLOAT3(1.0f, 1.0f, 0.5f),
XMFLOAT3(0.5f, 1.0f, 1.0f),
XMFLOAT3(1.0f, 0.5f, 0.75f),
XMFLOAT3(0.0f, 0.5f, 0.75f),
XMFLOAT3(0.5f, 0.5f, 0.75f),
XMFLOAT3(0.5f, 0.5f, 1.0f),
};
//////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////
const SValue g_pOptions[] =
{
{ L"r", OPT_RECURSIVE },
{ L"q", OPT_QUALITY },
{ L"n", OPT_MAXCHARTS },
{ L"st", OPT_MAXSTRETCH },
{ L"g", OPT_GUTTER },
{ L"w", OPT_WIDTH },
{ L"h", OPT_HEIGHT },
{ L"ta", OPT_TOPOLOGICAL_ADJ },
{ L"ga", OPT_GEOMETRIC_ADJ },
{ L"nn", OPT_NORMALS },
{ L"na", OPT_WEIGHT_BY_AREA },
{ L"ne", OPT_WEIGHT_BY_EQUAL },
{ L"tt", OPT_TANGENTS },
{ L"tb", OPT_CTF },
{ L"c", OPT_COLOR_MESH },
{ L"t", OPT_UV_MESH },
{ L"it", OPT_IMT_TEXFILE },
{ L"iv", OPT_IMT_VERTEX },
{ L"o", OPT_OUTPUTFILE },
{ L"l", OPT_TOLOWER },
{ L"sdkmesh", OPT_SDKMESH },
{ L"sdkmesh2", OPT_SDKMESH_V2 },
{ L"cmo", OPT_CMO },
{ L"vbo", OPT_VBO },
{ L"wf", OPT_WAVEFRONT_OBJ },
{ L"cw", OPT_CLOCKWISE },
{ L"ib32", OPT_FORCE_32BIT_IB },
{ L"y", OPT_OVERWRITE },
{ L"nodds", OPT_NODDS },
{ L"flip", OPT_FLIP },
{ L"flipu", OPT_FLIPU },
{ L"flipv", OPT_FLIPV },
{ L"flipz", OPT_FLIPZ },
{ L"fn", OPT_VERT_NORMAL_FORMAT },
{ L"fuv", OPT_VERT_UV_FORMAT },
{ L"fc", OPT_VERT_COLOR_FORMAT },
{ L"nologo", OPT_NOLOGO },
{ L"flist", OPT_FILELIST },
{ nullptr, 0 }
};
const SValue g_vertexNormalFormats[] =
{
{ L"float3", DXGI_FORMAT_R32G32B32_FLOAT },
{ L"float16_4", DXGI_FORMAT_R16G16B16A16_FLOAT },
{ L"r11g11b10", DXGI_FORMAT_R11G11B10_FLOAT },
{ nullptr, 0 }
};
const SValue g_vertexUVFormats[] =
{
{ L"float2", DXGI_FORMAT_R32G32_FLOAT },
{ L"float16_2", DXGI_FORMAT_R16G16_FLOAT },
{ nullptr, 0 }
};
const SValue g_vertexColorFormats[] =
{
{ L"bgra", DXGI_FORMAT_B8G8R8A8_UNORM },
{ L"rgba", DXGI_FORMAT_R8G8B8A8_UNORM },
{ L"float4", DXGI_FORMAT_R32G32B32A32_FLOAT },
{ L"float16_4", DXGI_FORMAT_R16G16B16A16_FLOAT },
{ L"rgba_10", DXGI_FORMAT_R10G10B10A2_UNORM },
{ L"r11g11b10", DXGI_FORMAT_R11G11B10_FLOAT },
{ nullptr, 0 }
};
}
//////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////
const SValue g_pOptions [] =
{
{ L"r", OPT_RECURSIVE },
{ L"q", OPT_QUALITY },
{ L"n", OPT_MAXCHARTS },
{ L"st", OPT_MAXSTRETCH },
{ L"g", OPT_GUTTER },
{ L"w", OPT_WIDTH },
{ L"h", OPT_HEIGHT },
{ L"ta", OPT_TOPOLOGICAL_ADJ },
{ L"ga", OPT_GEOMETRIC_ADJ },
{ L"nn", OPT_NORMALS },
{ L"na", OPT_WEIGHT_BY_AREA },
{ L"ne", OPT_WEIGHT_BY_EQUAL },
{ L"tt", OPT_TANGENTS },
{ L"tb", OPT_CTF },
{ L"c", OPT_COLOR_MESH },
{ L"t", OPT_UV_MESH },
{ L"it", OPT_IMT_TEXFILE },
{ L"iv", OPT_IMT_VERTEX },
{ L"o", OPT_OUTPUTFILE },
{ L"l", OPT_TOLOWER },
{ L"sdkmesh", OPT_SDKMESH },
{ L"sdkmesh2", OPT_SDKMESH_V2 },
{ L"cmo", OPT_CMO },
{ L"vbo", OPT_VBO },
{ L"wf", OPT_WAVEFRONT_OBJ },
{ L"cw", OPT_CLOCKWISE },
{ L"ib32", OPT_FORCE_32BIT_IB },
{ L"y", OPT_OVERWRITE },
{ L"nodds", OPT_NODDS },
{ L"flip", OPT_FLIP },
{ L"flipu", OPT_FLIPU },
{ L"flipv", OPT_FLIPV },
{ L"flipz", OPT_FLIPZ },
{ L"nologo", OPT_NOLOGO },
{ L"flist", OPT_FILELIST },
{ nullptr, 0 }
};
HRESULT LoadFromOBJ(const wchar_t* szFilename,
std::unique_ptr<Mesh>& inMesh, std::vector<Mesh::Material>& inMaterial,
bool ccw, bool dds);
//////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////
@ -169,9 +213,9 @@ const SValue g_pOptions [] =
namespace
{
inline HANDLE safe_handle(HANDLE h) { return (h == INVALID_HANDLE_VALUE) ? nullptr : h; }
inline HANDLE safe_handle(HANDLE h) noexcept { return (h == INVALID_HANDLE_VALUE) ? nullptr : h; }
struct find_closer { void operator()(HANDLE h) { assert(h != INVALID_HANDLE_VALUE); if (h) FindClose(h); } };
struct find_closer { void operator()(HANDLE h) noexcept { assert(h != INVALID_HANDLE_VALUE); if (h) FindClose(h); } };
using ScopedFindHandle = std::unique_ptr<void, find_closer>;
@ -179,7 +223,7 @@ namespace
#pragma prefast(disable : 26018, "Only used with static internal arrays")
#endif
DWORD LookupByName(const wchar_t *pName, const SValue *pArray)
DWORD LookupByName(const wchar_t* pName, const SValue* pArray)
{
while (pArray->pName)
{
@ -267,6 +311,25 @@ namespace
}
}
void PrintList(size_t cch, const SValue* pValue)
{
while (pValue->pName)
{
size_t cchName = wcslen(pValue->pName);
if (cch + cchName + 2 >= 80)
{
wprintf(L"\n ");
cch = 6;
}
wprintf(L"%ls ", pValue->pName);
cch += cchName + 2;
pValue++;
}
wprintf(L"\n");
}
void PrintLogo()
{
@ -304,7 +367,6 @@ namespace
wprintf(L" -tt generate tangents\n");
wprintf(L" -tb generate tangents & bi-tangents\n");
wprintf(L" -cw faces are clockwise (defaults to counter-clockwise)\n");
wprintf(L" -ib32 use 32-bit index buffer (SDKMESH only)\n");
wprintf(L" -c generate mesh with colors showing charts\n");
wprintf(L" -t generates a separate mesh with uvs - (*_texture)\n");
wprintf(L" -it <filename> calculate IMT for the mesh using this texture map\n");
@ -321,8 +383,20 @@ namespace
wprintf(L" -y overwrite existing output file (if any)\n");
wprintf(L" -nologo suppress copyright message\n");
wprintf(L" -flist <filename> use text file with a list of input files (one per line)\n");
wprintf(L"\n (sdkmesh/sdkmesh2 only)\n");
wprintf(L" -ib32 use 32-bit index buffer\n");
wprintf(L" -fn <normal-format> format to use for writing normals/tangents/normals\n");
wprintf(L" -fuv <uv-format> format to use for texture coordinates\n");
wprintf(L" -fc <color-format> format to use for writing colors\n");
wprintf(L"\n");
wprintf(L"\n <normal-format>: ");
PrintList(13, g_vertexNormalFormats);
wprintf(L"\n <uv-format>: ");
PrintList(13, g_vertexUVFormats);
wprintf(L"\n <color-format>: ");
PrintList(13, g_vertexColorFormats);
}
@ -352,8 +426,6 @@ namespace
}
}
extern HRESULT LoadFromOBJ(const wchar_t* szFilename, std::unique_ptr<Mesh>& inMesh, std::vector<Mesh::Material>& inMaterial, bool ccw, bool dds);
//--------------------------------------------------------------------------------------
// Entry-point
//--------------------------------------------------------------------------------------
@ -371,6 +443,9 @@ int __cdecl wmain(_In_ int argc, _In_z_count_(argc) wchar_t* argv[])
size_t height = 512;
CHANNELS perVertex = CHANNEL_NONE;
DWORD uvOptions = UVATLAS_DEFAULT;
DXGI_FORMAT normalFormat = DXGI_FORMAT_R32G32B32_FLOAT;
DXGI_FORMAT uvFormat = DXGI_FORMAT_R32G32_FLOAT;
DXGI_FORMAT colorFormat = DXGI_FORMAT_B8G8R8A8_UNORM;
wchar_t szTexFile[MAX_PATH] = {};
wchar_t szOutputFile[MAX_PATH] = {};
@ -424,6 +499,9 @@ int __cdecl wmain(_In_ int argc, _In_z_count_(argc) wchar_t* argv[])
case OPT_IMT_TEXFILE:
case OPT_IMT_VERTEX:
case OPT_OUTPUTFILE:
case OPT_VERT_NORMAL_FORMAT:
case OPT_VERT_UV_FORMAT:
case OPT_VERT_COLOR_FORMAT:
case OPT_FILELIST:
if (!*pValue)
{
@ -616,6 +694,39 @@ int __cdecl wmain(_In_ int argc, _In_z_count_(argc) wchar_t* argv[])
}
break;
case OPT_VERT_NORMAL_FORMAT:
normalFormat = static_cast<DXGI_FORMAT>(LookupByName(pValue, g_vertexNormalFormats));
if (!normalFormat)
{
wprintf(L"Invalid value specified with -fn (%ls)\n", pValue);
wprintf(L"\n");
PrintUsage();
return 1;
}
break;
case OPT_VERT_UV_FORMAT:
uvFormat = static_cast<DXGI_FORMAT>(LookupByName(pValue, g_vertexUVFormats));
if (!uvFormat)
{
wprintf(L"Invalid value specified with -fuv (%ls)\n", pValue);
wprintf(L"\n");
PrintUsage();
return 1;
}
break;
case OPT_VERT_COLOR_FORMAT:
colorFormat = static_cast<DXGI_FORMAT>(LookupByName(pValue, g_vertexColorFormats));
if (!colorFormat)
{
wprintf(L"Invalid value specified with -fc (%ls)\n", pValue);
wprintf(L"\n");
PrintUsage();
return 1;
}
break;
case OPT_FILELIST:
{
std::wifstream inFile(pValue);
@ -1254,7 +1365,10 @@ int __cdecl wmain(_In_ int argc, _In_z_count_(argc) wchar_t* argv[])
outputPath,
inMaterial.size(), inMaterial.empty() ? nullptr : inMaterial.data(),
(dwOptions & (DWORD64(1) << OPT_FORCE_32BIT_IB)) ? true : false,
(dwOptions & (DWORD64(1) << OPT_SDKMESH_V2)) ? true : false);
(dwOptions & (DWORD64(1) << OPT_SDKMESH_V2)) ? true : false,
normalFormat,
uvFormat,
colorFormat);
}
else if (!_wcsicmp(outputExt, L".cmo"))
{
@ -1336,7 +1450,10 @@ int __cdecl wmain(_In_ int argc, _In_z_count_(argc) wchar_t* argv[])
outputPath,
inMaterial.size(), inMaterial.empty() ? nullptr : inMaterial.data(),
(dwOptions & (DWORD64(1) << OPT_FORCE_32BIT_IB)) ? true : false,
(dwOptions & (DWORD64(1) << OPT_SDKMESH_V2)) ? true : false);
(dwOptions & (DWORD64(1) << OPT_SDKMESH_V2)) ? true : false,
normalFormat,
uvFormat,
colorFormat);
}
else if (!_wcsicmp(outputExt, L".cmo"))
{

View File

@ -139,6 +139,7 @@
<ConformanceMode>true</ConformanceMode>
<AdditionalOptions>/Zc:__cplusplus /Zc:twoPhase- %(AdditionalOptions)</AdditionalOptions>
<OpenMPSupport>true</OpenMPSupport>
<DisableSpecificWarnings>26812</DisableSpecificWarnings>
</ClCompile>
<Link>
<AdditionalDependencies>ole32.lib;windowscodecs.lib;uuid.lib;%(AdditionalDependencies)</AdditionalDependencies>
@ -171,6 +172,7 @@
<ConformanceMode>true</ConformanceMode>
<AdditionalOptions>/Zc:__cplusplus /Zc:twoPhase- %(AdditionalOptions)</AdditionalOptions>
<OpenMPSupport>true</OpenMPSupport>
<DisableSpecificWarnings>26812</DisableSpecificWarnings>
</ClCompile>
<Link>
<AdditionalDependencies>ole32.lib;windowscodecs.lib;uuid.lib;%(AdditionalDependencies)</AdditionalDependencies>
@ -202,6 +204,7 @@
<ConformanceMode>true</ConformanceMode>
<AdditionalOptions>/Zc:__cplusplus /Zc:twoPhase- %(AdditionalOptions)</AdditionalOptions>
<OpenMPSupport>true</OpenMPSupport>
<DisableSpecificWarnings>26812</DisableSpecificWarnings>
</ClCompile>
<Link>
<AdditionalDependencies>ole32.lib;oleaut32.lib;windowscodecs.lib;uuid.lib;%(AdditionalDependencies)</AdditionalDependencies>
@ -235,6 +238,7 @@
<ConformanceMode>true</ConformanceMode>
<AdditionalOptions>/Zc:__cplusplus /Zc:twoPhase- %(AdditionalOptions)</AdditionalOptions>
<OpenMPSupport>true</OpenMPSupport>
<DisableSpecificWarnings>26812</DisableSpecificWarnings>
</ClCompile>
<Link>
<AdditionalDependencies>ole32.lib;oleaut32.lib;windowscodecs.lib;uuid.lib;%(AdditionalDependencies)</AdditionalDependencies>
@ -267,6 +271,7 @@
<ControlFlowGuard>Guard</ControlFlowGuard>
<ConformanceMode>true</ConformanceMode>
<AdditionalOptions>/Zc:__cplusplus %(AdditionalOptions)</AdditionalOptions>
<DisableSpecificWarnings>26812</DisableSpecificWarnings>
</ClCompile>
<Link>
<AdditionalDependencies>ole32.lib;oleaut32.lib;windowscodecs.lib;uuid.lib;%(AdditionalDependencies)</AdditionalDependencies>
@ -299,6 +304,7 @@
<ControlFlowGuard>Guard</ControlFlowGuard>
<ConformanceMode>true</ConformanceMode>
<AdditionalOptions>/Zc:__cplusplus %(AdditionalOptions)</AdditionalOptions>
<DisableSpecificWarnings>26812</DisableSpecificWarnings>
</ClCompile>
<Link>
<AdditionalDependencies>ole32.lib;oleaut32.lib;windowscodecs.lib;uuid.lib;%(AdditionalDependencies)</AdditionalDependencies>