javagl / JglTF

Java libraries related to glTF
MIT License
204 stars 57 forks source link

Handling of duplicate URIs #115

Open javagl opened 1 week ago

javagl commented 1 week ago

Right now, it is not clear how duplicate URIs should be handled.

For example:

The latter is happening silently and certainly not desired.

Simply appending some _0 suffix to the file name might be a reasonable solution. But different mechanisms could be considered...

import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;

import de.javagl.jgltf.model.ImageModel;
import de.javagl.jgltf.model.creation.GltfModelBuilder;
import de.javagl.jgltf.model.creation.ImageModels;
import de.javagl.jgltf.model.impl.DefaultGltfModel;
import de.javagl.jgltf.model.impl.DefaultSceneModel;
import de.javagl.jgltf.model.io.GltfModelWriter;

public class GltfModelBuilderImageUriDeduplicationTest
{
    public static void main(String[] args) throws IOException
    {
        BufferedImage bufferedImage =
            new BufferedImage(8, 8, BufferedImage.TYPE_INT_ARGB);
        ImageModel imageModel0 = ImageModels.createFromBufferedImage(
            "image.png", "image/png", bufferedImage);
        ImageModel imageModel1 = ImageModels.createFromBufferedImage(
            "image.png", "image/png", bufferedImage);

        GltfModelBuilder gltfModelBuilder = GltfModelBuilder.create();
        gltfModelBuilder.addSceneModel(new DefaultSceneModel());
        gltfModelBuilder.addImageModel(imageModel0);
        gltfModelBuilder.addImageModel(imageModel1);

        DefaultGltfModel gltfModel = gltfModelBuilder.build();
        GltfModelWriter w = new GltfModelWriter();
        w.write(gltfModel, new File("./data/temp.gltf"));
    }

}

(Note: The same might apply to buffers - to be verified - but for images, it is much more apparent)

javagl commented 1 week ago

In many ways, I see glTF-Transform as ... "a source of inspiration" at least, but often as a reference for sensible ways of approaching things like this.

And I just tried it - i.e. creating a Document with two textures, and writing that out.

Now, the conceptual handling of images and textures in glTF-Transform is a bit special, and "structurally different" to a verbatim translation of glTF itself. There is no Image object, so to speak - the image is just "the data that is backing the texture". The user often will not explicitly assign a URI to a texture, even though this is possible:

texture0.setURI("test.png");
texture1.setURI("test.png");

Writing that out will also overwrite the "file" (resource) of the first texture with the data from the second.

Sooo... one could just say that this is the behavior that the user has to expect when doing something like this...

However: When no URIs are assigned explicitly, then they will be assigned automatically. And by default, the URIs are texture_1.png and texture_2.png.

(Now... glTF-Transform is doing many things right, but ... how can one start counting at 1? 😆 )


After seeing that, I followed my usual behavior of "being nasty", and tried

//texture0.setURI("test.png");
texture1.setURI("texture_1.png");

and this also causes the first texture to be called texture_1.png, and consequently, its data will be overwritten with the data from the second texture. That... is something that one might call a "bug"... but ... it's not worth arguing about that, I guess.


For JglTF, one overarching quesiton is whether any deduplication should happen in the model, or only at the time of writing. Both could have undesired implications, so there might not be a silver bullet.

However, when using null as the URI when creating the ImageModel, then it will also generate the URIs when writing out the data, namely as image0.png and image1.png. (And before you ask: When assigning image0.png as the URI for the second one, then it will rename this to image1.png and not overwrite the existing data...)

Maybe I'll just close this...