I've been working on a program someone else wrote, doing some general clean-up. One of the things I have done is upgrade it from Irrlicht 0.14 to 1.7.1, with an interim stop at 1.3.
In the move from 1.3 to 1.7.1, I've encountered a problem with textures in .x files (exported from Maya a long time ago) not loading. I've tried several things, but with no luck (well, putting the texture in the same folder as the .x file works, but that breaks the nice clean organisation that we have). In searching the forums I've seen references to "relative path issues" but haven't found a clear indication of exactly what these are, or what the changes were.
Can anyone provide some clarification on what changed and what I need to do? From what I can see, relative paths should be recognised as they were before.
Thanks,
Hugh
Relative Texture Paths in .x files
-
- Posts: 4
- Joined: Wed Apr 07, 2010 9:02 pm
Sure. Since relative paths worked before, I figured I must be missing something obvious.
The code loads the file like so:
std::string File = Path + "Objects/Horses/horse_and_jockey.x";
IAnimatedMesh *HorseModel = smgr->getMesh(File.c_str());
The layout is
-Objects
-Horses
>horse_andjockey.x
-Textures
-Whip
>whip.jpg
The .x file has contents such as:
MeshMaterialList {
[Lots of lines of numbers cut]
Material {
1.000000;1.000000;1.000000;1.000000;;
0.000000;
0.000000;0.000000;0.000000;;
0.000000;0.000000;0.000000;;
TextureFilename {
"../../Textures/Whip/whip.jpg";
}
}
}
The error message is simple: "Could not open file of texture: whip.jpg" I've tracked this down to CNullDriver::getTexture.
Thanks,
Hugh
The code loads the file like so:
std::string File = Path + "Objects/Horses/horse_and_jockey.x";
IAnimatedMesh *HorseModel = smgr->getMesh(File.c_str());
The layout is
-Objects
-Horses
>horse_andjockey.x
-Textures
-Whip
>whip.jpg
The .x file has contents such as:
MeshMaterialList {
[Lots of lines of numbers cut]
Material {
1.000000;1.000000;1.000000;1.000000;;
0.000000;
0.000000;0.000000;0.000000;;
0.000000;0.000000;0.000000;;
TextureFilename {
"../../Textures/Whip/whip.jpg";
}
}
}
The error message is simple: "Could not open file of texture: whip.jpg" I've tracked this down to CNullDriver::getTexture.
Thanks,
Hugh
-
- Posts: 4
- Joined: Wed Apr 07, 2010 9:02 pm
I've been stepping through the Irrlicht code, and, though I don't yet understand what should be happening, I think I see what is going wrong.
In the example below:
This first part works fine, returning our relative path as defined in the .x file: "../../Textures/Reins/strap.jpg"
existFile can't find the relative path, so it jumps to the else:
Here FilePath is the full path we loaded the .x file from: C:/Projects/OurProject/OurProgram/Objects/Horses//" (There's a "//" on the end, but that isn't the problem, at least not yet). The code then separates the file name from the relative path, giving us this, which is wrong: "C:/Projects/OurProject/OurProgram/Objects/Horses//strap.jpg" (This explains why the texture is found if I put it in the same directory).
existFile again can't find the file, so it jumps to:
And this line tries to load it from whatever the working directory is (it ends up generating the same path as the block above: "C:/Projects/OurProject/OurProgram/Objects/Horses//strap.jpg").
If someone could help me understand where the relative paths are supposed to be handled, I'd be happy to see if I can figure out how to handle this. I'm a little reluctant to try to patch something I don't yet understand well.
Thanks,
Hugh
In the example below:
- The mesh is loaded from: "C:\Projects\OurProject\OurProgram\Objects\Horses"
- The texture is relative to this, in "C:\Projects\OurProject\OurProgram\Textures\Reins", or "../../Textures/Reins/strap.jpg" as it is stored in the .x file.
Code: Select all
if (!parseDataObjectTextureFilename(TextureFileName))
return false;
Code: Select all
// original name
if (FileSystem->existFile(TextureFileName))
material.setTexture(textureLayer, SceneManager->getVideoDriver()->getTexture(TextureFileName));
Code: Select all
// mesh path
else
{
TextureFileName=FilePath + FileSystem->getFileBasename(TextureFileName);
if (FileSystem->existFile(TextureFileName))
material.setTexture(textureLayer, SceneManager->getVideoDriver()->getTexture(TextureFileName));
existFile again can't find the file, so it jumps to:
Code: Select all
// working directory
else
material.setTexture(textureLayer, SceneManager->getVideoDriver()->getTexture(FileSystem->getFileBasename(TextureFileName)));
If someone could help me understand where the relative paths are supposed to be handled, I'd be happy to see if I can figure out how to handle this. I'm a little reluctant to try to patch something I don't yet understand well.
Thanks,
Hugh
Have you tried doingdistributist wrote:In the example below:
- The mesh is loaded from: "C:\Projects\OurProject\OurProgram\Objects\Horses"
- The texture is relative to this, in "C:\Projects\OurProject\OurProgram\Textures\Reins", or "../../Textures/Reins/strap.jpg" as it is stored in the .x file.
Code: Select all
changeWorkingDirectoryTo("C:\Projects\OurProject\OurProgram\Objects\Horses");
Irrlicht Demos: http://irrlicht.sourceforge.net/forum/viewtopic.php?f=6&t=45781
-
- Posts: 4
- Joined: Wed Apr 07, 2010 9:02 pm
Sorry for the delay in replying. I had to deal with some other issues and just got back to this. Yes, this solves the problem.sio2 wrote:Have you tried doingbefore trying to load the mesh?Code: Select all
changeWorkingDirectoryTo("C:\Projects\OurProject\OurProgram\Objects\Horses");
The original code doesn't use changeWorkingDirectory anywhere. Earlier versions of Irrlicht's loader must have automatically used the animation file's path as the default, whereas later versions (somewhere after 1.3) must have used the file system object's working directory as the default.
While this is a change, I'm not sure it's a bug. The earlier behaviour was convenient, but I can certainly see how you could make the decision to implement it either way.
Thanks again for everyone's help with this.
I just digged into that problem for a while. I couldn't really find out if this had ever been different - at least not in the loader. But maybe I missed that as there had been a lot of changes. Anyway that does not matter so much - I get what you are asking for here and it's for example working that way for .obj files.
And well, I suppose the real problem we are having is that each loader does code the way to find texture itself and so we hunt those problems rather often. I think the solution is to add one tool-function which takes the mesh-filename (or at least the folder-name part of it), the user defined texture-path (some filetypes allow setting that) and figures out the best name to use from that. And that function should include relative paths starting from the mesh. Afterwards we can just use that function for all meshloaders - or at least I hope so.
Btw - I also found the reason for the double slashes (//), but that didn't cause the problems here.
Not sure when I will find time to fix this, I suppose it's rather something for 1.8 as there are still a few more urgent bugs I have to work at. But thanks for reporting, I try to get to it, it's something that has bothered me already a few times ;-)
And well, I suppose the real problem we are having is that each loader does code the way to find texture itself and so we hunt those problems rather often. I think the solution is to add one tool-function which takes the mesh-filename (or at least the folder-name part of it), the user defined texture-path (some filetypes allow setting that) and figures out the best name to use from that. And that function should include relative paths starting from the mesh. Afterwards we can just use that function for all meshloaders - or at least I hope so.
Btw - I also found the reason for the double slashes (//), but that didn't cause the problems here.
Not sure when I will find time to fix this, I suppose it's rather something for 1.8 as there are still a few more urgent bugs I have to work at. But thanks for reporting, I try to get to it, it's something that has bothered me already a few times ;-)
IRC: #irrlicht on irc.libera.chat
Code snippet repository: https://github.com/mzeilfelder/irr-playground-micha
Free racer made with Irrlicht: http://www.irrgheist.com/hcraftsource.htm
Code snippet repository: https://github.com/mzeilfelder/irr-playground-micha
Free racer made with Irrlicht: http://www.irrgheist.com/hcraftsource.htm