TimLee9024 / MCglTF

glTF library for Minecraft Modding
MIT License
7 stars 12 forks source link

Support for the KHR_materials_variants extension. #4

Open Waterpicker opened 2 years ago

Waterpicker commented 2 years ago

I have a situation with modded minecraft where usage of the official material variants extension for gltf is needed. It would be neat to see support for it. If there is issues with it needed to be supported by the jgltf itself, I previously made an issue with gltf about this. https://github.com/javagl/JglTF/issues/63

Extension's page: https://github.com/KhronosGroup/glTF/tree/main/extensions/2.0/Khronos/KHR_materials_variants

TimLee9024 commented 2 years ago

I don't really think I will implements this for MCglTF.

Because the purpose of KHR_materials_variants to me is just represent one of many ways to serialization and controlling over some of glTF model's behavior(e.g. node transformation, animation timer, dynamic material).

For those behavior, some other mods(like me) will choose to use extras for these application-specific scenario instead of extensions to have more flexibility to make use of custom properties and control model.

If you still want to use KHR_materials_variants, here is the partial code and some guideline you can use in your own custom renderer :

public class SomeTestRenderer implements IGltfModelReceiver {

    @Override
    public boolean isReceiveSharedModel(GltfModel gltfModel, List<GltfRenderData> gltfRenderDatas) {
        Gson gson = new Gson();

        VariantKeys variantKeys = gson.fromJson(gson.toJsonTree(gltfModel.getExtensions().get("KHR_materials_variants")), VariantKeys.class);

        RenderedGltfModel renderedModel = new RenderedGltfModel(gltfModel) {

            @Override
            protected void processMeshPrimitiveModel(NodeModel nodeModel, MeshModel meshModel, MeshPrimitiveModel meshPrimitiveModel, List<Runnable> vanillaRenderCommands, List<Runnable> shaderModRenderCommands) {
                VariantMapping variantMapping = gson.fromJson(gson.toJsonTree(meshPrimitiveModel.getExtensions().get("KHR_materials_variants")), VariantMapping.class);

                // Basically using variantKeys and variantMapping mix with code from parent method to prepare needed materials into OpenGL commands and dynamically select material in Runnable with your mod's client logic.
            }

            @Override
            protected void processMeshPrimitiveModel(NodeModel nodeModel, MeshModel meshModel, MeshPrimitiveModel meshPrimitiveModel, List<Runnable> skinningCommand, List<Runnable> vanillaRenderCommands, List<Runnable> shaderModRenderCommands) {
                // Same as above, but pass skinningCommand to next stage of MeshPrimitiveModel processing.
            }

        };

        renderedScene = renderedModel.renderedGltfScenes.get(0);
        List<AnimationModel> animationModels = renderedModel.gltfModel.getAnimationModels();
        animations = new ArrayList<List<InterpolatedChannel>>(animationModels.size());
        for(AnimationModel animationModel : animationModels) {
            animations.add(GltfAnimationCreator.createGltfAnimation(animationModel));
        }

        return false; // Remember to return false, as this model is now a custom render one and cannot be share memory and OpenGL allocation with other mods.
    }

}

Hope this help for you!

Waterpicker commented 2 years ago

I see!. So you just ensure the core model stuff is loaded properly, That's alright!