Big f***ing cleanup part 1

This commit is contained in:
Lynix
2020-02-23 00:42:22 +01:00
parent 67d0e0a689
commit 3d22321109
178 changed files with 2190 additions and 5113 deletions

View File

@@ -18,7 +18,7 @@ namespace Nz
DDSLoader() = delete;
~DDSLoader() = delete;
static bool IsSupported(const String& extension)
static bool IsSupported(const std::string& extension)
{
return (extension == "dds");
}

View File

@@ -320,9 +320,9 @@ namespace Nz
return characterSize/15.f; // Joker ?
}
bool SetFile(const String& filePath)
bool SetFile(const std::filesystem::path& filePath)
{
std::unique_ptr<File> file(new File);
std::unique_ptr<File> file = std::make_unique<File>();
if (!file->Open(filePath, OpenMode_ReadOnly))
{
NazaraError("Failed to open stream from file: " + Error::GetLastError());
@@ -336,7 +336,7 @@ namespace Nz
void SetMemory(const void* data, std::size_t size)
{
m_ownedStream.reset(new MemoryView(data, size));
m_ownedStream = std::make_unique<MemoryView>(data, size);
SetStream(*m_ownedStream);
}
@@ -349,14 +349,14 @@ namespace Nz
m_stream.pos = 0;
m_stream.size = static_cast<unsigned long>(stream.GetSize());
m_args.driver = 0;
m_args.driver = nullptr;
m_args.flags = FT_OPEN_STREAM;
m_args.stream = &m_stream;
}
bool SupportsOutline(float /*outlineThickness*/) const override
{
return s_stroker != 0;
return s_stroker != nullptr;
}
bool SupportsStyle(TextStyleFlags style) const override
@@ -383,10 +383,10 @@ namespace Nz
mutable unsigned int m_characterSize;
};
bool IsSupported(const String& extension)
bool IsSupported(const std::string& extension)
{
///FIXME: Je suppose qu'il en manque quelques unes..
static std::set<String> supportedExtensions = {
static std::set<std::string> supportedExtensions = {
"afm", "bdf", "cff", "cid", "dfont", "fnt", "fon", "otf", "pfa", "pfb", "pfm", "pfr", "sfnt", "ttc", "tte", "ttf"
};
@@ -408,12 +408,11 @@ namespace Nz
return Ternary_False;
}
FontRef LoadFile(const String& filePath, const FontParams& parameters)
FontRef LoadFile(const std::filesystem::path& filePath, const FontParams& parameters)
{
NazaraUnused(parameters);
std::unique_ptr<FreeTypeStream> face(new FreeTypeStream);
std::unique_ptr<FreeTypeStream> face = std::make_unique<FreeTypeStream>();
if (!face->SetFile(filePath))
{
NazaraError("Failed to open file");

View File

@@ -20,7 +20,7 @@ namespace Nz
{
namespace
{
bool IsSupported(const String& extension)
bool IsSupported(const std::string& extension)
{
return (extension == "md2");
}
@@ -93,14 +93,14 @@ namespace Nz
mesh->SetMaterialCount(header.num_skins);
stream.SetCursorPos(header.offset_skins);
{
String baseDir = stream.GetDirectory();
std::filesystem::path baseDir = stream.GetDirectory();
char skin[68];
for (unsigned int i = 0; i < header.num_skins; ++i)
{
stream.Read(skin, 68*sizeof(char));
ParameterList matData;
matData.SetParameter(MaterialData::DiffuseTexturePath, baseDir + skin);
matData.SetParameter(MaterialData::DiffuseTexturePath, (baseDir / skin).generic_u8string());
mesh->SetMaterialData(i, std::move(matData));
}
@@ -196,10 +196,8 @@ namespace Nz
Vector2f invSkinSize(1.f / header.skinwidth, 1.f / header.skinheight);
for (unsigned int i = 0; i < header.num_tris; ++i)
{
for (unsigned int j = 0; j < 3; ++j)
for (unsigned int fixedIndex : indexFix) //< Reverse winding order
{
const unsigned int fixedIndex = indexFix[j]; //< Reverse winding order
const MD2_TexCoord& texC = texCoords[triangles[i].texCoords[fixedIndex]];
Vector2f uv(texC.u, texC.v);
uv *= invSkinSize;

View File

@@ -3,7 +3,6 @@
// For conditions of distribution and use, see copyright notice in Config.hpp
#include <Nazara/Utility/Formats/MD5AnimLoader.hpp>
#include <Nazara/Core/Directory.hpp>
#include <Nazara/Utility/Formats/MD5AnimParser.hpp>
#include <Nazara/Utility/Animation.hpp>
#include <Nazara/Utility/Sequence.hpp>
@@ -13,7 +12,7 @@ namespace Nz
{
namespace
{
bool IsSupported(const String& extension)
bool IsSupported(const std::string& extension)
{
return (extension == "md5anim");
}
@@ -40,10 +39,10 @@ namespace Nz
}
const MD5AnimParser::Frame* frames = parser.GetFrames();
UInt32 frameCount = parser.GetFrameCount();
UInt32 frameRate = parser.GetFrameRate();
std::size_t frameCount = parser.GetFrameCount();
std::size_t frameRate = parser.GetFrameRate();
const MD5AnimParser::Joint* joints = parser.GetJoints();
UInt32 jointCount = parser.GetJointCount();
std::size_t jointCount = parser.GetJointCount();
// À ce stade, nous sommes censés avoir assez d'informations pour créer l'animation
AnimationRef animation = Animation::New();
@@ -53,7 +52,7 @@ namespace Nz
sequence.firstFrame = 0;
sequence.frameCount = frameCount;
sequence.frameRate = frameRate;
sequence.name = stream.GetPath().SubStringFrom(NAZARA_DIRECTORY_SEPARATOR, -1, true);
sequence.name = stream.GetPath().filename().generic_u8string();
animation->AddSequence(sequence);
@@ -63,10 +62,10 @@ namespace Nz
Quaternionf rotationQuat = Quaternionf::RotationBetween(Vector3f::UnitX(), Vector3f::Forward()) *
Quaternionf::RotationBetween(Vector3f::UnitZ(), Vector3f::Up());
for (UInt32 i = 0; i < jointCount; ++i)
for (std::size_t i = 0; i < jointCount; ++i)
{
int parent = joints[i].parent;
for (UInt32 j = 0; j < frameCount; ++j)
for (std::size_t j = 0; j < frameCount; ++j)
{
SequenceJoint& sequenceJoint = sequenceJoints[j*jointCount + i];

View File

@@ -20,7 +20,7 @@ namespace Nz
{
namespace
{
bool IsSupported(const String& extension)
bool IsSupported(const std::string& extension)
{
return (extension == "md5mesh");
}
@@ -48,7 +48,7 @@ namespace Nz
Quaternionf rotationQuat = Quaternionf::RotationBetween(Vector3f::UnitX(), Vector3f::Forward()) *
Quaternionf::RotationBetween(Vector3f::UnitZ(), Vector3f::Up());
String baseDir = stream.GetDirectory();
std::filesystem::path baseDir = stream.GetDirectory();
// Le hellknight de Doom 3 fait ~120 unités, et il est dit qu'il fait trois mètres
// Nous réduisons donc la taille générale des fichiers MD5 de 1/40
@@ -198,7 +198,7 @@ namespace Nz
// Material
ParameterList matData;
matData.SetParameter(MaterialData::FilePath, baseDir + md5Mesh.shader);
matData.SetParameter(MaterialData::FilePath, (baseDir / md5Mesh.shader).generic_u8string());
mesh->SetMaterialData(i, std::move(matData));
@@ -211,11 +211,11 @@ namespace Nz
// Animation
// Il est peut-être éventuellement possible que la probabilité que l'animation ait le même nom soit non-nulle.
String path = stream.GetPath();
if (!path.IsEmpty())
std::filesystem::path path = stream.GetPath();
if (!path.empty())
{
path.Replace(".md5mesh", ".md5anim", -8, String::CaseInsensitive);
if (File::Exists(path))
path.replace_extension(".md5anim");
if (std::filesystem::exists(path))
mesh->SetAnimation(path);
}
}
@@ -306,7 +306,7 @@ namespace Nz
// Material
ParameterList matData;
matData.SetParameter(MaterialData::FilePath, baseDir + md5Mesh.shader);
matData.SetParameter(MaterialData::FilePath, (baseDir / md5Mesh.shader).generic_u8string());
mesh->SetMaterialData(i, std::move(matData));
}

View File

@@ -4,6 +4,7 @@
#include <Nazara/Utility/Formats/MD5MeshParser.hpp>
#include <Nazara/Core/Error.hpp>
#include <Nazara/Core/StringExt.hpp>
#include <Nazara/Utility/Config.hpp>
#include <cstdio>
#include <memory>
@@ -71,19 +72,19 @@ namespace Nz
{
#if NAZARA_UTILITY_STRICT_RESOURCE_PARSING
case 'M': // MD5Version
if (m_currentLine.GetWord(0) != "MD5Version")
if (!StartsWith(m_currentLine, "MD5Version "))
UnrecognizedLine();
break;
case 'c': // commandline
if (m_currentLine.GetWord(0) != "commandline")
if (!StartsWith(m_currentLine, "commandline "))
UnrecognizedLine();
break;
#endif
case 'j': // joints
#if NAZARA_UTILITY_STRICT_RESOURCE_PARSING
if (!m_currentLine.StartsWith("joints {"))
if (!StartsWith(m_currentLine, "joints {"))
{
UnrecognizedLine();
break;
@@ -100,7 +101,7 @@ namespace Nz
case 'm': // mesh
{
#if NAZARA_UTILITY_STRICT_RESOURCE_PARSING
if (m_currentLine != "mesh {")
if (!StartsWith(m_currentLine, "mesh {"))
{
UnrecognizedLine();
break;
@@ -113,7 +114,7 @@ namespace Nz
Warning("More meshes than registred");
#endif
m_meshes.push_back(Mesh());
m_meshes.emplace_back();
}
if (!ParseMesh())
@@ -182,14 +183,25 @@ namespace Nz
m_lineCount++;
m_currentLine = m_stream.ReadLine();
if (m_currentLine.IsEmpty())
continue;
m_currentLine = m_currentLine.SubStringTo("//"); // On ignore les commentaires
m_currentLine.Simplify(); // Pour un traitement plus simple
m_currentLine.Trim();
if (std::size_t p = m_currentLine.find("//"); p != m_currentLine.npos)
{
if (p > 0)
m_currentLine = m_currentLine.substr(0, p - 1);
else
m_currentLine.clear();
}
// Trim left
m_currentLine.erase(m_currentLine.begin(), std::find_if(m_currentLine.begin(), m_currentLine.end(), [](char c)
{
return !std::isspace(c);
}));
if (m_currentLine.empty())
continue;
}
while (m_currentLine.IsEmpty());
while (m_currentLine.empty());
}
else
m_keepLastLine = false;
@@ -197,9 +209,9 @@ namespace Nz
return true;
}
void MD5MeshParser::Error(const String& message)
void MD5MeshParser::Error(const std::string& message)
{
NazaraError(message + " at line #" + String::Number(m_lineCount));
NazaraError(message + " at line #" + std::to_string(m_lineCount));
}
bool MD5MeshParser::ParseJoints()
@@ -216,7 +228,7 @@ namespace Nz
if (!Advance())
return false;
std::size_t pos = m_currentLine.Find(' ');
std::size_t pos = m_currentLine.find(' ');
if (pos == String::npos)
{
UnrecognizedLine(true);
@@ -231,8 +243,8 @@ namespace Nz
char name[64];
if (std::sscanf(&m_currentLine[0], "%63s %d ( %f %f %f ) ( %f %f %f )", &name[0], &m_joints[i].parent,
&m_joints[i].bindPos.x, &m_joints[i].bindPos.y, &m_joints[i].bindPos.z,
&m_joints[i].bindOrient.x, &m_joints[i].bindOrient.y, &m_joints[i].bindOrient.z) != 8)
&m_joints[i].bindPos.x, &m_joints[i].bindPos.y, &m_joints[i].bindPos.z,
&m_joints[i].bindOrient.x, &m_joints[i].bindOrient.y, &m_joints[i].bindOrient.z) != 8)
{
UnrecognizedLine(true);
return false;
@@ -246,7 +258,7 @@ namespace Nz
{
if (static_cast<std::size_t>(parent) >= jointCount)
{
Error("Joint's parent is out of bounds (" + String::Number(parent) + " >= " + String::Number(jointCount) + ')');
Error("Joint's parent is out of bounds (" + std::to_string(parent) + " >= " + std::to_string(jointCount) + ')');
return false;
}
}
@@ -257,7 +269,7 @@ namespace Nz
if (!Advance())
return false;
if (m_currentLine != '}')
if (m_currentLine != "}")
{
#if NAZARA_UTILITY_STRICT_RESOURCE_PARSING
Warning("Hierarchy braces closing not found");
@@ -282,17 +294,42 @@ namespace Nz
break;
case 's': // shader
{
#if NAZARA_UTILITY_STRICT_RESOURCE_PARSING
if (!m_currentLine.StartsWith("shader "))
if (!StartsWith(m_currentLine, "shader "))
{
UnrecognizedLine();
break;
}
#endif
m_meshes[m_meshIndex].shader = m_currentLine.SubString(7);
m_meshes[m_meshIndex].shader.Trim('"');
std::string_view shader = m_currentLine;
shader = shader.substr(7);
if (shader.empty())
{
#if NAZARA_UTILITY_STRICT_RESOURCE_PARSING
UnrecognizedLine();
#endif
break;
}
if (shader.front() == '"')
shader.remove_prefix(1);
if (shader.empty())
{
#if NAZARA_UTILITY_STRICT_RESOURCE_PARSING
UnrecognizedLine();
#endif
break;
}
if (shader.back() == '"')
shader.remove_prefix(1);
m_meshes[m_meshIndex].shader = shader;
break;
}
case 'n': // num[tris/verts]
{
@@ -315,7 +352,7 @@ namespace Nz
if (index != i)
{
Error("Unexpected triangle index (expected " + String::Number(i) + ", got " + String::Number(index) + ')');
Error("Unexpected triangle index (expected " + std::to_string(i) + ", got " + std::to_string(index) + ')');
return false;
}
}
@@ -338,7 +375,7 @@ namespace Nz
if (index != i)
{
Error("Unexpected vertex index (expected " + String::Number(i) + ", got " + String::Number(index) + ')');
Error("Unexpected vertex index (expected " + std::to_string(i) + ", got " + std::to_string(index) + ')');
return false;
}
}
@@ -354,7 +391,7 @@ namespace Nz
Weight& weight = m_meshes[m_meshIndex].weights[i];
unsigned int index;
if (std::sscanf(&m_currentLine[0], "weight %u %u %f ( %f %f %f )", &index, &weight.joint, &weight.bias,
&weight.pos.x, &weight.pos.y, &weight.pos.z) != 6)
&weight.pos.x, &weight.pos.y, &weight.pos.z) != 6)
{
UnrecognizedLine(true);
return false;
@@ -362,7 +399,7 @@ namespace Nz
if (index != i)
{
Error("Unexpected weight index (expected " + String::Number(i) + ", got " + String::Number(index) + ')');
Error("Unexpected weight index (expected " + std::to_string(i) + ", got " + std::to_string(index) + ')');
return false;
}
}
@@ -408,14 +445,14 @@ namespace Nz
return true;
}
void MD5MeshParser::Warning(const String& message)
void MD5MeshParser::Warning(const std::string& message)
{
NazaraWarning(message + " at line #" + String::Number(m_lineCount));
NazaraWarning(message + " at line #" + std::to_string(m_lineCount));
}
void MD5MeshParser::UnrecognizedLine(bool error)
{
String message = "Unrecognized \"" + m_currentLine + '"';
std::string message = "Unrecognized \"" + m_currentLine + '"';
if (error)
Error(message);

View File

@@ -4,12 +4,31 @@
#include <Nazara/Utility/Formats/MTLParser.hpp>
#include <Nazara/Core/CallOnExit.hpp>
#include <Nazara/Core/StringExt.hpp>
#include <Nazara/Utility/Config.hpp>
#include <cstdio>
#include <Nazara/Utility/Debug.hpp>
namespace Nz
{
namespace
{
template<std::size_t N>
bool TestKeyword(const std::string& currentLine, const char(&keyword)[N], std::size_t& offset)
{
if (currentLine.size() > N && StartsWith(currentLine, keyword, CaseIndependent{}) && std::isspace(currentLine[N - 1]))
{
offset = N;
while (offset < currentLine.size() && std::isspace(currentLine[offset]))
offset++;
return offset < currentLine.size();
}
else
return false;
}
}
bool MTLParser::Parse(Stream& stream)
{
m_currentStream = &stream;
@@ -31,266 +50,434 @@ namespace Nz
m_materials.clear();
Material* currentMaterial = nullptr;
std::size_t offset;
while (Advance(false))
{
String keyword = m_currentLine.GetWord(0).ToLower();
if (keyword == "ka")
switch (std::tolower(m_currentLine[0]))
{
float r, g, b;
if (std::sscanf(&m_currentLine[3], "%f %f %f", &r, &g, &b) == 3)
case 'b':
{
if (!currentMaterial)
currentMaterial = AddMaterial("default");
if (TestKeyword(m_currentLine, "bump", offset))
{
std::string map = m_currentLine.substr(offset);
if (!map.empty())
{
if (!currentMaterial)
currentMaterial = AddMaterial("default");
currentMaterial->ambient = Color(static_cast<UInt8>(r*255.f), static_cast<UInt8>(g*255.f), static_cast<UInt8>(b*255.f));
currentMaterial->bumpMap = map;
}
#if NAZARA_UTILITY_STRICT_RESOURCE_PARSING
else
UnrecognizedLine();
#endif
}
}
#if NAZARA_UTILITY_STRICT_RESOURCE_PARSING
else
UnrecognizedLine();
#endif
}
else if (keyword == "kd")
{
float r, g, b;
if (std::sscanf(&m_currentLine[3], "%f %f %f", &r, &g, &b) == 3)
case 'd':
{
if (!currentMaterial)
currentMaterial = AddMaterial("default");
if (TestKeyword(m_currentLine, "d", offset))
{
float alpha;
if (std::sscanf(&m_currentLine[2], "%f", &alpha) == 1)
{
if (!currentMaterial)
currentMaterial = AddMaterial("default");
currentMaterial->diffuse = Color(static_cast<UInt8>(r*255.f), static_cast<UInt8>(g*255.f), static_cast<UInt8>(b*255.f));
currentMaterial->alpha = alpha;
}
#if NAZARA_UTILITY_STRICT_RESOURCE_PARSING
else
UnrecognizedLine();
#endif
}
else if (TestKeyword(m_currentLine, "decal", offset))
{
std::string map = m_currentLine.substr(offset);
if (!map.empty())
{
if (!currentMaterial)
currentMaterial = AddMaterial("default");
currentMaterial->decalMap = map;
}
#if NAZARA_UTILITY_STRICT_RESOURCE_PARSING
else
UnrecognizedLine();
#endif
}
else if (TestKeyword(m_currentLine, "disp", offset))
{
std::string map = m_currentLine.substr(offset);
if (!map.empty())
{
if (!currentMaterial)
currentMaterial = AddMaterial("default");
currentMaterial->displacementMap = map;
}
#if NAZARA_UTILITY_STRICT_RESOURCE_PARSING
else
UnrecognizedLine();
#endif
}
break;
}
#if NAZARA_UTILITY_STRICT_RESOURCE_PARSING
else
UnrecognizedLine();
#endif
}
else if (keyword == "ks")
{
float r, g, b;
if (std::sscanf(&m_currentLine[3], "%f %f %f", &r, &g, &b) == 3)
case 'e':
{
if (!currentMaterial)
currentMaterial = AddMaterial("default");
if (TestKeyword(m_currentLine, "emissive", offset))
{
// <!> This is a custom keyword
std::string map = m_currentLine.substr(offset);
if (!map.empty())
{
if (!currentMaterial)
currentMaterial = AddMaterial("default");
currentMaterial->specular = Color(static_cast<UInt8>(r*255.f), static_cast<UInt8>(g*255.f), static_cast<UInt8>(b*255.f));
currentMaterial->emissiveMap = map;
}
#if NAZARA_UTILITY_STRICT_RESOURCE_PARSING
else
UnrecognizedLine();
#endif
}
break;
}
#if NAZARA_UTILITY_STRICT_RESOURCE_PARSING
else
UnrecognizedLine();
#endif
}
else if (keyword == "ni")
{
float density;
if (std::sscanf(&m_currentLine[3], "%f", &density) == 1)
case 'k':
{
if (!currentMaterial)
currentMaterial = AddMaterial("default");
if (TestKeyword(m_currentLine, "ka", offset))
{
float r, g, b;
if (std::sscanf(&m_currentLine[offset], "%f %f %f", &r, &g, &b) == 3)
{
if (!currentMaterial)
currentMaterial = AddMaterial("default");
currentMaterial->refractionIndex = density;
currentMaterial->ambient = Color(static_cast<UInt8>(r * 255.f), static_cast<UInt8>(g * 255.f), static_cast<UInt8>(b * 255.f));
}
#if NAZARA_UTILITY_STRICT_RESOURCE_PARSING
else
UnrecognizedLine();
#endif
}
else if (TestKeyword(m_currentLine, "kd", offset))
{
float r, g, b;
if (std::sscanf(&m_currentLine[offset], "%f %f %f", &r, &g, &b) == 3)
{
if (!currentMaterial)
currentMaterial = AddMaterial("default");
currentMaterial->diffuse = Color(static_cast<UInt8>(r * 255.f), static_cast<UInt8>(g * 255.f), static_cast<UInt8>(b * 255.f));
}
#if NAZARA_UTILITY_STRICT_RESOURCE_PARSING
else
UnrecognizedLine();
#endif
}
else if (TestKeyword(m_currentLine, "ks", offset))
{
float r, g, b;
if (std::sscanf(&m_currentLine[offset], "%f %f %f", &r, &g, &b) == 3)
{
if (!currentMaterial)
currentMaterial = AddMaterial("default");
currentMaterial->specular = Color(static_cast<UInt8>(r * 255.f), static_cast<UInt8>(g * 255.f), static_cast<UInt8>(b * 255.f));
}
#if NAZARA_UTILITY_STRICT_RESOURCE_PARSING
else
UnrecognizedLine();
#endif
}
break;
}
#if NAZARA_UTILITY_STRICT_RESOURCE_PARSING
else
UnrecognizedLine();
#endif
}
else if (keyword == "ns")
{
float coef;
if (std::sscanf(&m_currentLine[3], "%f", &coef) == 1)
case 'i':
{
if (!currentMaterial)
currentMaterial = AddMaterial("default");
if (TestKeyword(m_currentLine, "illum", offset))
{
unsigned int model;
if (std::sscanf(&m_currentLine[offset], "%u", &model) == 1)
{
if (!currentMaterial)
currentMaterial = AddMaterial("default");
currentMaterial->shininess = coef;
}
#if NAZARA_UTILITY_STRICT_RESOURCE_PARSING
else
UnrecognizedLine();
#endif
}
else if (keyword == 'd')
{
float alpha;
if (std::sscanf(&m_currentLine[(keyword[0] == 'd') ? 2 : 3], "%f", &alpha) == 1)
{
if (!currentMaterial)
currentMaterial = AddMaterial("default");
currentMaterial->alpha = alpha;
}
#if NAZARA_UTILITY_STRICT_RESOURCE_PARSING
else
UnrecognizedLine();
#endif
}
else if (keyword == "tr")
{
float alpha;
if (std::sscanf(&m_currentLine[(keyword[0] == 'd') ? 2 : 3], "%f", &alpha) == 1)
{
if (!currentMaterial)
currentMaterial = AddMaterial("default");
currentMaterial->alpha = 1.f - alpha; // tr vaut pour la "valeur de transparence", 0 = opaque
}
#if NAZARA_UTILITY_STRICT_RESOURCE_PARSING
else
UnrecognizedLine();
#endif
}
else if (keyword == "illum")
{
unsigned int model;
if (std::sscanf(&m_currentLine[6], "%u", &model) == 1)
{
if (!currentMaterial)
currentMaterial = AddMaterial("default");
currentMaterial->illumModel = model;
}
#if NAZARA_UTILITY_STRICT_RESOURCE_PARSING
else
UnrecognizedLine();
#endif
}
else if (keyword == "map_ka")
{
std::size_t mapPos = m_currentLine.GetWordPosition(1);
if (mapPos != String::npos)
{
String map = m_currentLine.SubString(mapPos);
if (!currentMaterial)
currentMaterial = AddMaterial("default");
currentMaterial->ambientMap = map;
}
}
else if (keyword == "map_kd")
{
std::size_t mapPos = m_currentLine.GetWordPosition(1);
if (mapPos != String::npos)
{
String map = m_currentLine.SubString(mapPos);
if (!currentMaterial)
currentMaterial = AddMaterial("default");
currentMaterial->diffuseMap = map;
}
}
else if (keyword == "map_ks")
{
std::size_t mapPos = m_currentLine.GetWordPosition(1);
if (mapPos != String::npos)
{
String map = m_currentLine.SubString(mapPos);
if (!currentMaterial)
currentMaterial = AddMaterial("default");
currentMaterial->specularMap = map;
}
}
else if (keyword == "map_bump" || keyword == "bump")
{
std::size_t mapPos = m_currentLine.GetWordPosition(1);
if (mapPos != String::npos)
{
String map = m_currentLine.SubString(mapPos);
if (!currentMaterial)
currentMaterial = AddMaterial("default");
currentMaterial->bumpMap = map;
}
}
else if (keyword == "map_d")
{
std::size_t mapPos = m_currentLine.GetWordPosition(1);
if (mapPos != String::npos)
{
String map = m_currentLine.SubString(mapPos);
if (!currentMaterial)
currentMaterial = AddMaterial("default");
currentMaterial->alphaMap = map;
}
}
else if (keyword == "map_decal" || keyword == "decal")
{
std::size_t mapPos = m_currentLine.GetWordPosition(1);
if (mapPos != String::npos)
{
String map = m_currentLine.SubString(mapPos);
if (!currentMaterial)
currentMaterial = AddMaterial("default");
currentMaterial->decalMap = map;
}
}
else if (keyword == "map_disp" || keyword == "disp")
{
std::size_t mapPos = m_currentLine.GetWordPosition(1);
if (mapPos != String::npos)
{
String map = m_currentLine.SubString(mapPos);
if (!currentMaterial)
currentMaterial = AddMaterial("default");
currentMaterial->displacementMap = map;
}
}
else if (keyword == "map_refl" || keyword == "refl")
{
std::size_t mapPos = m_currentLine.GetWordPosition(1);
if (mapPos != String::npos)
{
String map = m_currentLine.SubString(mapPos);
if (!currentMaterial)
currentMaterial = AddMaterial("default");
currentMaterial->reflectionMap = map;
}
}
else if (keyword == "map_normal" || keyword == "normal")
{
// <!> This is a custom keyword
std::size_t mapPos = m_currentLine.GetWordPosition(1);
if (mapPos != String::npos)
{
String map = m_currentLine.SubString(mapPos);
if (!currentMaterial)
currentMaterial = AddMaterial("default");
currentMaterial->normalMap = map;
}
}
else if (keyword == "map_emissive" || keyword == "emissive")
{
// <!> This is a custom keyword
std::size_t mapPos = m_currentLine.GetWordPosition(1);
if (mapPos != String::npos)
{
String map = m_currentLine.SubString(mapPos);
if (!currentMaterial)
currentMaterial = AddMaterial("default");
currentMaterial->emissiveMap = map;
}
}
else if (keyword == "newmtl")
{
String materialName = m_currentLine.SubString(m_currentLine.GetWordPosition(1));
if (!materialName.IsEmpty())
currentMaterial = AddMaterial(materialName);
#if NAZARA_UTILITY_STRICT_RESOURCE_PARSING
else
UnrecognizedLine();
#endif
}
currentMaterial->illumModel = model;
}
#if NAZARA_UTILITY_STRICT_RESOURCE_PARSING
else
UnrecognizedLine();
else
UnrecognizedLine();
#endif
}
break;
}
case 'm':
{
if (TestKeyword(m_currentLine, "map_ka", offset))
{
std::string map = m_currentLine.substr(offset);
if (!map.empty())
{
if (!currentMaterial)
currentMaterial = AddMaterial("default");
currentMaterial->ambientMap = map;
}
#if NAZARA_UTILITY_STRICT_RESOURCE_PARSING
else
UnrecognizedLine();
#endif
}
else if (TestKeyword(m_currentLine, "map_kd", offset))
{
std::string map = m_currentLine.substr(offset);
if (!map.empty())
{
if (!currentMaterial)
currentMaterial = AddMaterial("default");
currentMaterial->diffuseMap = map;
}
#if NAZARA_UTILITY_STRICT_RESOURCE_PARSING
else
UnrecognizedLine();
#endif
}
else if (TestKeyword(m_currentLine, "map_ks", offset))
{
std::string map = m_currentLine.substr(offset);
if (!map.empty())
{
if (!currentMaterial)
currentMaterial = AddMaterial("default");
currentMaterial->specularMap = map;
}
#if NAZARA_UTILITY_STRICT_RESOURCE_PARSING
else
UnrecognizedLine();
#endif
}
else if (TestKeyword(m_currentLine, "map_bump", offset))
{
std::string map = m_currentLine.substr(offset);
if (!map.empty())
{
if (!currentMaterial)
currentMaterial = AddMaterial("default");
currentMaterial->bumpMap = map;
}
#if NAZARA_UTILITY_STRICT_RESOURCE_PARSING
else
UnrecognizedLine();
#endif
}
else if (TestKeyword(m_currentLine, "map_d", offset))
{
std::string map = m_currentLine.substr(offset);
if (!map.empty())
{
if (!currentMaterial)
currentMaterial = AddMaterial("default");
currentMaterial->alphaMap = map;
}
#if NAZARA_UTILITY_STRICT_RESOURCE_PARSING
else
UnrecognizedLine();
#endif
}
else if (TestKeyword(m_currentLine, "map_decal", offset))
{
std::string map = m_currentLine.substr(offset);
if (!map.empty())
{
if (!currentMaterial)
currentMaterial = AddMaterial("default");
currentMaterial->decalMap = map;
}
#if NAZARA_UTILITY_STRICT_RESOURCE_PARSING
else
UnrecognizedLine();
#endif
}
else if (TestKeyword(m_currentLine, "map_disp", offset))
{
std::string map = m_currentLine.substr(offset);
if (!map.empty())
{
if (!currentMaterial)
currentMaterial = AddMaterial("default");
currentMaterial->displacementMap = map;
}
#if NAZARA_UTILITY_STRICT_RESOURCE_PARSING
else
UnrecognizedLine();
#endif
}
else if (TestKeyword(m_currentLine, "map_refl", offset))
{
std::string map = m_currentLine.substr(offset);
if (!map.empty())
{
if (!currentMaterial)
currentMaterial = AddMaterial("default");
currentMaterial->reflectionMap = map;
}
#if NAZARA_UTILITY_STRICT_RESOURCE_PARSING
else
UnrecognizedLine();
#endif
}
else if (TestKeyword(m_currentLine, "map_normal", offset))
{
std::string map = m_currentLine.substr(offset);
if (!map.empty())
{
if (!currentMaterial)
currentMaterial = AddMaterial("default");
currentMaterial->normalMap = map;
}
#if NAZARA_UTILITY_STRICT_RESOURCE_PARSING
else
UnrecognizedLine();
#endif
}
else if (TestKeyword(m_currentLine, "map_emissive", offset))
{
// <!> This is a custom keyword
std::string map = m_currentLine.substr(offset);
if (!map.empty())
{
if (!currentMaterial)
currentMaterial = AddMaterial("default");
currentMaterial->emissiveMap = map;
}
#if NAZARA_UTILITY_STRICT_RESOURCE_PARSING
else
UnrecognizedLine();
#endif
}
break;
}
case 'n':
{
if (TestKeyword(m_currentLine, "ni", offset))
{
float density;
if (std::sscanf(&m_currentLine[offset], "%f", &density) == 1)
{
if (!currentMaterial)
currentMaterial = AddMaterial("default");
currentMaterial->refractionIndex = density;
}
#if NAZARA_UTILITY_STRICT_RESOURCE_PARSING
else
UnrecognizedLine();
#endif
}
else if (TestKeyword(m_currentLine, "ns", offset))
{
float coef;
if (std::sscanf(&m_currentLine[offset], "%f", &coef) == 1)
{
if (!currentMaterial)
currentMaterial = AddMaterial("default");
currentMaterial->shininess = coef;
}
#if NAZARA_UTILITY_STRICT_RESOURCE_PARSING
else
UnrecognizedLine();
#endif
}
else if (TestKeyword(m_currentLine, "normal", offset))
{
std::string map = m_currentLine.substr(offset);
if (!map.empty())
{
if (!currentMaterial)
currentMaterial = AddMaterial("default");
currentMaterial->normalMap = map;
}
#if NAZARA_UTILITY_STRICT_RESOURCE_PARSING
else
UnrecognizedLine();
#endif
}
else if (TestKeyword(m_currentLine, "newmtl", offset))
{
std::string materialName = m_currentLine.substr(offset);
if (!materialName.empty())
currentMaterial = AddMaterial(materialName);
#if NAZARA_UTILITY_STRICT_RESOURCE_PARSING
else
UnrecognizedLine();
#endif
}
break;
}
case 'r':
{
if (TestKeyword(m_currentLine, "refl", offset))
{
std::string map = m_currentLine.substr(offset);
if (!map.empty())
{
if (!currentMaterial)
currentMaterial = AddMaterial("default");
currentMaterial->reflectionMap = map;
}
#if NAZARA_UTILITY_STRICT_RESOURCE_PARSING
else
UnrecognizedLine();
#endif
}
break;
}
case 't':
{
if (TestKeyword(m_currentLine, "tr", offset))
{
float alpha;
if (std::sscanf(&m_currentLine[offset], "%f", &alpha) == 1)
{
if (!currentMaterial)
currentMaterial = AddMaterial("default");
currentMaterial->alpha = 1.f - alpha; // tr vaut pour la "valeur de transparence", 0 = opaque
}
#if NAZARA_UTILITY_STRICT_RESOURCE_PARSING
else
UnrecognizedLine();
#endif
}
}
default:
#if NAZARA_UTILITY_STRICT_RESOURCE_PARSING
UnrecognizedLine();
#endif
break;
}
}
return true;
@@ -378,49 +565,49 @@ namespace Nz
EmitLine(mat.illumModel);
}
if (!mat.ambientMap.IsEmpty())
if (!mat.ambientMap.empty())
{
Emit("map_Ka ");
EmitLine(mat.ambientMap);
}
if (!mat.diffuseMap.IsEmpty())
if (!mat.diffuseMap.empty())
{
Emit("map_Kd ");
EmitLine(mat.diffuseMap);
}
if (!mat.specularMap.IsEmpty())
if (!mat.specularMap.empty())
{
Emit("map_Ks ");
EmitLine(mat.specularMap);
}
if (!mat.bumpMap.IsEmpty())
if (!mat.bumpMap.empty())
{
Emit("map_bump ");
EmitLine(mat.bumpMap);
}
if (!mat.alphaMap.IsEmpty())
if (!mat.alphaMap.empty())
{
Emit("map_d ");
EmitLine(mat.alphaMap);
}
if (!mat.decalMap.IsEmpty())
if (!mat.decalMap.empty())
{
Emit("map_decal ");
EmitLine(mat.decalMap);
}
if (!mat.displacementMap.IsEmpty())
if (!mat.displacementMap.empty())
{
Emit("map_disp ");
EmitLine(mat.displacementMap);
}
if (!mat.reflectionMap.IsEmpty())
if (!mat.reflectionMap.empty())
{
Emit("map_refl ");
EmitLine(mat.reflectionMap);
@@ -450,13 +637,18 @@ namespace Nz
m_lineCount++;
m_currentLine = m_currentStream->ReadLine();
if (m_currentLine.IsEmpty())
continue;
if (std::size_t p = m_currentLine.find('#'); p != m_currentLine.npos)
{
if (p > 0)
m_currentLine = m_currentLine.substr(0, p - 1);
else
m_currentLine.clear();
}
m_currentLine = m_currentLine.SubStringTo("#"); // On ignore les commentaires
m_currentLine.Simplify(); // Pour un traitement plus simple
if (m_currentLine.empty())
continue;
}
while (m_currentLine.IsEmpty());
while (m_currentLine.empty());
}
else
m_keepLastLine = false;

View File

@@ -22,7 +22,7 @@ namespace Nz
{
namespace
{
bool IsSupported(const String& extension)
bool IsSupported(const std::string& extension)
{
return (extension == "obj");
}
@@ -42,12 +42,12 @@ namespace Nz
return Ternary_Unknown;
}
bool ParseMTL(Mesh* mesh, const String& filePath, const String* materials, const OBJParser::Mesh* meshes, UInt32 meshCount)
bool ParseMTL(Mesh* mesh, const std::filesystem::path& filePath, const std::string* materials, const OBJParser::Mesh* meshes, std::size_t meshCount)
{
File file(filePath);
if (!file.Open(OpenMode_ReadOnly | OpenMode_Text))
{
NazaraError("Failed to open MTL file (" + file.GetPath() + ')');
NazaraError("Failed to open MTL file (" + file.GetPath().generic_u8string() + ')');
return false;
}
@@ -59,10 +59,10 @@ namespace Nz
}
std::unordered_map<String, ParameterList> materialCache;
String baseDir = file.GetDirectory();
for (UInt32 i = 0; i < meshCount; ++i)
std::filesystem::path baseDir = file.GetDirectory();
for (std::size_t i = 0; i < meshCount; ++i)
{
const String& matName = materials[meshes[i].material];
const std::string& matName = materials[meshes[i].material];
const MTLParser::Material* mtlMat = materialParser.GetMaterial(matName);
if (!mtlMat)
{
@@ -89,53 +89,53 @@ namespace Nz
data.SetParameter(MaterialData::Shininess, mtlMat->shininess);
data.SetParameter(MaterialData::SpecularColor, specularColor);
if (!mtlMat->alphaMap.IsEmpty())
if (!mtlMat->alphaMap.empty())
{
String fullPath = mtlMat->alphaMap;
if (!Nz::File::IsAbsolute(fullPath))
fullPath.Prepend(baseDir);
std::filesystem::path fullPath = mtlMat->alphaMap;
if (!fullPath.is_absolute())
fullPath = baseDir / fullPath;
data.SetParameter(MaterialData::AlphaTexturePath, fullPath);
data.SetParameter(MaterialData::AlphaTexturePath, fullPath.generic_u8string());
}
if (!mtlMat->diffuseMap.IsEmpty())
if (!mtlMat->diffuseMap.empty())
{
String fullPath = mtlMat->diffuseMap;
if (!Nz::File::IsAbsolute(fullPath))
fullPath.Prepend(baseDir);
std::filesystem::path fullPath = mtlMat->diffuseMap;
if (!fullPath.is_absolute())
fullPath = baseDir / fullPath;
data.SetParameter(MaterialData::DiffuseTexturePath, fullPath);
data.SetParameter(MaterialData::DiffuseTexturePath, fullPath.generic_u8string());
}
if (!mtlMat->emissiveMap.IsEmpty())
if (!mtlMat->emissiveMap.empty())
{
String fullPath = mtlMat->emissiveMap;
if (!Nz::File::IsAbsolute(fullPath))
fullPath.Prepend(baseDir);
std::filesystem::path fullPath = mtlMat->emissiveMap;
if (!fullPath.is_absolute())
fullPath = baseDir / fullPath;
data.SetParameter(MaterialData::EmissiveTexturePath, fullPath);
data.SetParameter(MaterialData::EmissiveTexturePath, fullPath.generic_u8string());
}
if (!mtlMat->normalMap.IsEmpty())
if (!mtlMat->normalMap.empty())
{
String fullPath = mtlMat->normalMap;
if (!Nz::File::IsAbsolute(fullPath))
fullPath.Prepend(baseDir);
std::filesystem::path fullPath = mtlMat->normalMap;
if (!fullPath.is_absolute())
fullPath = baseDir / fullPath;
data.SetParameter(MaterialData::NormalTexturePath, fullPath);
data.SetParameter(MaterialData::NormalTexturePath, fullPath.generic_u8string());
}
if (!mtlMat->specularMap.IsEmpty())
if (!mtlMat->specularMap.empty())
{
String fullPath = mtlMat->specularMap;
if (!Nz::File::IsAbsolute(fullPath))
fullPath.Prepend(baseDir);
std::filesystem::path fullPath = mtlMat->specularMap;
if (!fullPath.is_absolute())
fullPath = baseDir / fullPath;
data.SetParameter(MaterialData::SpecularTexturePath, fullPath);
data.SetParameter(MaterialData::SpecularTexturePath, fullPath.generic_u8string());
}
// If we either have an alpha value or an alpha map, let's configure the material for transparency
if (alphaValue != 255 || !mtlMat->alphaMap.IsEmpty())
if (alphaValue != 255 || !mtlMat->alphaMap.empty())
{
// Some default settings
data.SetParameter(MaterialData::Blending, true);
@@ -169,27 +169,27 @@ namespace Nz
MeshRef mesh = Mesh::New();
mesh->CreateStatic();
const String* materials = parser.GetMaterials();
const std::string* materials = parser.GetMaterials();
const Vector4f* positions = parser.GetPositions();
const Vector3f* normals = parser.GetNormals();
const Vector3f* texCoords = parser.GetTexCoords();
const OBJParser::Mesh* meshes = parser.GetMeshes();
UInt32 meshCount = parser.GetMeshCount();
std::size_t meshCount = parser.GetMeshCount();
NazaraAssert(materials != nullptr && positions != nullptr && normals != nullptr &&
texCoords != nullptr && meshes != nullptr && meshCount > 0,
"Invalid OBJParser output");
// Un conteneur temporaire pour contenir les indices de face avant triangulation
std::vector<UInt32> faceIndices(3); // Comme il y aura au moins trois sommets
for (UInt32 i = 0; i < meshCount; ++i)
std::vector<std::size_t> faceIndices(3); // Comme il y aura au moins trois sommets
for (std::size_t i = 0; i < meshCount; ++i)
{
std::size_t faceCount = meshes[i].faces.size();
if (faceCount == 0)
continue;
std::vector<UInt32> indices;
std::vector<std::size_t> indices;
indices.reserve(faceCount*3); // Pire cas si les faces sont des triangles
// Afin d'utiliser OBJParser::FaceVertex comme clé dans un unordered_map,
@@ -226,10 +226,10 @@ namespace Nz
unsigned int vertexCount = 0;
for (unsigned int j = 0; j < faceCount; ++j)
{
UInt32 faceVertexCount = meshes[i].faces[j].vertexCount;
std::size_t faceVertexCount = meshes[i].faces[j].vertexCount;
faceIndices.resize(faceVertexCount);
for (UInt32 k = 0; k < faceVertexCount; ++k)
for (std::size_t k = 0; k < faceVertexCount; ++k)
{
const OBJParser::FaceVertex& vertex = meshes[i].vertices[meshes[i].faces[j].firstVertex + k];
@@ -241,7 +241,7 @@ namespace Nz
}
// Triangulation
for (UInt32 k = 1; k < faceVertexCount-1; ++k)
for (std::size_t k = 1; k < faceVertexCount-1; ++k)
{
indices.push_back(faceIndices[0]);
indices.push_back(faceIndices[k]);
@@ -250,13 +250,13 @@ namespace Nz
}
// Création des buffers
IndexBufferRef indexBuffer = IndexBuffer::New(vertexCount > std::numeric_limits<UInt16>::max(), UInt32(indices.size()), parameters.storage, parameters.indexBufferFlags);
VertexBufferRef vertexBuffer = VertexBuffer::New(parameters.vertexDeclaration, UInt32(vertexCount), parameters.storage, parameters.vertexBufferFlags);
IndexBufferRef indexBuffer = IndexBuffer::New(vertexCount > std::numeric_limits<UInt16>::max(), std::size_t(indices.size()), parameters.storage, parameters.indexBufferFlags);
VertexBufferRef vertexBuffer = VertexBuffer::New(parameters.vertexDeclaration, std::size_t(vertexCount), parameters.storage, parameters.vertexBufferFlags);
// Remplissage des indices
IndexMapper indexMapper(indexBuffer, BufferAccess_WriteOnly);
for (std::size_t j = 0; j < indices.size(); ++j)
indexMapper.Set(j, indices[j]);
indexMapper.Set(j, UInt32(indices[j]));
indexMapper.Unmap(); // Pour laisser les autres tâches affecter l'index buffer
@@ -337,11 +337,11 @@ namespace Nz
mesh->Recenter();
// On charge les matériaux si demandé
String mtlLib = parser.GetMtlLib();
if (!mtlLib.IsEmpty())
std::filesystem::path mtlLib = parser.GetMtlLib();
if (!mtlLib.empty())
{
ErrorFlags flags(ErrorFlag_ThrowExceptionDisabled);
ParseMTL(mesh, stream.GetDirectory() + mtlLib, materials, meshes, meshCount);
ParseMTL(mesh, stream.GetDirectory() / mtlLib, materials, meshes, meshCount);
}
return mesh;

View File

@@ -4,6 +4,7 @@
#include <Nazara/Utility/Formats/OBJParser.hpp>
#include <Nazara/Core/CallOnExit.hpp>
#include <Nazara/Core/StringExt.hpp>
#include <Nazara/Utility/Config.hpp>
#include <cctype>
#include <memory>
@@ -45,32 +46,29 @@ namespace Nz
case 'o': //< Object (defines a mesh)
case 's': //< Smooth
{
if (m_currentLine.GetSize() > 1 && m_currentLine[1] == ' ')
if (m_currentLine.size() > 1 && m_currentLine[1] == ' ')
return true;
break;
}
case 'm': //< MTLLib
if (m_currentLine.GetWord(0).ToLower() == "mtllib")
if (StartsWith(m_currentLine, "mtllib "))
return true;
break;
case 'u': //< Usemtl
if (m_currentLine.GetWord(0).ToLower() == "usemtl")
if (StartsWith(m_currentLine, "usemtl "))
return true;
break;
case 'v': //< Position/Normal/Texcoords
{
String word = m_currentLine.GetWord(0).ToLower();
if (word == 'v')
return true;
else if (word == "vn")
return true;
else if (word == "vt")
if (StartsWith(m_currentLine, "v ") ||
StartsWith(m_currentLine, "vn ") ||
StartsWith(m_currentLine, "vt "))
return true;
break;
@@ -87,7 +85,7 @@ namespace Nz
return false;
}
bool OBJParser::Parse(Nz::Stream& stream, UInt32 reservedVertexCount)
bool OBJParser::Parse(Nz::Stream& stream, std::size_t reservedVertexCount)
{
m_currentStream = &stream;
m_errorCount = 0;
@@ -106,10 +104,10 @@ namespace Nz
});
}
String matName, meshName;
std::string matName, meshName;
matName = meshName = "default";
m_meshes.clear();
m_mtlLib.Clear();
m_mtlLib.clear();
m_normals.clear();
m_positions.clear();
@@ -122,12 +120,12 @@ namespace Nz
// Sort meshes by material and group
using MatPair = std::pair<Mesh, unsigned int>;
std::unordered_map<String, std::unordered_map<String, MatPair>> meshesByName;
std::unordered_map<std::string, std::unordered_map<std::string, MatPair>> meshesByName;
UInt32 faceReserve = 0;
UInt32 vertexReserve = 0;
unsigned int matCount = 0;
auto GetMaterial = [&] (const String& mesh, const String& mat) -> Mesh*
auto GetMaterial = [&] (const std::string& mesh, const std::string& mat) -> Mesh*
{
auto& map = meshesByName[mesh];
auto it = map.find(mat);
@@ -154,22 +152,22 @@ namespace Nz
case '#': //< Comment
// Some softwares write comments to gives the number of vertex/faces an importer can expect
unsigned int data;
if (std::sscanf(m_currentLine.GetConstBuffer(), "# position count: %u", &data) == 1)
if (std::sscanf(m_currentLine.data(), "# position count: %u", &data) == 1)
m_positions.reserve(data);
else if (std::sscanf(m_currentLine.GetConstBuffer(), "# normal count: %u", &data) == 1)
else if (std::sscanf(m_currentLine.data(), "# normal count: %u", &data) == 1)
m_normals.reserve(data);
else if (std::sscanf(m_currentLine.GetConstBuffer(), "# texcoords count: %u", &data) == 1)
else if (std::sscanf(m_currentLine.data(), "# texcoords count: %u", &data) == 1)
m_texCoords.reserve(data);
else if (std::sscanf(m_currentLine.GetConstBuffer(), "# face count: %u", &data) == 1)
else if (std::sscanf(m_currentLine.data(), "# face count: %u", &data) == 1)
faceReserve = data;
else if (std::sscanf(m_currentLine.GetConstBuffer(), "# vertex count: %u", &data) == 1)
else if (std::sscanf(m_currentLine.data(), "# vertex count: %u", &data) == 1)
vertexReserve = data;
break;
case 'f': //< Face
{
if (m_currentLine.GetSize() < 7) // Since we only treat triangles, this is the minimum length of a face line (f 1 2 3)
if (m_currentLine.size() < 7) // Since we only treat triangles, this is the minimum length of a face line (f 1 2 3)
{
#if NAZARA_UTILITY_STRICT_RESOURCE_PARSING
if (!UnrecognizedLine())
@@ -178,7 +176,7 @@ namespace Nz
break;
}
unsigned int vertexCount = m_currentLine.Count(' ');
std::size_t vertexCount = std::count(m_currentLine.begin(), m_currentLine.end(), ' ');
if (vertexCount < 3)
{
#if NAZARA_UTILITY_STRICT_RESOURCE_PARSING
@@ -192,8 +190,8 @@ namespace Nz
currentMesh = GetMaterial(meshName, matName);
Face face;
face.firstVertex = static_cast<UInt32>(currentMesh->vertices.size());
face.vertexCount = static_cast<UInt32>(vertexCount);
face.firstVertex = currentMesh->vertices.size();
face.vertexCount = vertexCount;
currentMesh->vertices.resize(face.firstVertex + vertexCount, FaceVertex{0, 0, 0});
@@ -230,7 +228,7 @@ namespace Nz
p += static_cast<int>(m_positions.size());
if (p < 0)
{
Error("Vertex index out of range (" + String::Number(p) + " < 0");
Error("Vertex index out of range (" + std::to_string(p) + " < 0");
error = true;
break;
}
@@ -243,7 +241,7 @@ namespace Nz
n += static_cast<int>(m_normals.size());
if (n < 0)
{
Error("Normal index out of range (" + String::Number(n) + " < 0");
Error("Normal index out of range (" + std::to_string(n) + " < 0");
error = true;
break;
}
@@ -256,7 +254,7 @@ namespace Nz
t += static_cast<int>(m_texCoords.size());
if (t < 0)
{
Error("Texture coordinates index out of range (" + String::Number(t) + " < 0");
Error("Texture coordinates index out of range (" + std::to_string(t) + " < 0");
error = true;
break;
}
@@ -266,19 +264,19 @@ namespace Nz
if (static_cast<std::size_t>(p) > m_positions.size())
{
Error("Vertex index out of range (" + String::Number(p) + " >= " + String::Number(m_positions.size()) + ')');
Error("Vertex index out of range (" + std::to_string(p) + " >= " + std::to_string(m_positions.size()) + ')');
error = true;
break;
}
else if (n != 0 && static_cast<std::size_t>(n) > m_normals.size())
{
Error("Normal index out of range (" + String::Number(n) + " >= " + String::Number(m_normals.size()) + ')');
Error("Normal index out of range (" + std::to_string(n) + " >= " + std::to_string(m_normals.size()) + ')');
error = true;
break;
}
else if (t != 0 && static_cast<std::size_t>(t) > m_texCoords.size())
{
Error("TexCoord index out of range (" + String::Number(t) + " >= " + String::Number(m_texCoords.size()) + ')');
Error("TexCoord index out of range (" + std::to_string(t) + " >= " + std::to_string(m_texCoords.size()) + ')');
error = true;
break;
}
@@ -299,29 +297,36 @@ namespace Nz
}
case 'm': //< MTLLib
#if NAZARA_UTILITY_STRICT_RESOURCE_PARSING
if (m_currentLine.GetWord(0).ToLower() != "mtllib")
{
const char prefix[] = "mtllib ";
if (!StartsWith(m_currentLine, prefix))
{
#if NAZARA_UTILITY_STRICT_RESOURCE_PARSING
if (!UnrecognizedLine())
return false;
#endif
#endif
m_mtlLib = m_currentLine.SubString(m_currentLine.GetWordPosition(1));
break;
}
m_mtlLib = m_currentLine.substr(sizeof(prefix) - 1);
break;
}
case 'g': //< Group (inside a mesh)
case 'o': //< Object (defines a mesh)
{
if (m_currentLine.GetSize() <= 2 || m_currentLine[1] != ' ')
if (m_currentLine.size() <= 2 || m_currentLine[1] != ' ')
{
#if NAZARA_UTILITY_STRICT_RESOURCE_PARSING
#if NAZARA_UTILITY_STRICT_RESOURCE_PARSING
if (!UnrecognizedLine())
return false;
#endif
#endif
break;
}
String objectName = m_currentLine.SubString(m_currentLine.GetWordPosition(1));
if (objectName.IsEmpty())
std::string objectName = m_currentLine.substr(2);
if (objectName.empty())
{
#if NAZARA_UTILITY_STRICT_RESOURCE_PARSING
if (!UnrecognizedLine())
@@ -335,12 +340,12 @@ namespace Nz
break;
}
#if NAZARA_UTILITY_STRICT_RESOURCE_PARSING
#if NAZARA_UTILITY_STRICT_RESOURCE_PARSING
case 's': //< Smooth
if (m_currentLine.GetSize() <= 2 || m_currentLine[1] == ' ')
if (m_currentLine.size() <= 2 || m_currentLine[1] == ' ')
{
String param = m_currentLine.SubString(2);
if (param != "all" && param != "on" && param != "off" && !param.IsNumber())
std::string param = m_currentLine.substr(2);
if (param != "all" && param != "on" && param != "off" && !IsNumber(param))
{
if (!UnrecognizedLine())
return false;
@@ -349,33 +354,51 @@ namespace Nz
else if (!UnrecognizedLine())
return false;
break;
#endif
#endif
case 'u': //< Usemtl
#if NAZARA_UTILITY_STRICT_RESOURCE_PARSING
if (m_currentLine.GetWord(0) != "usemtl" && !UnrecognizedLine())
return false;
#endif
matName = m_currentLine.SubString(m_currentLine.GetWordPosition(1));
currentMesh = nullptr;
if (matName.IsEmpty())
{
const char prefix[] = "usemtl ";
if (!StartsWith(m_currentLine, prefix))
{
#if NAZARA_UTILITY_STRICT_RESOURCE_PARSING
#if NAZARA_UTILITY_STRICT_RESOURCE_PARSING
if (!UnrecognizedLine())
return false;
#endif
#endif
break;
}
std::string newMatName = m_currentLine.substr(sizeof(prefix) - 1);
if (newMatName.empty())
{
#if NAZARA_UTILITY_STRICT_RESOURCE_PARSING
if (!UnrecognizedLine())
return false;
#endif
break;
}
matName = std::move(newMatName);
currentMesh = nullptr;
break;
}
case 'v': //< Position/Normal/Texcoords
{
String word = m_currentLine.GetWord(0).ToLower();
if (word == 'v')
if (m_currentLine.size() < 7)
{
#if NAZARA_UTILITY_STRICT_RESOURCE_PARSING
if (!UnrecognizedLine())
return false;
#endif
break;
}
if (std::isspace(m_currentLine[1]))
{
Vector4f vertex(Vector3f::Zero(), 1.f);
unsigned int paramCount = std::sscanf(&m_currentLine[2], "%f %f %f %f", &vertex.x, &vertex.y, &vertex.z, &vertex.w);
unsigned int paramCount = std::sscanf(&m_currentLine[2], " %f %f %f %f", &vertex.x, &vertex.y, &vertex.z, &vertex.w);
if (paramCount >= 1)
m_positions.push_back(vertex);
#if NAZARA_UTILITY_STRICT_RESOURCE_PARSING
@@ -383,10 +406,10 @@ namespace Nz
return false;
#endif
}
else if (word == "vn")
else if (m_currentLine[1] == 'n' && std::isspace(m_currentLine[2]))
{
Vector3f normal(Vector3f::Zero());
unsigned int paramCount = std::sscanf(&m_currentLine[3], "%f %f %f", &normal.x, &normal.y, &normal.z);
unsigned int paramCount = std::sscanf(&m_currentLine[3], " %f %f %f", &normal.x, &normal.y, &normal.z);
if (paramCount == 3)
m_normals.push_back(normal);
#if NAZARA_UTILITY_STRICT_RESOURCE_PARSING
@@ -394,10 +417,10 @@ namespace Nz
return false;
#endif
}
else if (word == "vt")
else if (m_currentLine[1] == 't' && std::isspace(m_currentLine[2]))
{
Vector3f uvw(Vector3f::Zero());
unsigned int paramCount = std::sscanf(&m_currentLine[3], "%f %f %f", &uvw.x, &uvw.y, &uvw.z);
unsigned int paramCount = std::sscanf(&m_currentLine[3], " %f %f %f", &uvw.x, &uvw.y, &uvw.z);
if (paramCount >= 2)
m_texCoords.push_back(uvw);
#if NAZARA_UTILITY_STRICT_RESOURCE_PARSING
@@ -422,7 +445,7 @@ namespace Nz
}
}
std::unordered_map<String, unsigned int> materials;
std::unordered_map<std::string, unsigned int> materials;
m_materials.resize(matCount);
for (auto& meshPair : meshesByName)
@@ -480,10 +503,10 @@ namespace Nz
EmitLine("# Exported by Nazara Engine");
EmitLine();
if (!m_mtlLib.IsEmpty())
if (!m_mtlLib.empty())
{
Emit("mtllib ");
EmitLine(m_mtlLib);
EmitLine(m_mtlLib.generic_u8string());
EmitLine();
}
@@ -617,12 +640,18 @@ namespace Nz
m_lineCount++;
m_currentLine = m_currentStream->ReadLine();
if (m_currentLine.IsEmpty())
continue;
if (std::size_t p = m_currentLine.find('#'); p != m_currentLine.npos)
{
if (p > 0)
m_currentLine = m_currentLine.substr(0, p - 1);
else
m_currentLine.clear();
}
m_currentLine.Simplify(); // Simplify lines (convert multiple blanks into a single space and trims)
if (m_currentLine.empty())
continue;
}
while (m_currentLine.IsEmpty());
while (m_currentLine.empty());
}
else
m_keepLastLine = false;

View File

@@ -2,7 +2,6 @@
// This file is part of the "Nazara Engine - Utility module"
// For conditions of distribution and use, see copyright notice in Config.hpp
#include <Nazara/Core/Directory.hpp>
#include <Nazara/Utility/MaterialData.hpp>
#include <Nazara/Utility/Mesh.hpp>
#include <Nazara/Utility/StaticMesh.hpp>
@@ -28,12 +27,12 @@ namespace Nz
{
}
UInt32 GetCount() const
std::size_t GetCount() const
{
return m_count;
}
UInt32 Insert(const T& data)
std::size_t Insert(const T& data)
{
auto it = m_cache.find(data);
if (it == m_cache.end())
@@ -47,17 +46,17 @@ namespace Nz
}
private:
UInt32 m_count;
std::map<T, UInt32> m_cache;
std::size_t m_count;
std::map<T, std::size_t> m_cache;
T* m_buffer;
};
bool IsSupported(const String& extension)
bool IsSupported(const std::string& extension)
{
return (extension == "obj");
}
bool SaveToStream(const Mesh& mesh, const String& format, Stream& stream, const MeshParams& parameters)
bool SaveToStream(const Mesh& mesh, const std::string& format, Stream& stream, const MeshParams& parameters)
{
NazaraUnused(parameters);
@@ -73,18 +72,18 @@ namespace Nz
return false;
}
UInt32 worstCacheVertexCount = mesh.GetVertexCount();
std::size_t worstCacheVertexCount = mesh.GetVertexCount();
OBJParser objFormat;
objFormat.SetNormalCount(worstCacheVertexCount);
objFormat.SetPositionCount(worstCacheVertexCount);
objFormat.SetTexCoordCount(worstCacheVertexCount);
String mtlPath = stream.GetPath();
if (!mtlPath.IsEmpty())
std::filesystem::path mtlPath = stream.GetPath();
if (!mtlPath.empty())
{
mtlPath.Replace(".obj", ".mtl");
String fileName = mtlPath.SubStringFrom(NAZARA_DIRECTORY_SEPARATOR, -1, true);
if (!fileName.IsEmpty())
mtlPath.replace_extension(".mtl");
std::filesystem::path fileName = mtlPath.filename();
if (!fileName.empty())
objFormat.SetMtlLib(fileName);
}
@@ -94,17 +93,20 @@ namespace Nz
// Materials
MTLParser mtlFormat;
std::unordered_set<String> registredMaterials;
std::unordered_set<std::string> registredMaterials;
UInt32 matCount = mesh.GetMaterialCount();
String* materialNames = objFormat.SetMaterialCount(matCount);
for (UInt32 i = 0; i < matCount; ++i)
std::size_t matCount = mesh.GetMaterialCount();
std::string* materialNames = objFormat.SetMaterialCount(matCount);
for (std::size_t i = 0; i < matCount; ++i)
{
const ParameterList& matData = mesh.GetMaterialData(i);
String name;
if (!matData.GetStringParameter(MaterialData::Name, &name))
name = "material_" + String::Number(i);
String nzname;
std::string name;
if (matData.GetStringParameter(MaterialData::Name, &nzname))
name = nzname.ToStdString();
else
name = "material_" + std::to_string(i);
// Makes sure we only have one material of that name
while (registredMaterials.find(name) != registredMaterials.end())
@@ -117,7 +119,7 @@ namespace Nz
String strVal;
if (matData.GetStringParameter(MaterialData::FilePath, &strVal))
material->diffuseMap = strVal;
material->diffuseMap = strVal.ToStdString();
else
{
Color colorVal;
@@ -136,28 +138,28 @@ namespace Nz
material->shininess = float(dValue);
if (matData.GetStringParameter(MaterialData::AlphaTexturePath, &strVal))
material->alphaMap = strVal;
material->alphaMap = strVal.ToStdString();
if (matData.GetStringParameter(MaterialData::DiffuseTexturePath, &strVal))
material->diffuseMap = strVal;
material->diffuseMap = strVal.ToStdString();
if (matData.GetStringParameter(MaterialData::SpecularTexturePath, &strVal))
material->specularMap = strVal;
material->specularMap = strVal.ToStdString();
}
}
// Meshes
UInt32 meshCount = mesh.GetSubMeshCount();
std::size_t meshCount = mesh.GetSubMeshCount();
OBJParser::Mesh* meshes = objFormat.SetMeshCount(meshCount);
for (UInt32 i = 0; i < meshCount; ++i)
for (std::size_t i = 0; i < meshCount; ++i)
{
const StaticMesh* staticMesh = static_cast<const StaticMesh*>(mesh.GetSubMesh(i));
UInt32 triangleCount = staticMesh->GetTriangleCount();
std::size_t triangleCount = staticMesh->GetTriangleCount();
meshes[i].faces.resize(triangleCount);
meshes[i].material = staticMesh->GetMaterialIndex();
meshes[i].name = "mesh_" + String::Number(i);
meshes[i].name = "mesh_" + std::to_string(i);
meshes[i].vertices.resize(triangleCount * 3);
{
@@ -167,7 +169,7 @@ namespace Nz
SparsePtr<Vector3f> positionPtr = vertexMapper.GetComponentPtr<Vector3f>(VertexComponent_Position);
SparsePtr<Vector2f> texCoordsPtr = vertexMapper.GetComponentPtr<Vector2f>(VertexComponent_TexCoord);
UInt32 faceIndex = 0;
std::size_t faceIndex = 0;
TriangleIterator triangle(staticMesh);
do
{
@@ -179,7 +181,7 @@ namespace Nz
{
OBJParser::FaceVertex& vertexIndices = meshes[i].vertices[face.firstVertex + j];
UInt32 index = triangle[j];
std::size_t index = triangle[j];
vertexIndices.normal = normalCache.Insert(normalPtr[index]);
vertexIndices.position = positionCache.Insert(positionPtr[index]);
vertexIndices.texCoord = texCoordsCache.Insert(texCoordsPtr[index]);
@@ -197,7 +199,7 @@ namespace Nz
objFormat.Save(stream);
if (!mtlPath.IsEmpty())
if (!mtlPath.empty())
{
File mtlFile(mtlPath, OpenMode_WriteOnly | OpenMode_Truncate);
if (mtlFile.IsOpen())

View File

@@ -40,7 +40,7 @@ namespace Nz
static_assert(sizeof(pcx_header) == (6+48+54)*sizeof(UInt8) + 10*sizeof(UInt16), "pcx_header struct must be packed");
bool IsSupported(const String& extension)
bool IsSupported(const std::string& extension)
{
return (extension == "pcx");
}

View File

@@ -36,7 +36,7 @@ namespace Nz
static stbi_io_callbacks callbacks = {Read, Skip, Eof};
bool IsSupported(const String& extension)
bool IsSupported(const std::string& extension)
{
static std::set<String> supportedExtensions = {"bmp", "gif", "hdr", "jpg", "jpeg", "pic", "png", "ppm", "pgm", "psd", "tga"};
return supportedExtensions.find(extension) != supportedExtensions.end();

View File

@@ -15,7 +15,7 @@ namespace Nz
{
using FormatHandler = bool(*)(const Image& image, const ImageParams& parameters, Stream& stream);
std::map<String, FormatHandler> s_formatHandlers;
std::map<std::string, FormatHandler> s_formatHandlers;
int ConvertToFloatFormat(Image& image)
{
@@ -102,12 +102,12 @@ namespace Nz
throw std::runtime_error("Failed to write to stream");
}
bool FormatQuerier(const String& extension)
bool FormatQuerier(const std::string& extension)
{
return s_formatHandlers.find(extension) != s_formatHandlers.end();
}
bool SaveToStream(const Image& image, const String& format, Stream& stream, const ImageParams& parameters)
bool SaveToStream(const Image& image, const std::string& format, Stream& stream, const ImageParams& parameters)
{
NazaraUnused(parameters);