Loading single geometry files

Problems building or running the engine, queries about how to use features etc.
Post Reply
Pellaeon
Goblin
Posts: 220
Joined: Thu Apr 28, 2011 12:23 pm
x 25

Loading single geometry files

Post by Pellaeon »

Ogre Version: 1.13.4
Operating System: Win 10
Render System: DX9/DX11

Hi,

is there a way to load single geometry files with inclusion of the assimp module?
Normally, I add a file path to the resource system, load my resource group and then I use the meshes. For all default geometry this is fine.
But in my application there is a possibility to add objects at runtime for the user. There is a classical file open dialog where the user can choose the file which is to add. So I want to take the file, load the geometry and that's it, without expanding my resoure system with a new filesystem location.

Atm I use the below code to load mesh files manually. Now I'd also like to have the possibility to load other file formats with the assimp plugin. My current code can't handle this. I always get an error. I suppose the below code only loads mesh files and never invokes the assimp plugin.

Is there a way to get the desired behaviour, to include the assimp plugin in a simple "load and show file" use case?

Code: Select all

Ogre::SceneNode* Machine_tool_graphic::create_scene_node_from_files(const std::wstring& file)
{
	//at first we check that the path is really a file
	if (!std::filesystem::is_regular_file(std::filesystem::path(file)))
	{
		throw Ogre::Exception(Ogre::Exception::ERR_FILE_NOT_FOUND, "No regular file", "MachineToolGraphic::loadMesh");
	}

	//set resource path		
	auto file_path = std::filesystem::absolute(std::filesystem::path(file));
		
	//second, we must load the mesh into ogre resources
	std::fstream fs(file, std::ios_base::in | std::ios_base::binary);
	Ogre::SharedPtr<Ogre::DataStream> ogre_stream (new Ogre::FileStreamDataStream(&fs, false));

	//2
	auto p_mesh = Ogre::MeshManager::getSingleton().getByName(file_path.string(), m_res_group_name_devices);
	if (!p_mesh)
	{
		p_mesh = Ogre::MeshManager::getSingleton().createManual(file_path.string(), m_res_group_name_devices);

		Ogre::MeshSerializer mesh_serializer;
		mesh_serializer.importMesh(ogre_stream, p_mesh.get());
	}
	
	//now we create the entity and a scene node
	auto entity = m_ogre_mng.getSceneManager()->createEntity(p_mesh);

	Ogre::SceneNode* p_node = m_ogre_mng.getSceneManager()->createSceneNode();
	p_node->attachObject(entity);	

	return p_node;
}
Pellaeon
Goblin
Posts: 220
Joined: Thu Apr 28, 2011 12:23 pm
x 25

Re: Loading single geometry files

Post by Pellaeon »

This means it should already work? But when giving an OBJ file to my upper code in the first post, I got an exception. The code doesn't load the obj file.
paroj
OGRE Team Member
OGRE Team Member
Posts: 1612
Joined: Sun Mar 30, 2014 2:51 pm
x 787
Contact:

Re: Loading single geometry files

Post by paroj »

no, this is the code that you should copy paste instead of what you are currently doing
Pellaeon
Goblin
Posts: 220
Joined: Thu Apr 28, 2011 12:23 pm
x 25

Re: Loading single geometry files

Post by Pellaeon »

paroj wrote: Wed Jan 12, 2022 1:11 pm no, this is the code that you should copy paste instead of what you are currently doing
Thank you for the hint!

I copied the code and adjusted it to my variables (see below). The code still works fine for mesh files. But it doesn't load e.g. my OBJ file.
There is no exception, but the log file tells me:
Error, T13752: No suitable reader found for the file format of file "".
Ogre: Assimp: Error, T13752: No suitable reader found for the file format of file "".
Ogre: Error: Assimp failed - No suitable reader found for the file format of file "".

Code: Select all

Ogre::SceneNode* Machine_tool_graphic::create_scene_node_from_files(const std::wstring& file)
{
	//at first we check that the path is really a file
	if (!std::filesystem::is_regular_file(std::filesystem::path(file)))
	{
		throw Ogre::Exception(Ogre::Exception::ERR_FILE_NOT_FOUND, "No regular file", "MachineToolGraphic::loadMesh");
	}

	//set resource path		
	auto file_path = std::filesystem::absolute(std::filesystem::path(file));

	//second, we must load the mesh into ogre resources
	std::fstream fs(file, std::ios_base::in | std::ios_base::binary);
	Ogre::SharedPtr<Ogre::DataStream> ogre_stream(new Ogre::FileStreamDataStream(&fs, false));

	//2
	auto p_mesh = Ogre::MeshManager::getSingleton().getByName(file_path.string(), m_res_group_name_devices);
	if (!p_mesh)
	{
		p_mesh = Ogre::MeshManager::getSingleton().createManual(file_path.string(), m_res_group_name_devices);

		Ogre::String baseName, strExt;
		Ogre::StringUtil::splitBaseFilename(file_path.string(), baseName, strExt);
		auto codec = Codec::getCodec(strExt);
		if (!codec)
			throw Ogre::Exception(Ogre::Exception::ERR_FILE_NOT_FOUND, "No codec found to load", "MachineToolGraphic::loadMesh");
			
		codec->decode(ogre_stream, p_mesh.get());
	}

	//now we create the entity and a scene node
	auto entity = m_ogre_mng.getSceneManager()->createEntity(p_mesh);

	Ogre::SceneNode* p_node = m_ogre_mng.getSceneManager()->createSceneNode();
	p_node->attachObject(entity);

	return p_node;
}
paroj
OGRE Team Member
OGRE Team Member
Posts: 1612
Joined: Sun Mar 30, 2014 2:51 pm
x 787
Contact:

Re: Loading single geometry files

Post by paroj »

set the name of FileStreamDataStream to your filepath
Pellaeon
Goblin
Posts: 220
Joined: Thu Apr 28, 2011 12:23 pm
x 25

Re: Loading single geometry files

Post by Pellaeon »

paroj wrote: Thu Jan 13, 2022 6:33 pm set the name of FileStreamDataStream to your filepath
Thank you very much! This helped to solve it. There was one more pitfall. My target platform is windows, where boost filesystem delivers paths with backslashs. During loading in the codec, the assimp loader normalizes the file path (which changes the '\' to '/') and checks the wished file against the id of the filestream, which results in an error, that the loader can't open the file.

Code from assimploader.cpp from ogre:

Code: Select all

bool Exists(const char* pFile) const
{
    String file = StringUtil::normalizeFilePath(pFile, false);
   if (file == source->getName()) //fails if original path is defined with '\'
        return true;
    return ResourceGroupManager::getSingleton().resourceExists(_group, file);
}
I normalized the file path in the same way before setting it as ID in the file stream object. Now it works!

Perhaps one last general question. Is this approach a clean approach regarding memory management in your opinion? For all static resources, I use the resource system as it is designed in the ogre engine. But for this special case, it seems much easier for me to realise a simple single file load process instead of trying to force it into the resource system.

When the user deletes such an object, I call Ogre::MeshManager::getSingleton().removeUnreferencedResources() to remove dangling meshes. Does this also check for unused materials? Or do I need to check for unused materials (which could be created by the assimp loader, e.g. from MTL files) separately?
paroj
OGRE Team Member
OGRE Team Member
Posts: 1612
Joined: Sun Mar 30, 2014 2:51 pm
x 787
Contact:

Re: Loading single geometry files

Post by paroj »

I think your approach is much more complicated than just adding a special resource group for the user specified location. Also you lose the ability to reload resources from disk (on e.g. context loss) by using manual resources. Still, if it works for you, then its probably ok..

No, the MeshManager does not unload Materials or Textures.
Post Reply