mirror of
https://github.com/microsoft/UVAtlas
synced 2024-11-09 13:50:05 +00:00
Code review and more work on WaveFront OBJ export
This commit is contained in:
parent
c3cf5b6c00
commit
2bbef8687c
@ -290,7 +290,6 @@ HRESULT CIsochartEngine::ParameterizeChartsInHeapParallelized(
|
||||
parent.emplace_back(m_currentChartHeap.cutTopData());
|
||||
|
||||
HRESULT hrOut = S_OK;
|
||||
int runs = 0;
|
||||
while (!parent.empty() && !FAILED(hrOut))
|
||||
{
|
||||
std::vector<CIsochartMesh*> children;
|
||||
|
@ -28,8 +28,6 @@
|
||||
#include <DirectXCollision.h>
|
||||
#include <UVAtlas.h>
|
||||
|
||||
#include <fstream>
|
||||
|
||||
using namespace DirectX;
|
||||
|
||||
namespace
|
||||
|
@ -42,7 +42,6 @@ public:
|
||||
void Clear();
|
||||
|
||||
void SetMTLFileName(const std::wstring& name) { mtlFileName = name; }
|
||||
void SetFirstMaterialName(const std::wstring& name) { firstMaterialName = 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);
|
||||
@ -146,7 +145,7 @@ public:
|
||||
}
|
||||
};
|
||||
|
||||
HRESULT ExportToOBJ(const wchar_t* szFileName) const;
|
||||
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;
|
||||
@ -170,8 +169,6 @@ private:
|
||||
std::unique_ptr<DirectX::XMFLOAT4[]> mBlendWeights;
|
||||
|
||||
std::wstring mtlFileName;
|
||||
std::wstring firstMaterialName;
|
||||
|
||||
HRESULT ExportToOBJ(std::string filePath) const;
|
||||
void ExportToOBJ(std::wostream& os) const;
|
||||
void ExportToOBJ(std::wostream& os, _In_ size_t nMaterials, _In_reads_opt_(nMaterials) const Material* materials) const;
|
||||
};
|
||||
|
@ -49,6 +49,7 @@ namespace
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------
|
||||
HRESULT LoadFromOBJ(
|
||||
const wchar_t* szFilename,
|
||||
std::unique_ptr<Mesh>& inMesh,
|
||||
@ -149,62 +150,96 @@ HRESULT LoadFromOBJ(
|
||||
if (wfReader.materials.size() > 1)
|
||||
{
|
||||
inMesh->SetMTLFileName(wfReader.name);
|
||||
inMesh->SetFirstMaterialName(wfReader.materials[1].strName);
|
||||
}
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------
|
||||
HRESULT Mesh::ExportToOBJ(std::string filePath) const
|
||||
{
|
||||
return ExportToOBJ(std::wstring(filePath.begin(), filePath.end()).c_str());
|
||||
}
|
||||
/// Write to file
|
||||
HRESULT Mesh::ExportToOBJ(const wchar_t* szFileName) const
|
||||
_Use_decl_annotations_
|
||||
HRESULT Mesh::ExportToOBJ(const wchar_t* szFileName, size_t nMaterials, const Material* materials) const
|
||||
{
|
||||
if (!szFileName)
|
||||
return E_INVALIDARG;
|
||||
|
||||
if (nMaterials > 0 && !materials)
|
||||
return E_INVALIDARG;
|
||||
|
||||
std::wofstream os;
|
||||
os.open(szFileName);
|
||||
ExportToOBJ(os);
|
||||
if (!os)
|
||||
return E_FAIL;
|
||||
|
||||
os << L"# " << szFileName << std::endl << L"#" << std::endl << std::endl;
|
||||
|
||||
ExportToOBJ(os, nMaterials, materials);
|
||||
|
||||
os.close();
|
||||
|
||||
return (os.bad()) ? E_FAIL : S_OK;
|
||||
}
|
||||
/// Writing to cout or to a file stream
|
||||
void Mesh::ExportToOBJ(std::wostream& os) const
|
||||
|
||||
_Use_decl_annotations_
|
||||
void Mesh::ExportToOBJ(std::wostream& os, size_t nMaterials, const Material* materials) const
|
||||
{
|
||||
if (!mtlFileName.empty())
|
||||
os << "mtllib ./" << mtlFileName << ".mtl" << std::endl; // https://stackoverflow.com/questions/4804298/how-to-convert-wstring-into-string converting wstring to string this way works for almost everything except chinese characters
|
||||
os << L"mtllib ./" << mtlFileName << L".mtl" << std::endl;
|
||||
|
||||
for (size_t vert = 0; vert < mnVerts; ++vert)
|
||||
os << "v " << mPositions[vert].x << " " << mPositions[vert].y << " " << mPositions[vert].z << std::endl;
|
||||
{
|
||||
os << L"v " << mPositions[vert].x << L" " << mPositions[vert].y << L" " << mPositions[vert].z << std::endl;
|
||||
}
|
||||
os << std::endl;
|
||||
|
||||
if (mTexCoords)
|
||||
for (size_t vert = 0; vert < mnVerts; ++vert) // in this Mesh format the number of texture vertices is always the same as mnVerts
|
||||
os << "vt " << mTexCoords[vert].x << " " << mTexCoords[vert].y << std::endl;
|
||||
{
|
||||
for (size_t vert = 0; vert < mnVerts; ++vert)
|
||||
{
|
||||
os << L"vt " << mTexCoords[vert].x << L" " << mTexCoords[vert].y << std::endl;
|
||||
}
|
||||
os << std::endl;
|
||||
}
|
||||
|
||||
if (mNormals)
|
||||
for (size_t vert = 0; vert < mnVerts; ++vert) // in this Mesh format the number of texture vertices is always the same as mnVerts
|
||||
os << "vn " << mNormals[vert].x << " " << mNormals[vert].y << " " << mNormals[vert].z << std::endl;
|
||||
{
|
||||
for (size_t vert = 0; vert < mnVerts; ++vert)
|
||||
{
|
||||
os << L"vn " << mNormals[vert].x << L" " << mNormals[vert].y << L" " << mNormals[vert].z << std::endl;
|
||||
}
|
||||
os << std::endl;
|
||||
}
|
||||
|
||||
// Using the first material entry as they are all the same for our use cases
|
||||
if (!firstMaterialName.empty())
|
||||
os << "usemtl " << firstMaterialName << std::endl; // https://stackoverflow.com/questions/4804298/how-to-convert-wstring-into-string converting wstring to string this way works for almost everything except chinese characters
|
||||
if (!materials || !mAttributes)
|
||||
{
|
||||
os << L"usemtl default" << std::endl;
|
||||
}
|
||||
|
||||
/// Now the faces, a face is the first 3 indexes in indexes on the faces vertex
|
||||
uint32_t lastAttribute = uint32_t(-1);
|
||||
for (size_t face = 0; face < mnFaces; ++face)
|
||||
{
|
||||
os << "f ";
|
||||
if (mAttributes && mAttributes[face] != lastAttribute)
|
||||
{
|
||||
lastAttribute = mAttributes[face];
|
||||
if (lastAttribute < nMaterials)
|
||||
{
|
||||
os << L"usemtl " << materials[lastAttribute].name << std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
os << L"f ";
|
||||
for (size_t point = 0; point < 3; ++point)
|
||||
{
|
||||
auto i = mIndices[face * 3 + point] + 1;
|
||||
uint32_t i = mIndices[face * 3 + point] + 1;
|
||||
|
||||
os << i << "/";
|
||||
os << i << L"/";
|
||||
if (mTexCoords)
|
||||
os << i;
|
||||
os << "/";
|
||||
os << L"/";
|
||||
if (mNormals)
|
||||
os << i;
|
||||
os << " ";
|
||||
os << L" ";
|
||||
}
|
||||
os << std::endl;
|
||||
}
|
||||
|
@ -70,6 +70,7 @@ enum OPTIONS
|
||||
OPT_SDKMESH_V2,
|
||||
OPT_CMO,
|
||||
OPT_VBO,
|
||||
OPT_WAVEFRONT_OBJ,
|
||||
OPT_OUTPUTFILE,
|
||||
OPT_CLOCKWISE,
|
||||
OPT_FORCE_32BIT_IB,
|
||||
@ -146,6 +147,7 @@ const SValue g_pOptions [] =
|
||||
{ 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 },
|
||||
@ -281,12 +283,13 @@ namespace
|
||||
|
||||
wprintf(L"Usage: uvatlas <options> <files>\n");
|
||||
wprintf(L"\n");
|
||||
wprintf(L" Input file type must be Wavefront OBJ\n\n");
|
||||
wprintf(L" Input file type must be Wavefront Object (.obj)\n\n");
|
||||
wprintf(L" Output file type:\n");
|
||||
wprintf(L" -sdkmesh DirectX SDK .sdkmesh format (default)\n");
|
||||
wprintf(L" -sdkmesh2 .sdkmesh format version 2 (PBR materials)\n");
|
||||
wprintf(L" -cmo Visual Studio Content Pipeline .cmo format\n");
|
||||
wprintf(L" -vbo Vertex Buffer Object (.vbo) format\n\n");
|
||||
wprintf(L" -wf WaveFront Object (.obj) format\n\n");
|
||||
wprintf(L" -r wildcard filename search is recursive\n");
|
||||
wprintf(L" -q <level> sets quality level to DEFAULT, FAST or QUALITY\n");
|
||||
wprintf(L" -n <number> maximum number of charts to generate (def: 0)\n");
|
||||
@ -575,9 +578,9 @@ int __cdecl wmain(_In_ int argc, _In_z_count_(argc) wchar_t* argv[])
|
||||
|
||||
case OPT_SDKMESH:
|
||||
case OPT_SDKMESH_V2:
|
||||
if (dwOptions & ((DWORD64(1) << OPT_VBO) | (DWORD64(1) << OPT_CMO)))
|
||||
if (dwOptions & ((DWORD64(1) << OPT_VBO) | (DWORD64(1) << OPT_CMO) | (DWORD64(1) << OPT_WAVEFRONT_OBJ)))
|
||||
{
|
||||
wprintf(L"Can only use one of sdkmesh, cmo, or vbo\n");
|
||||
wprintf(L"Can only use one of sdkmesh, cmo, vbo, or wf\n");
|
||||
return 1;
|
||||
}
|
||||
if (dwOption == OPT_SDKMESH_V2)
|
||||
@ -587,17 +590,25 @@ int __cdecl wmain(_In_ int argc, _In_z_count_(argc) wchar_t* argv[])
|
||||
break;
|
||||
|
||||
case OPT_CMO:
|
||||
if (dwOptions & ((DWORD64(1) << OPT_VBO) | (DWORD64(1) << OPT_SDKMESH)))
|
||||
if (dwOptions & ((DWORD64(1) << OPT_VBO) | (DWORD64(1) << OPT_SDKMESH) | (DWORD64(1) << OPT_WAVEFRONT_OBJ)))
|
||||
{
|
||||
wprintf(L"Can only use one of sdkmesh, cmo, or vbo\n");
|
||||
wprintf(L"Can only use one of sdkmesh, cmo, vbo, or wf\n");
|
||||
return 1;
|
||||
}
|
||||
break;
|
||||
|
||||
case OPT_VBO:
|
||||
if (dwOptions & ((DWORD64(1) << OPT_SDKMESH) | (DWORD64(1) << OPT_CMO)))
|
||||
if (dwOptions & ((DWORD64(1) << OPT_SDKMESH) | (DWORD64(1) << OPT_CMO) | (DWORD64(1) << OPT_WAVEFRONT_OBJ)))
|
||||
{
|
||||
wprintf(L"Can only use one of sdkmesh, cmo, or vbo\n");
|
||||
wprintf(L"Can only use one of sdkmesh, cmo, vbo, or wf\n");
|
||||
return 1;
|
||||
}
|
||||
break;
|
||||
|
||||
case OPT_WAVEFRONT_OBJ:
|
||||
if (dwOptions & ((DWORD64(1) << OPT_VBO) | (DWORD64(1) << OPT_SDKMESH) | (DWORD64(1) << OPT_CMO)))
|
||||
{
|
||||
wprintf(L"Can only use one of sdkmesh, cmo, vbo, or wf\n");
|
||||
return 1;
|
||||
}
|
||||
break;
|
||||
@ -1190,6 +1201,10 @@ int __cdecl wmain(_In_ int argc, _In_z_count_(argc) wchar_t* argv[])
|
||||
{
|
||||
wcscpy_s(outputExt, L".cmo");
|
||||
}
|
||||
else if (dwOptions & (DWORD64(1) << OPT_WAVEFRONT_OBJ))
|
||||
{
|
||||
wcscpy_s(outputExt, L".obj");
|
||||
}
|
||||
else
|
||||
{
|
||||
wcscpy_s(outputExt, L".sdkmesh");
|
||||
@ -1250,9 +1265,9 @@ int __cdecl wmain(_In_ int argc, _In_z_count_(argc) wchar_t* argv[])
|
||||
|
||||
hr = inMesh->ExportToCMO(outputPath, inMaterial.size(), inMaterial.empty() ? nullptr : inMaterial.data());
|
||||
}
|
||||
else if (!_wcsicmp(outputExt, L".obj"))
|
||||
else if (!_wcsicmp(outputExt, L".obj") || !_wcsicmp(outputExt, L"._obj"))
|
||||
{
|
||||
hr = inMesh->ExportToOBJ(outputPath);
|
||||
hr = inMesh->ExportToOBJ(outputPath, inMaterial.size(), inMaterial.empty() ? nullptr : inMaterial.data());
|
||||
}
|
||||
else if (!_wcsicmp(outputExt, L".x"))
|
||||
{
|
||||
|
Loading…
Reference in New Issue
Block a user