Delayed Texture Loading request

Our current (proprietary 3D) system uses a delayed loading mechanism for all 3D stuff:

a) Application is notified that a texture load attempt was made.
b) A temporary placeholder texture is provided for use in the meantime.
c) Later, the application provides the actual file data to replace the placeholder.

However, we’re trying to transition to Xith instead. Unfortunately, all those cool 3D model loaders try to load the textures directly. How difficult would it be to implement the following stuff in TextureLoader…

  1. During initialization, I set the TextureLoader into a “delayed loading” mode. I provide a callback object (to be defined) and a placeholder texture which I’ve already made:

TextureLoader.enableDelayedLoading(NotifyCallbackObject NCO, Texture Placeholder)

  1. Whenever anything tries to load a texture via filename or URL, the following happens:

a) A copy of the texture placeholder is made.

placeholderCopy = Placeholder.copy()

a) My callback is notified of the texture load attempt, with the filename/URL and a reference to the texture placeholder copy which was made:

void NCO.TextureLoadAttempt(String filenameOrURL, Texture placeholderCopy)

b) The texture placeholder copy is returned to whatever made the request.

return placeholderCopy;

  1. Through various and sundry means (proprietary retrieval, runtime texture generation, etc), I obtain or generate the requested texture File at some point in the future.

  2. I then call the Textureloader to load the File I found over the current placeholder texture copy. Presumably, everywhere the placeholder texture is currently in use, it will be immediately replaced with the new texture data:

TextureLoader.loadFileIntoTexture(InputStream textureFileStream, Texture placeholderCopy)

The reason we need each texture load attempt to have its own unique copy of the texture placeholder is such that we can modify its texture to reflect the retrieval progress (a download indicator graphic directly on the texture, etc)

Note that the textureFileStream may not actually be coming from a File on disk… rather, it may be a GIF file that I’m holding only in a memory buffer, etc.

Naturally, all these functions are open to being modified. If it’s easier to provide the filenameOrURL on the loadFileIntoTexture() call or whatever, that’s cool. Just trying to give ya’ll an idea of what I’m thinking about.

Thoughts? It should be pretty straight-forward to do, just I’m completely unfamiliar with the inner workings of Xith. Something that would take me two weeks to figure out could probably be done in a couple hours by one of ya’ll. Unfortunately, we can’t proceed with our transition to Xith without something like this in place.

I would probably just implement this as a custom texture loader. There is absolutally no requirment to use the provided TextureLoader class at all (and some people don’t). All it does is read files and return BufferedImageS (and caches the images so the same file is not read twice). All you would do is create your custom texture loader which returned the placeholder BufferedImage (whose image would be overwritten at a later time).

Will.

Could I insert a custom texture loader such that it doesn’t interfere with existing systems (model loaders, etc) that aren’t aware of such?

Could this be done at runtime without having to create my own Xith build?

The model loaders arn’t really part of the Xith3D code. The ASE loader exists in the codebase but could just as easily be separated out. The others housed in the xith-tk project are not part of the core.

You would need to alter the model loader you wish to use so it uses your custom texture loader. This would be fairly trivial I would imagine (just a find/replace) if you make your model loader compatable.

Will.

Yeah, I was afraid of that. I’d really hate to have to provide custom versions of multiple model loaders just to support that feature. In addition, I don’t think it’s really the responsibility of a model loader to know how textures are being provided, only that it asks for a texture and receives one. Wouldn’t this be easier to solve in one location like the central TextureLoader, rather than seperately in each individual model loader?

The best option I think would be to define a texture loader interface which all the loaders use. That would give us the most flexability. It’s just a matter of defining a generic interface and convincing the loader authors to adopt it.

To me this seems like a specialised need of your program so I’m not sure if it really belongs in the TextureLoader class that everyone uses. I’d be interested in hearing the use-case argument as to why it’s a good idea in general though.

Will.

I don’t mind writing my own TextureLoader, with two caveats:

  1. I can insert my own TextureLoader during runtime, so I don’t have to create a custom build of Xith to use it

  2. Changing TextureLoaders doesn’t break existing model loaders.

I dunno why a delayed loading mechanism is such a strange idea. In today’s networked world, it’s silly to assume that every resource is immediately loadable every time, particularly when you don’t even know you’ll need that resource until it’s too late (ie, you don’t even know you need a texture until the model is already in the process of loading).

It’s also handy for a logging perspective, to be notified when a texture is being loaded by a third-party loader of which you have no control otherwise.

The outline I provided doesn’t break any existing compatibility for current users of TextureLoader. It simply provides an optional loading mechanism, if the application chooses to activate it.

But I think a runtime-pluggable TextureLoader mechanism would be the better long term solution, since I doubt I’ll be the last person with a different loading need than what others consider to be standard.

Here’s the basic code for the texture loading process in Xith-3DS:


URL realURL = TexMapProcessor.class.getClassLoader().getResource(filename);
image = javax.imageio.ImageIO.read(realURL);
image = javax.imageio.ImageIO.read(new File(filename));
Texture texture = new TextureLoader().loadTexture(image, textureFormat, context.generateMipMaps, Texture.BASE_LEVEL_LINEAR, Texture.BASE_LEVEL_LINEAR, Texture.CLAMP);

I think it’s inappropriate anyway for model loaders to be responsible for locating and loading textures. In my opinion, a model loader should call upon a central (runtime pluggable) TextureLoader system, and let the latter be concerned about how and where a texture comes from. A texture can come from many unique places, and the model loader above assumes that it comes immediately either from the JAR file or from an on-disk File, which is useless if the texture must be actively retrieved, is runtime generated, is sitting in a memory buffer, etc.

I know ya’ll didn’t write this loader, but I think it’s reflective of a situation that could be handled more cleanly and with a greater flexibility of design.

I won’t mind writing my own TextureLoader and fixing the existing model loaders I’ll use, to work with a pluggable centralized design.

With due respect, I did write the model loader. The 3DS format specifies that textures will be loaded from disk, so even loading from the classpath is probably wrong.

While I totally agree that these things could be more flexible your use case for a model loader is rather specialised.

Kev

I’d vote for that simply because it’s good programming practice.

In reality, though, texture loading is so thoroughly different from model loading at the application level (not, obviously, at the “creating a 3D model in a modelling app and saving it” level) that it does seem very sensible to de-couple the two e.g. at least have a factory pattern or similar.

But then again I’m only a casual Xith developer, so feel free to ignore me :).

My apologies Kevglass, I didn’t intend for my post to sound like disrespectful criticism. For the record, your loader worked flawlessly for my growing testbed application, and no doubt shaved a week or two off my development. I’m completely and totally appreciative of everybody’s involvement and effort in Xith.

I’m just presenting an angle that I suppose Xith wasn’t originally intended to handle :slight_smile:

So then, lets create a texture loader interface, and implementation of which is passed into the model loaders as an option to override the use of the default texture loader.

A model loder interface would be handy while we are at it, and some general guidelines written for people creating model loaders.

Will.

I’d suggest just a TextureLoader interface for now since thats a known quantity.

We’ve had discussions about Model loaders interface before, how to deal with animation has been a sticking point.

Kev

I’ve noticed that everything seems to reference TextureLoader.tf … perhaps a TextureLoader function so an application can replace the .tf with their own custom loader? That way, everything will still know that TextureLoader is the global access point, and the .tf is the custom insert.

We’d also need for the default TextureLoader not to disappear entirely. For instance, once my application retrieved/generated the file, I’d still need to use the original to actually create the texture. Naturally I could just save a reference to the original before I replaced it, as long as the original was still functional in that state.

I was thinking a bit more, and came up with a further simplification to my idea. I could register a callback object with TextureLoader, and then my callback object returns the texture that TextureLoader returns to the requesting system (model loader, etc). In this way, my application is the one who handles the placeholder texture, etc etc. It would boil down to the following:

  1. TextureLoader.enableCallback (CallbackObject myCO)
  2. Whenever something tries to load via filename or URL:

return myCO.TextureRequest(String filenameOrURL)

Far simplier than my original request. Of course, that assumes that model loaders, etc all try to load via filename or URL.

[quote]We’ve had discussions about Model loaders interface before, how to deal with animation has been a sticking point.
[/quote]
Yes, there is no way to add the features of every model loader out there into a common interface - but an interface might be handy for people just using the basics. I’m talking really simple stuff like “public TransformGroup getModel()” which all loaders can do. In the future, seperate interfaces could be added for various other features (animation, named nodes, transform group chaining, etc…).

Will.

Hi,

I would suggest something in between the interface and the callback approaches.

What I suggest is to add a static (or factory, or both) delegation class which will become an interface between texture loader implementation and user application. Custom texture loaders can be implemented as TextureLoaderProviders, so developer can set his own implementation of texture loader provider, while all the model loaders will use factory class to access texture loading mechanism.

The main benefit of this approach is elemination of indirect class loading (i.e. use of class.forName()) and complete isolation of the plug-in mechanisms from the model loader code.

The nearest example for us is javax.imageio and javax.imageio.spi, but for many people it looks overcomplicated, so they use just

image = javax.imageio.ImageIO.read(realURL);

while the API allows to do much more (for example, there is a way how to reduce memory used at application startup if load images directly into DirectBufferedImage instead of loading them in BufferedImage and painting on DirectBufferedImage).

Yuri