bool NzDirectory::NextResult(bool skipDots) { NazaraLock(m_mutex); #if NAZARA_CORE_SAFE if (!m_impl) { NazaraError("Directory not opened"); return false; } #endif NzString name; do { if (!m_impl->NextResult()) return false; name = m_impl->GetResultName(); if (skipDots && (name == '.' || name == "..")) continue; if (name.Match(m_pattern)) break; } while (true); return true; }
NzString NzStringStream::ToString() const { NzString string; string.Reserve(m_bufferSize); for (const NzString& str : m_strings) string += str; return string; }
NzString NzInputStream::ReadLine(unsigned int lineSize) { NzString line; if (lineSize == 0) // Taille maximale indéterminée { const unsigned int bufferSize = 64; char buffer[bufferSize+1]; buffer[bufferSize] = '\0'; unsigned int readSize; do { readSize = Read(buffer, bufferSize); const char* ptr = std::strchr(buffer, '\n'); if (ptr) { unsigned int pos = ptr-buffer; if (m_streamOptions & nzStreamOption_Text && pos > 0 && buffer[pos-1] == '\r') line.Append(buffer, pos-1); else line.Append(buffer, pos); if (!SetCursorPos(GetCursorPos() - readSize + pos + 1)) NazaraWarning("Failed to reset cursos pos"); break; } else line.Append(buffer, readSize); } while (readSize == bufferSize); } else { line.Set(lineSize, '\0'); unsigned int readSize = Read(&line[0], lineSize); unsigned int pos = line.Find('\n'); if (pos <= readSize) // Faux uniquement si le caractère n'est pas présent (npos étant le plus grand entier) { if (m_streamOptions & nzStreamOption_Text && pos > 0 && line[pos-1] == '\r') line.Resize(pos); else line.Resize(pos+1); if (!SetCursorPos(GetCursorPos() - readSize + pos + 1)) NazaraWarning("Failed to reset cursos pos"); } else line.Resize(readSize); } return line; }
void NzShaderStage::SetSource(const NzString& source) { #if NAZARA_RENDERER_SAFE if (!m_id) { NazaraError("Shader stage is not initialized"); return; } #endif const char* tmp = source.GetConstBuffer(); GLint length = source.GetSize(); glShaderSource(m_id, 1, &tmp, &length); }
bool NzLuaInstance::Execute(const NzString& code) { if (code.IsEmpty()) return true; if (luaL_loadstring(m_state, code.GetConstBuffer()) != 0) { m_lastError = lua_tostring(m_state, -1); lua_pop(m_state, 1); return false; } return Run(0, 0); }
bool NzShader::Create() { NzContext::EnsureContext(); m_program = glCreateProgram(); if (!m_program) { NazaraError("Failed to create program"); return false; } m_linked = false; glBindAttribLocation(m_program, NzOpenGL::VertexComponentIndex[nzVertexComponent_InstanceData0], "InstanceData0"); glBindAttribLocation(m_program, NzOpenGL::VertexComponentIndex[nzVertexComponent_InstanceData1], "InstanceData1"); glBindAttribLocation(m_program, NzOpenGL::VertexComponentIndex[nzVertexComponent_InstanceData2], "InstanceData2"); glBindAttribLocation(m_program, NzOpenGL::VertexComponentIndex[nzVertexComponent_InstanceData3], "InstanceData3"); glBindAttribLocation(m_program, NzOpenGL::VertexComponentIndex[nzVertexComponent_InstanceData4], "InstanceData4"); glBindAttribLocation(m_program, NzOpenGL::VertexComponentIndex[nzVertexComponent_InstanceData5], "InstanceData5"); glBindAttribLocation(m_program, NzOpenGL::VertexComponentIndex[nzVertexComponent_Color], "VertexColor"); glBindAttribLocation(m_program, NzOpenGL::VertexComponentIndex[nzVertexComponent_Normal], "VertexNormal"); glBindAttribLocation(m_program, NzOpenGL::VertexComponentIndex[nzVertexComponent_Position], "VertexPosition"); glBindAttribLocation(m_program, NzOpenGL::VertexComponentIndex[nzVertexComponent_Tangent], "VertexTangent"); glBindAttribLocation(m_program, NzOpenGL::VertexComponentIndex[nzVertexComponent_TexCoord], "VertexTexCoord"); glBindAttribLocation(m_program, NzOpenGL::VertexComponentIndex[nzVertexComponent_Userdata0], "VertexUserdata0"); glBindAttribLocation(m_program, NzOpenGL::VertexComponentIndex[nzVertexComponent_Userdata1], "VertexUserdata1"); glBindAttribLocation(m_program, NzOpenGL::VertexComponentIndex[nzVertexComponent_Userdata2], "VertexUserdata2"); glBindAttribLocation(m_program, NzOpenGL::VertexComponentIndex[nzVertexComponent_Userdata3], "VertexUserdata3"); glBindAttribLocation(m_program, NzOpenGL::VertexComponentIndex[nzVertexComponent_Userdata4], "VertexUserdata4"); if (NzRenderer::HasCapability(nzRendererCap_MultipleRenderTargets)) { NzString uniform; uniform = "RenderTarget"; unsigned int maxRenderTargets = NzRenderer::GetMaxRenderTargets(); for (unsigned int i = 0; i < maxRenderTargets; ++i) { NzString uniformName = uniform + NzString::Number(i); glBindFragDataLocation(m_program, i, uniformName.GetConstBuffer()); } } if (NzOpenGL::IsSupported(nzOpenGLExtension_GetProgramBinary)) glProgramParameteri(m_program, GL_PROGRAM_BINARY_RETRIEVABLE_HINT, GL_TRUE); return true; }
bool NzDirectory::Exists(const NzString& dirPath) { if (dirPath.IsEmpty()) return false; return NzDirectoryImpl::Exists(NzFile::NormalizePath(dirPath)); }
bool NzDirectory::Remove(const NzString& dirPath, bool emptyDirectory) { if (dirPath.IsEmpty()) return false; if (emptyDirectory) { NzDirectory dir(dirPath); if (!dir.Open()) return NzDirectoryImpl::Remove(dirPath); // Si on n'arrive pas à ouvrir le dossier, on tente de le supprimer while (dir.NextResult(true)) { if (dir.IsResultDirectory()) { if (!Remove(dir.GetResultPath(), true)) return false; } else if (!NzFile::Delete(dir.GetResultPath())) { NazaraError(dir.GetResultPath()); return false; } } dir.Close(); } return NzDirectoryImpl::Remove(NzFile::NormalizePath(dirPath)); }
void NzUberShaderPreprocessor::SetShader(nzShaderStage stage, const NzString& source, const NzString& shaderFlags, const NzString& requiredFlags) { Shader& shader = m_shaders[stage]; shader.present = true; shader.source = source; // On extrait les flags de la chaîne std::vector<NzString> flags; shaderFlags.Split(flags, ' '); for (NzString& flag : flags) { auto it = m_flags.find(flag); if (it == m_flags.end()) m_flags[flag] = 1U << m_flags.size(); auto it2 = shader.flags.find(flag); if (it2 == shader.flags.end()) shader.flags[flag] = 1U << shader.flags.size(); } // On construit les flags requis pour l'activation du shader shader.requiredFlags = 0; flags.clear(); requiredFlags.Split(flags, ' '); for (NzString& flag : flags) { nzUInt32 flagVal; auto it = m_flags.find(flag); if (it == m_flags.end()) { flagVal = 1U << m_flags.size(); m_flags[flag] = flagVal; } else flagVal = it->second; shader.requiredFlags |= flagVal; } }
bool NzDirectory::Copy(const NzString& sourcePath, const NzString& destPath) { if (sourcePath.IsEmpty() || destPath.IsEmpty()) return false; NzString dirPath(sourcePath); NzString dest(NzFile::NormalizePath(destPath)); if (!Create(destPath, true)) { NazaraError("Unable to create \"" + destPath + '"'); return false; } NzDirectory dir(dirPath); if (!dir.Open()) { NazaraError("Unable to open \"" + destPath + '"'); return false; } while (dir.NextResult(true)) { if (dir.IsResultDirectory()) { if (!Copy(dir.GetResultPath(), dest + NAZARA_DIRECTORY_SEPARATOR + dir.GetResultName())) return false; } else if (!NzFile::Copy(dir.GetResultPath(), dest + NAZARA_DIRECTORY_SEPARATOR + dir.GetResultName())) { NazaraError("Failed to copy \"" + dir.GetResultPath() + "\" to \"" + dest + NAZARA_DIRECTORY_SEPARATOR + dir.GetResultName() + '"'); return false; } } dir.Close(); return true; }
NzString NzShaderStage::GetSource() const { #if NAZARA_RENDERER_SAFE if (!m_id) { NazaraError("Shader stage is not initialized"); return NzString(); } #endif NzString source; GLint length = 0; glGetShaderiv(m_id, GL_SHADER_SOURCE_LENGTH, &length); if (length > 1) // Le caractère de fin compte { source.Set(length - 1, '\0'); // La taille retournée est celle du buffer (Avec caractère de fin) glGetShaderSource(m_id, length, nullptr, &source[0]); } return source; }
NzString NzShaderStage::GetLog() const { #if NAZARA_RENDERER_SAFE if (!m_id) { NazaraError("Shader stage is not initialized"); return NzString(); } #endif NzString log; GLint length = 0; glGetShaderiv(m_id, GL_INFO_LOG_LENGTH, &length); if (length > 1) // Le caractère de fin faisant partie du compte { log.Set(length - 1, '\0'); // La taille retournée est celle du buffer (Avec caractère de fin) glGetShaderInfoLog(m_id, length, nullptr, &log[0]); } else log = "No log."; return log; }
void NzMesh::AddSubMesh(const NzString& identifier, NzSubMesh* subMesh) { #if NAZARA_UTILITY_SAFE if (!m_impl) { NazaraError("Mesh not created"); return; } if (identifier.IsEmpty()) { NazaraError("Identifier is empty"); return; } auto it = m_impl->subMeshMap.find(identifier); if (it != m_impl->subMeshMap.end()) { NazaraError("SubMesh identifier \"" + identifier + "\" is already used"); return; } if (!subMesh) { NazaraError("Invalid submesh"); return; } if (m_impl->animationType != subMesh->GetAnimationType()) { NazaraError("Submesh animation type must match mesh animation type"); return; } #endif int index = m_impl->subMeshes.size(); subMesh->AddResourceListener(this, index); subMesh->AddResourceReference(); m_impl->aabbUpdated = false; // On invalide l'AABB m_impl->subMeshes.push_back(subMesh); m_impl->subMeshMap[identifier] = index; }
bool NzWindowImpl::Create(const NzVideoMode& mode, const NzString& title, nzUInt32 style) { bool fullscreen = (style & nzWindowStyle_Fullscreen) != 0; DWORD win32Style, win32StyleEx; unsigned int x, y; unsigned int width = mode.width; unsigned int height = mode.height; if (fullscreen) { DEVMODE win32Mode; std::memset(&win32Mode, 0, sizeof(DEVMODE)); win32Mode.dmBitsPerPel = mode.bitsPerPixel; win32Mode.dmPelsHeight = mode.height; win32Mode.dmPelsWidth = mode.width; win32Mode.dmFields = DM_BITSPERPEL | DM_PELSWIDTH | DM_PELSHEIGHT; win32Mode.dmSize = sizeof(DEVMODE); if (ChangeDisplaySettings(&win32Mode, CDS_FULLSCREEN) != DISP_CHANGE_SUCCESSFUL) { // Situation extrêmement rare grâce à NzVideoMode::IsValid appelé par NzWindow NazaraError("Failed to change display settings for fullscreen, this video mode is not supported by your computer"); fullscreen = false; } } // Testé une seconde fois car sa valeur peut changer if (fullscreen) { x = 0; y = 0; win32Style = WS_CLIPCHILDREN | WS_POPUP; // Pour cacher la barre des tâches // http://msdn.microsoft.com/en-us/library/windows/desktop/ff700543(v=vs.85).aspx win32StyleEx = WS_EX_APPWINDOW; fullscreenWindow = this; } else { win32Style = WS_VISIBLE; if (style & nzWindowStyle_Titlebar) { win32Style |= WS_CAPTION | WS_MINIMIZEBOX; if (style & nzWindowStyle_Closable) win32Style |= WS_SYSMENU; if (style & nzWindowStyle_Resizable) win32Style |= WS_MAXIMIZEBOX | WS_SIZEBOX; } else win32Style |= WS_POPUP; win32StyleEx = 0; RECT rect = {0, 0, static_cast<LONG>(width), static_cast<LONG>(height)}; AdjustWindowRect(&rect, win32Style, false); width = rect.right-rect.left; height = rect.bottom-rect.top; x = (GetSystemMetrics(SM_CXSCREEN) - width)/2; y = (GetSystemMetrics(SM_CYSCREEN) - height)/2; } m_callback = 0; #if NAZARA_UTILITY_THREADED_WINDOW NzMutex mutex; NzConditionVariable condition; m_threadActive = true; // On attend que la fenêtre soit créée mutex.Lock(); m_thread = NzThread(WindowThread, &m_handle, win32StyleEx, title.GetWideString().data(), win32Style, x, y, width, height, this, &mutex, &condition); condition.Wait(&mutex); mutex.Unlock(); #else m_handle = CreateWindowExW(win32StyleEx, className, title.GetWideString().data(), win32Style, x, y, width, height, nullptr, nullptr, GetModuleHandle(nullptr), this); #endif if (!m_handle) { NazaraError("Failed to create window: " + NzError::GetLastSystemError()); return false; } if (fullscreen) { SetForegroundWindow(m_handle); ShowWindow(m_handle, SW_SHOW); } m_eventListener = true; m_ownsWindow = true; #if !NAZARA_UTILITY_THREADED_WINDOW m_sizemove = false; #endif m_style = style; // Récupération de la position/taille de la fenêtre (Après sa création) RECT clientRect, windowRect; GetClientRect(m_handle, &clientRect); GetWindowRect(m_handle, &windowRect); m_position.Set(windowRect.left, windowRect.top); m_size.Set(clientRect.right - clientRect.left, clientRect.bottom - clientRect.top); return true; }
nzLuaType NzLuaInstance::GetGlobal(const NzString& name) const { return FromLuaType(lua_getglobal(m_state, name.GetConstBuffer())); }
bool NzPluginManager::Mount(const NzString& pluginPath, bool appendExtension) { if (!Initialize()) { NazaraError("Failed to initialize PluginManager"); return false; } NzString path = pluginPath; if (appendExtension && !path.EndsWith(NAZARA_DYNLIB_EXTENSION)) path += NAZARA_DYNLIB_EXTENSION; bool exists = false; if (!NzFile::IsAbsolute(path)) { for (const NzString& dir : s_directories) { NzString testPath; testPath.Reserve(dir.GetSize() + path.GetSize() + 10); testPath = dir; testPath += NAZARA_DIRECTORY_SEPARATOR; testPath += path; if (NzFile::Exists(testPath)) { path = testPath; exists = true; break; } } } else if (NzFile::Exists(path)) exists = true; if (!exists) { NazaraError("Failed to find plugin file"); return false; } std::unique_ptr<NzDynLib> library(new NzDynLib); if (!library->Load(path)) { NazaraError("Failed to load plugin"); return false; } PluginLoad func = reinterpret_cast<PluginLoad>(library->GetSymbol("NzPluginLoad")); if (!func) { NazaraError("Failed to get symbol NzPluginLoad"); return false; } if (!func()) { NazaraError("Plugin failed to load"); return false; } s_plugins[pluginPath] = library.release(); return true; }
nzLuaType NzLuaInstance::GetMetatable(const NzString& tname) const { return FromLuaType(luaL_getmetatable(m_state, tname.GetConstBuffer())); }
bool NzLuaInstance::IsOfType(int index, const NzString& tname) const { return IsOfType(index, tname.GetConstBuffer()); }
void NzLuaInstance::PushMetatable(const NzString& str) { luaL_getmetatable(m_state, str.GetConstBuffer()); }
void NzLuaInstance::Error(const NzString& message) { luaL_error(m_state, message.GetConstBuffer()); }
bool NzDirectory::Create(const NzString& dirPath, bool recursive) { if (dirPath.IsEmpty()) return false; if (recursive) { NzString path = NzFile::NormalizePath(dirPath); unsigned int foundPos = path.Find(NAZARA_DIRECTORY_SEPARATOR); if (foundPos == NzString::npos) return false; #ifdef NAZARA_PLATFORM_WINDOWS // Contrairement au disque (Ex: "C:"), le chemin réseau n'est pas considéré comme un dossier (Ex: "\\Laptop") if (path.Match("\\\\*")) { foundPos = path.Find('\\', 2); if (foundPos == NzString::npos) return false; foundPos = path.Find('\\', foundPos+1); if (foundPos == NzString::npos) return false; } #endif do { NzString p = path.SubString(0, foundPos); if (p.EndsWith(NAZARA_DIRECTORY_SEPARATOR)) p = p.SubString(0, -2); if (!NzDirectoryImpl::Exists(p) && !NzDirectoryImpl::Create(p)) return false; if (foundPos == NzString::npos) break; foundPos = path.Find(NAZARA_DIRECTORY_SEPARATOR, foundPos+1); } while (true); return true; } else return NzDirectoryImpl::Create(NzFile::NormalizePath(dirPath)); }
void NzWindowImpl::SetTitle(const NzString& title) { SetWindowTextW(m_handle, title.GetWideString().data()); }
void NzLuaInstance::SetMetatable(const NzString& tname) { luaL_setmetatable(m_state, tname.GetConstBuffer()); }
void NzLuaInstance::SetGlobal(const NzString& name) { lua_setglobal(m_state, name.GetConstBuffer()); }
void NzLuaInstance::SetField(const NzString& name, int index) { lua_setfield(m_state, index, name.GetConstBuffer()); }
void NzLuaInstance::PushString(const NzString& str) { lua_pushlstring(m_state, str.GetConstBuffer(), str.GetSize()); }
nzLuaType NzLuaInstance::GetField(const NzString& fieldName, int index) const { return FromLuaType(lua_getfield(m_state, index, fieldName.GetConstBuffer())); }
bool NzMTLParser::Parse() { m_keepLastLine = false; m_lineCount = 0; m_materials.clear(); Material* currentMaterial = nullptr; while (Advance(false)) { NzString keyword = m_currentLine.GetWord(0).ToLower(); if (keyword == "ka") { float r, g, b; if (std::sscanf(&m_currentLine[3], "%f %f %f", &r, &g, &b) == 3) { if (!currentMaterial) currentMaterial = &m_materials["default"]; currentMaterial->ambient = NzColor(r*255.f, g*255.f, b*255.f); } #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) { if (!currentMaterial) currentMaterial = &m_materials["default"]; currentMaterial->diffuse = NzColor(r*255.f, g*255.f, b*255.f); } #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) { if (!currentMaterial) currentMaterial = &m_materials["default"]; currentMaterial->specular = NzColor(r*255.f, g*255.f, b*255.f); } #if NAZARA_UTILITY_STRICT_RESOURCE_PARSING else UnrecognizedLine(); #endif } else if (keyword == "ni") { float density; if (std::sscanf(&m_currentLine[3], "%f", &density) == 1) { if (!currentMaterial) currentMaterial = &m_materials["default"]; currentMaterial->refractionIndex = density; } #if NAZARA_UTILITY_STRICT_RESOURCE_PARSING else UnrecognizedLine(); #endif } else if (keyword == "ns") { float coef; if (std::sscanf(&m_currentLine[3], "%f", &coef) == 1) { if (!currentMaterial) currentMaterial = &m_materials["default"]; currentMaterial->shininess = coef; } #if NAZARA_UTILITY_STRICT_RESOURCE_PARSING else UnrecognizedLine(); #endif } else if (keyword == 'd' || keyword == "tr") { float alpha; if (std::sscanf(&m_currentLine[(keyword[0] == 'd') ? 2 : 3], "%f", &alpha) == 1) { if (!currentMaterial) currentMaterial = &m_materials["default"]; currentMaterial->alpha = alpha; } #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 = &m_materials["default"]; currentMaterial->illumModel = model; } #if NAZARA_UTILITY_STRICT_RESOURCE_PARSING else UnrecognizedLine(); #endif } else if (keyword == "map_ka") { unsigned int mapPos = m_currentLine.GetWordPosition(1); if (mapPos != NzString::npos) { NzString map = m_currentLine.SubString(mapPos); if (!currentMaterial) currentMaterial = &m_materials["default"]; currentMaterial->ambientMap = map; } } else if (keyword == "map_kd") { unsigned int mapPos = m_currentLine.GetWordPosition(1); if (mapPos != NzString::npos) { NzString map = m_currentLine.SubString(mapPos); if (!currentMaterial) currentMaterial = &m_materials["default"]; currentMaterial->diffuseMap = map; } } else if (keyword == "map_ks") { unsigned int mapPos = m_currentLine.GetWordPosition(1); if (mapPos != NzString::npos) { NzString map = m_currentLine.SubString(mapPos); if (!currentMaterial) currentMaterial = &m_materials["default"]; currentMaterial->specularMap = map; } } else if (keyword == "map_bump" || keyword == "bump") { unsigned int mapPos = m_currentLine.GetWordPosition(1); if (mapPos != NzString::npos) { NzString map = m_currentLine.SubString(mapPos); if (!currentMaterial) currentMaterial = &m_materials["default"]; currentMaterial->bumpMap = map; } } else if (keyword == "map_d") { unsigned int mapPos = m_currentLine.GetWordPosition(1); if (mapPos != NzString::npos) { NzString map = m_currentLine.SubString(mapPos); if (!currentMaterial) currentMaterial = &m_materials["default"]; currentMaterial->alphaMap = map; } } else if (keyword == "map_decal" || keyword == "decal") { unsigned int mapPos = m_currentLine.GetWordPosition(1); if (mapPos != NzString::npos) { NzString map = m_currentLine.SubString(mapPos); if (!currentMaterial) currentMaterial = &m_materials["default"]; currentMaterial->decalMap = map; } } else if (keyword == "map_disp" || keyword == "disp") { unsigned int mapPos = m_currentLine.GetWordPosition(1); if (mapPos != NzString::npos) { NzString map = m_currentLine.SubString(mapPos); if (!currentMaterial) currentMaterial = &m_materials["default"]; currentMaterial->displacementMap = map; } } else if (keyword == "map_refl" || keyword == "refl") { unsigned int mapPos = m_currentLine.GetWordPosition(1); if (mapPos != NzString::npos) { NzString map = m_currentLine.SubString(mapPos); if (!currentMaterial) currentMaterial = &m_materials["default"]; currentMaterial->reflectionMap = map; } } else if (keyword == "newmtl") { NzString materialName = m_currentLine.SubString(m_currentLine.GetWordPosition(1)); if (!materialName.IsEmpty()) currentMaterial = &m_materials[materialName]; #if NAZARA_UTILITY_STRICT_RESOURCE_PARSING else UnrecognizedLine(); #endif } #if NAZARA_UTILITY_STRICT_RESOURCE_PARSING else UnrecognizedLine(); #endif } return true; }
bool NzOBJParser::Parse() { NzString matName, meshName; matName = meshName = "default"; m_keepLastLine = false; m_lineCount = 0; m_meshes.clear(); m_mtlLib.Clear(); m_normals.clear(); m_positions.clear(); m_texCoords.clear(); // Beaucoup de meshs font plus de 100 sommets, préparons le terrain m_normals.reserve(100); m_positions.reserve(100); m_texCoords.reserve(100); // On va regrouper les meshs par nom et par matériau std::unordered_map<NzString, std::unordered_map<NzString, std::vector<Face>>> meshes; // On prépare le mesh par défaut std::vector<Face>* currentMesh = &meshes[meshName][matName]; while (Advance(false)) { switch (std::tolower(m_currentLine[0])) { case 'f': // Une face { if (m_currentLine.GetSize() < 7) // Le minimum syndical pour définir une face de trois sommets (f 1 2 3) { #if NAZARA_UTILITY_STRICT_RESOURCE_PARSING UnrecognizedLine(); #endif break; } unsigned int vertexCount = m_currentLine.Count(' '); if (vertexCount < 3) { #if NAZARA_UTILITY_STRICT_RESOURCE_PARSING UnrecognizedLine(); #endif break; } Face face; face.vertices.resize(vertexCount); bool error = false; unsigned int pos = 2; for (unsigned int i = 0; i < vertexCount; ++i) { int offset; int& n = face.vertices[i].normal; int& p = face.vertices[i].position; int& t = face.vertices[i].texCoord; if (std::sscanf(&m_currentLine[pos], "%d/%d/%d%n", &p, &t, &n, &offset) != 3) { if (std::sscanf(&m_currentLine[pos], "%d//%d%n", &p, &n, &offset) != 2) { if (std::sscanf(&m_currentLine[pos], "%d/%d%n", &p, &t, &offset) != 2) { if (std::sscanf(&m_currentLine[pos], "%d%n", &p, &offset) != 1) { #if NAZARA_UTILITY_STRICT_RESOURCE_PARSING UnrecognizedLine(); #endif error = true; break; } else { n = 0; t = 0; } } else n = 0; } else t = 0; } if (p < 0) { p += m_positions.size(); if (p < 0) { Error("Vertex index out of range (" + NzString::Number(p) + " < 0"); error = true; break; } } else p--; if (n < 0) { n += m_normals.size(); if (n < 0) { Error("Vertex index out of range (" + NzString::Number(n) + " < 0"); error = true; break; } } else n--; if (t < 0) { t += m_texCoords.size(); if (t < 0) { Error("Vertex index out of range (" + NzString::Number(t) + " < 0"); error = true; break; } } else t--; if (static_cast<unsigned int>(p) >= m_positions.size()) { Error("Vertex index out of range (" + NzString::Number(p) + " >= " + NzString::Number(m_positions.size()) + ')'); error = true; break; } else if (n >= 0 && static_cast<unsigned int>(n) >= m_normals.size()) { Error("Normal index out of range (" + NzString::Number(n) + " >= " + NzString::Number(m_normals.size()) + ')'); error = true; break; } else if (t >= 0 && static_cast<unsigned int>(t) >= m_texCoords.size()) { Error("TexCoord index out of range (" + NzString::Number(t) + " >= " + NzString::Number(m_texCoords.size()) + ')'); error = true; break; } pos += offset; } if (!error) currentMesh->push_back(std::move(face)); break; } case 'm': #if NAZARA_UTILITY_STRICT_RESOURCE_PARSING if (m_currentLine.GetWord(0).ToLower() != "mtllib") UnrecognizedLine(); #endif m_mtlLib = m_currentLine.SubString(m_currentLine.GetWordPosition(1)); break; case 'g': case 'o': { if (m_currentLine.GetSize() <= 2 || m_currentLine[1] != ' ') { #if NAZARA_UTILITY_STRICT_RESOURCE_PARSING UnrecognizedLine(); #endif break; } NzString objectName = m_currentLine.SubString(m_currentLine.GetWordPosition(1)); if (objectName.IsEmpty()) { #if NAZARA_UTILITY_STRICT_RESOURCE_PARSING UnrecognizedLine(); #endif break; } meshName = objectName; currentMesh = &meshes[meshName][matName]; break; } #if NAZARA_UTILITY_STRICT_RESOURCE_PARSING case 's': if (m_currentLine.GetSize() <= 2 || m_currentLine[1] == ' ') { NzString param = m_currentLine.SubString(2); if (param != "all" && param != "on" && param != "off" && !param.IsNumber()) UnrecognizedLine(); } else UnrecognizedLine(); break; #endif case 'u': #if NAZARA_UTILITY_STRICT_RESOURCE_PARSING if (m_currentLine.GetWord(0) != "usemtl") UnrecognizedLine(); #endif matName = m_currentLine.SubString(m_currentLine.GetWordPosition(1)); if (matName.IsEmpty()) { #if NAZARA_UTILITY_STRICT_RESOURCE_PARSING UnrecognizedLine(); #endif break; } currentMesh = &meshes[meshName][matName]; break; case 'v': { NzString word = m_currentLine.GetWord(0).ToLower(); if (word == 'v') { NzVector4f vertex(NzVector3f::Zero(), 1.f); unsigned int paramCount = std::sscanf(&m_currentLine[2], "%f %f %f %f", &vertex.x, &vertex.y, &vertex.z, &vertex.w); if (paramCount >= 3) m_positions.push_back(vertex); #if NAZARA_UTILITY_STRICT_RESOURCE_PARSING else UnrecognizedLine(); #endif } else if (word == "vn") { NzVector3f normal(NzVector3f::Zero()); 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 else UnrecognizedLine(); #endif } else if (word == "vt") { NzVector3f uvw(NzVector3f::Zero()); 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 else UnrecognizedLine(); #endif } #if NAZARA_UTILITY_STRICT_RESOURCE_PARSING else UnrecognizedLine(); #endif break; } default: #if NAZARA_UTILITY_STRICT_RESOURCE_PARSING UnrecognizedLine(); #endif break; } } std::unordered_map<NzString, unsigned int> materials; unsigned int matCount = 0; for (auto& meshIt : meshes) { for (auto& matIt : meshIt.second) { if (!matIt.second.empty()) { Mesh mesh; mesh.faces = std::move(matIt.second); mesh.name = meshIt.first; auto it = materials.find(matIt.first); if (it == materials.end()) { mesh.material = matCount; materials[matIt.first] = matCount++; } else mesh.material = it->second; m_meshes.push_back(std::move(mesh)); } } } if (m_meshes.empty()) { NazaraError("No meshes"); return false; } m_materials.resize(matCount); for (const std::pair<NzString, unsigned int>& pair : materials) m_materials[pair.second] = pair.first; return true; }
bool NzLuaInstance::NewMetatable(const NzString& str) { return luaL_newmetatable(m_state, str.GetConstBuffer()) != 0; }