I'm trying to open a file as output so that I can write converted model data to my file. The problem currently is, even though the path does exist, and the file is created, it isn't actually open. I've tried removing the !is_open() check and of course it segfaults since it isn't open. I've added ios_base modes to specify how to open the file, and tried switching to a blank ofstream constructor and implicitly calling .open() to no result.
Again, the path is absolutely correct, a file is in fact created at the right path, it just isn't opening for whatever reason. Permissions are fine, I even tried running as root to no success.
void AssetConverter::ConvertModel(const std::string importPath, std::string exportPath, ModelImportSettings* settings) {
// assimp has a comically massive footprint which is why i create it implicitly
Assimp::Importer* importer = new Assimp::Importer();
const aiScene* scene = importer->ReadFile(importPath,
aiProcess_Triangulate
| aiProcess_OptimizeMeshes
| aiProcess_OptimizeGraph
);
delete importer;
if(scene == nullptr) {
Debug::LogError("Couldn't import model from path: " + importPath);
return;
}
bool skinned;
switch (settings->isSkinnedMesh) {
case TRI_TRUE:
skinned = true;
break;
case TRI_FALSE:
skinned = false;
break;
default: // Auto
skinned = scene->HasSkeletons();
break;
}
std::filesystem::path iP(importPath);
exportPath = std::filesystem::absolute(exportPath);
ModelBase m;
if(skinned) {
m = CreateSkinnedModel(scene);
exportPath += "/" + iP.stem().string() + ".nems";
} else {
m = CreateModel(scene);
exportPath += "/" + iP.stem().string() + ".nem";
}
if(std::filesystem::exists(exportPath)) {
std::filesystem::remove(exportPath);
}
// Actual problem starts here
std::ofstream outFile(exportPath, std::ios_base::out | std::ios_base::binary | std::ios_base::trunc);
if(outFile.bad()) {
Debug::LogError("Couldn't open, bad stream: " + exportPath);
return;
}
if(outFile.fail()) {
Debug::LogError("Couldn't open, failed: " + exportPath);
return;
}
if(!outFile.is_open()) {
// enters here every single time
bool exists = std::filesystem::exists(exportPath);
// i had comments showing the rage here, that i have gracefully removed
Debug::LogError("Couldn't open path for writing: " + exportPath);
if(exists) {
Debug::LogError("BUT THE PATH DOES EXIST WHWHWHWHHATATTTATT");
}
return;
}
const std::vector<uint8_t> data = m.getData();
for(unsigned char v : data) {
std::string str = std::to_string(v);
outFile.write(str.c_str(), str.length());
}
outFile.flush();
outFile.close();
}
mainprogram, with the attempt to open a file with a hardcoded name is all that would have been necessary to duplicate the issue.Assimp::Importer::ReadFile: /.../ the contents of the file are returned as a pointer to an aiScene object. The returned data is intended to be read-only, the importer object keeps ownership of the data and will destroy it upon destruction. (Emphasis mine.) This means that after youdelete importer, the data pointed to bysceneis gone! No surprise you get a segfault.outFile.flush(); outFile.close();. The destructor will do that.// Actual problem starts herewith the path hardcoded (instead ofexportPath) and error messages sent tostd::coutorstd::cerrinstead of whateverDebug::LogErroris (minimize dependencies on other code). It can end after the three checks (bad, fail, open) since you already have your symptom at that point. Furthermore, this should become yourmainfunction instead of a member function of some unknown class, so that you can copy-compile-run the code to reproduce the result.