TextureManager serializing state problem

Started by LoTan, February 23, 2014, 10:36:24 PM

Previous topic - Next topic

LoTan

I am attempting to serialize the texture manager's state to disk and then reload it at another time.

The following code works as expected and my Object3D renders with the appropriate texture:

TextureManager textureManager= TextureManager.getInstance();
textureManager.setState(textureManager.getState());




However, as soon as I serialize this out (I tried files at first, then wrote this code to post here), reload the state, and set it on the texture manager, I get blank/black textures when my object is rendered:


TextureManager textureManager = TextureManager.getInstance();
ByteArrayOutputStream baos = new ByteArrayOutputStream();
ObjectOutputStream oos = new ObjectOutputStream(baos);
for (Object state : textureManager.getState()) {
    oos.writeObject(state);
}
oos.writeObject(null); // flag for end of stream when reading in state below
oos.flush();
oos.close();

// restore the texture manager
ObjectInputStream ois = new ObjectInputStream(new ByteArrayInputStream(baos.toByteArray()));
List<Object> state = new ArrayList<Object>();
Object o;
while ( (o = ois.readObject()) != null) {
    state.add(o);
}
textureManager.setState(state);
Log.d("TextureLoader", "Texture names in the texture manager: " + textureManager.getNames());
Log.d("TextureLoader", "Texture count: " + textureManager.getTextureCount());

               

The logcat displays the following message:
Quote
D/TextureLoader﹕ Texture names in the texture manager: [__obj-Color:163/163/163, __obj-Color:0/0/0, --dummy--]
D/TextureLoader﹕ Texture count: 3

So it appears that the textures do load, but nothing renders in the world :(  Is there something I am not doing properly when serializing or deserializing the texture manager state to where it is properly set up?

Help would be truly appreciated.

- LoTan

EgonOlsen

My first advice would be: Don't do that. It eats up a lot of storage space and i fail to see the benefit over loading the texture in the "normal" way. But if you have to: You can't really (de-)serialize the textures that way, because you also serialize the attached state information for OpenGL. But these are invalid after a resume. As a workaround, you might want to try to call


setFiltering(true);


on all textures are deserializing them. That should force the engine to upload them again and correct the state information in the process. However, i wouldn't do it in the first place...

LoTan

My primary intention is to support dynamic, user generated content in the game.  I was going to try and keep it as simple as possible - by allowing the Android client to download zip packages of OBJ/MTL files, process them using Loader.loadOBJ, and serialize out everything into a cache so that I don't have to process the OBJ/MTL for future game loads.

That said, I'm currently writing some framework code for pulling the zip files and doing processing of them on the client.  I pull down a zip of OBJ/MTL, and then serializing it to a private cache as an Object3D.  The problem I have now is I cant figure out how to get to the textures that were loaded via Loader.loadOBJ(obj,mtl) so I was dumping the texture manager because I know it has it there.

Is there a way I can just keep the MTL files around and load them dynamically, but avoid calls to the Loader.loadOBJ and just use my serialized/cached Object3D instead?

I've also never created a game before, so I could be doing this all wrong anyway :)  I'm aware of jpct desktop and the possibility of using the DeSerializer class, but I'm still lost on how I should handle the MTL files and applying them to the deserialized Object3Ds.

EgonOlsen

I'm not sure if i fully understand the problem. When loading an OBJ file in combination with a MTL, the loader will look up texture names in the TextureManager as defined in the MTL file. If it finds them, it assigns the textures. If not, it creates a dummy texture of that name. So after loading, you have a TextureManager populated with the textures used in the file, either created or prefilled by your own code with the proper textures. In addition, you will have uni-colored textures in there for the parts of the objects that had no textures but a color defined in the MTL file.
Now, you are writing the object to the sd by using Java's default serialization means. In that case, you actually have to serialize the textures too, because otherwise, they won't match when deserializing them. What i still don't get: Why are you doing this? Why don't you load the OBJ files again instead?
When using the DeSerializer class of the desktop version, it's a little different. Just like in the MTL, it only stores references to the names of the textures in the texture manager. And just like with any other loader, it will either create dummy textures for these names or use the textures with that name provided by the TextureManager.
As mentioned above, you should be able to deserialize the textures if you force a re-upload by calling the little method that i mentioned. Have you tried that? Did it work?

LoTan

Unfortunately, calling that method did not work, no.

What would ultimately help me (I think) is some way to load just an MTL and get the textures out.  This way, I could cache the serialized Object3Ds and then I will load the MTL files when the game loads to apply the textures.  Does that not sound reasonable?

Right now, the MTL load is tightly coupled with parsing OBJ files and I don't want to parse raw OBJ files at runtime.  I want that parsing done in advance and the texture parsing to be done during game load (at runtime).

EgonOlsen

Then just have a look at some MTL files. It's pretty easy to parse them yourself. IIRC, all i'm using is the texture name in there. It's a bit more complicated if there is none, because then i'm creating a texture for the diffuse color with some naming that i can't remember ATM. But that might not apply in your case...

LoTan

Ok cool, I think I'll try going down this path :)  Thanks.