Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Migrating from 2.01 to 2.03 #78

Closed
Suicolen opened this issue Oct 20, 2022 · 6 comments
Closed

Migrating from 2.01 to 2.03 #78

Suicolen opened this issue Oct 20, 2022 · 6 comments

Comments

@Suicolen
Copy link

Suicolen commented Oct 20, 2022

A year ago i started working on a glTF converter tool (custom format -> glTF and vice versa) and it was fairly easy to do using this library, i never fully finished the project and decided to start working on it again now.
Last time i simply referred to jgltf-obj and built it based on that.
However now i decided to upgrade to the latest jgltf model (at least latest in mavenrepository) and seems like a lot has changed.
To be more specific, one specific class BufferStructureBuilder which i used heavily no longer exists, so code like this:

    public void exportJointsAndWeights() {
        List<ByteBuffer> buffers = writeJointsAndWeights(bones);
        int jointsAccessorIndex = bufferStructureBuilder.getNumAccessorModels();
        bufferStructureBuilder.createAccessorModel("jointsAccessor_" + jointsAccessorIndex,
                GltfConstants.GL_UNSIGNED_SHORT, "VEC4", buffers.get(0));
        meshPrimitive.addAttributes("JOINTS_0", jointsAccessorIndex);

        bufferStructureBuilder.createArrayElementBufferViewModel(
                "joints_bufferView");

        int weightsAccessorIndex = bufferStructureBuilder.getNumAccessorModels();
        bufferStructureBuilder.createAccessorModel("weightsAccessor_" + weightsAccessorIndex,
                GltfConstants.GL_FLOAT, "VEC4", buffers.get(1));
        meshPrimitive.addAttributes("WEIGHTS_0", weightsAccessorIndex);

        bufferStructureBuilder.createArrayElementBufferViewModel(
                "weights_bufferView");
    }

no longer compiles.

Edit: im aware that BufferStructureBuilder was only supposed to be used internally as i remember you mentioning it in an issue i made a while ago: #55 (comment)

So i believe my main question is what's the easiest way currently to construct a glTF file from a set of data (vertices, indices, normals, materials, joints/bones etc) as im aware that i probably have to rewrite most of my current code (probably best bet would be to just start from scratch).
I also don't mind using 'non-released modules' like the jgltf-model-builder (at least i didn't find a release of it in maven repo) or any other branches that are more up to date but just isn't released yet as i can just clone these easily rather easily and include in my project if it does make it any easier

@Suicolen
Copy link
Author

Suicolen commented Oct 21, 2022

After a bit of research i did find this:
https://github.com/javagl/JglTF/blob/master/jgltf-model-builder/src/main/java/de/javagl/jgltf/model/creation/MeshPrimitiveBuilder.java
However it seems like it's not entirely finished (there's a bunch of methods to set positions, indices, normals, texcoords but others like setting joints & weights are missing)

@javagl
Copy link
Owner

javagl commented Oct 22, 2022

As mentioned in the issue that you linked to: The BufferStructureBuilder was supposed to only be used internally. It did offer some methods that are required/convenient for building models, but it was never thought through well enough to provide a stable, reliable API. The jgltf-model-builder library was an attempt to create a more generic library for building models, but ... it also (still) carries that blanket disclaimer: Things might still change here.

(An aside: I know that this is a lame excuse for breaking changes. But JglTF is only one of ~50 spare time projects that I'm working on, and if somebody wants 'better engineered' software, then there is a simple solution for that: $$$)

However, the BufferStructureBuilder class still does exist, and I think that its API has not been changed significantly. I'd have to trace the log, but I think that it was only moved to a different package: https://github.com/javagl/JglTF/blob/523fcf0121b8b0aa03c404d9149cef8d95b67c5e/jgltf-model-builder/src/main/java/de/javagl/jgltf/model/creation/BufferStructureBuilder.java

So your original code snippet still compiles in the given form:

import java.nio.ByteBuffer;
import java.util.List;

import de.javagl.jgltf.impl.v2.MeshPrimitive;
import de.javagl.jgltf.model.GltfConstants;
import de.javagl.jgltf.model.creation.BufferStructureBuilder;

public class JgltfIssue78
{
    public void exportJointsAndWeights()
    {
        BufferStructureBuilder bufferStructureBuilder =
            new BufferStructureBuilder();
        MeshPrimitive meshPrimitive = new MeshPrimitive();

        List<ByteBuffer> buffers = null; // writeJointsAndWeights(bones);

        int jointsAccessorIndex = bufferStructureBuilder.getNumAccessorModels();
        bufferStructureBuilder.createAccessorModel(
            "jointsAccessor_" + jointsAccessorIndex,
            GltfConstants.GL_UNSIGNED_SHORT, "VEC4", buffers.get(0));
        meshPrimitive.addAttributes("JOINTS_0", jointsAccessorIndex);

        bufferStructureBuilder
            .createArrayElementBufferViewModel("joints_bufferView");

        int weightsAccessorIndex =
            bufferStructureBuilder.getNumAccessorModels();
        bufferStructureBuilder.createAccessorModel(
            "weightsAccessor_" + weightsAccessorIndex, GltfConstants.GL_FLOAT,
            "VEC4", buffers.get(1));
        meshPrimitive.addAttributes("WEIGHTS_0", weightsAccessorIndex);

        bufferStructureBuilder
            .createArrayElementBufferViewModel("weights_bufferView");
    }
}

(I hope that there are no breaking changes in the functionality, but ... you might give it a try...)


However it seems like it's not entirely finished (there's a bunch of methods to set positions, indices, normals, texcoords but others like setting joints & weights are missing)

The MeshPrimitiveBuilder is an attempt to create a class for building mesh primitives easily. There are convenience functions for "common" cases - for setting the positions, normals, and texture coordinates. These convenience functions should cover ~99% of the models that people might want to build. But internally, they always call a generic addAttribute method.

The addAttribute function can be used for other attributes, like joints and weights, or even custom attributes. In these cases, the caller is responsible for making sure that the data has the required form.

Here is an example that shows how a "complex, custom" attribute can be added:

import java.nio.ByteBuffer;
import java.nio.FloatBuffer;
import java.nio.IntBuffer;
import java.nio.ShortBuffer;

import de.javagl.jgltf.model.GltfConstants;
import de.javagl.jgltf.model.creation.AccessorModels;
import de.javagl.jgltf.model.creation.MeshPrimitiveBuilder;
import de.javagl.jgltf.model.impl.DefaultAccessorModel;
import de.javagl.jgltf.model.impl.DefaultMeshPrimitiveModel;
import de.javagl.jgltf.model.io.Buffers;

public class JgltfIssue78b
{
    public void builderExample()
    {
        int indices[] = null;
        float positions[] = null;
        float normals[] = null;
        short[] mySpecialAttributeData = null;

        // Add the attribute data for the commonly used attributes
        // using the convenience methods:
        MeshPrimitiveBuilder b = MeshPrimitiveBuilder.create();
        b.setIntIndicesAsShort(IntBuffer.wrap(indices));
        b.addPositions3D(FloatBuffer.wrap(positions));
        b.addNormals3D(FloatBuffer.wrap(normals));
        
        // Handle the 'mySpecialAttribute' data here. Just to have a complex
        // example, this is an attribute that contains normalized unsigned
        // short 2D vectors....
        int componentType = GltfConstants.GL_UNSIGNED_SHORT;
        String type = "VEC2";
        boolean normalized = true;
        ByteBuffer attributeData = Buffers.createByteBufferFrom(
            ShortBuffer.wrap(mySpecialAttributeData));
        DefaultAccessorModel mySpecialAttribute = AccessorModels.create(
            componentType, type, normalized, attributeData);
        b.addAttribute("_MY_SPECIAL_ATTRIBUTE", mySpecialAttribute);

        DefaultMeshPrimitiveModel meshPrimitiveModel = b.build();

    }
}

The idea here is, roughly speaking:

  • Creating a mesh primitive with positions, normals and texture coordinates should be easy - so there are convenience methods for that
  • Creating a mesh primitive with arbitrary (!) attributes should be possible

Or to put it that way: There certainly wouldn't be a point in adding methods like

  • addScalarFloatAttribute
  • addVec2FloatAttribute
  • ...
  • addMat2FloatAttribute
  • addScalarUnsignedByteAttribute
  • addVec2UnsignedByteAttribute
  • ...
  • addMat4UnsignedShortNormalizedAttribute.
  • ...

to the MeshPrimitiveBuilder class. That would literally be hundreds of functions, and totally unusable. But it should still be possible to add something like an "normalized unsigned short 4x4-matrix attribute", of somebody needs it. And this is possible now, by creating the accessor model with the AccessorModels class, and adding it using the addAttribute method.


However, you made a valid point: The JOINTS and WEIGHTS are part of the core specification. And there probably should be convenience methods like addJoints and addWeights, similar to the existing addPositions etc.

I'll consider adding these (and leave this issue open until this was addressed). But I always have to emphasize: All this is not yet 100% settled. Also see the message in this commit - I'd have to invest more time to arrive at a (more) stable solution locally, before publishing it.

But at least, this way, I may receive valuable feedback, like the point about joints and weights that you just brought up.

@Suicolen
Copy link
Author

Suicolen commented Oct 22, 2022

However, the BufferStructureBuilder class still does exist, and I think that its API has not been changed significantly. I'd have to trace the log, but I think that it was only moved to a different package:

Using jgltf-model dependency(https://mvnrepository.com/artifact/de.javagl/jgltf-model/2.0.3) like before but just version changed from 2.01 to 2.03 this still does not compile for me (creation package doesn't even exist) unless that's because it's not published yet

However, you made a valid point: The JOINTS and WEIGHTS are part of the core specification. And there probably should be convenience methods like addJoints and addWeights, similar to the existing addPositions etc.

Yeah this is exactly what i was trying to say, i agree that adding a bunch of convenience methods like addMat4UnsignedShortNormalizedAttribute is pointless but ones that people use fairly commonly like joints, weights should be there (at least i'd assume that exporting animated meshes is fairly common)

(An aside: I know that this is a lame excuse for breaking changes. But JglTF is only one of ~50 spare time projects that I'm working on, and if somebody wants 'better engineered' software, then there is a simple solution for that: $$$)

dam, i was not aware you were working on this many projects, anyway i actually wanted to make a new issue to ask about this but since you already sorta mentioned it, i'll ask it here.
Is there any way to support you/this project? some github repos have a 'sponsor' option for example.
I don't want to sponsor some new work in this repo (as the library is already at a good enough state for me and i've been able to use it easily in my project) but rather just support the work you've done so far as it has been very useful for me (I can't imagine how long writing my own java glTF library would've taken me)

@javagl
Copy link
Owner

javagl commented Oct 22, 2022

The jgltf-model-builder library should already be published, as of https://repo1.maven.org/maven2/de/javagl/jgltf-model-builder/2.0.3/ .

I guess the relevant point here is: This library is not part of jgltf-model. (It only depends on jgltf-model). The reason behind that is that some people might want to use jgltf-model, but may not need jgltf-model-builder.

Try adding the following dependency to your pom.xml:

    <dependency>
      <groupId>de.javagl</groupId>
      <artifactId>jgltf-model-builder</artifactId>
      <version>2.0.3</version>
    </dependency>

Is there any way to support you/this project? some github repos have a 'sponsor' option for example.

I haven't looked into the details of possible sponsorship, and somehow doubt that there's soooo much interest in what I'm doing: Nearly everything that I'm doing also exists as a *Script-npm library, often backed by large companies and many contributors (yes, sometimes sponsored). Setting up the infrastructure for sponsoring (including tax forms and whatnot) would probably not be worth the hassle. (I'm a freelancer, though. Wrapping a certain task into a fixed-price, fixed-time work contract could be much easier and goal-oriented...)

@Suicolen
Copy link
Author

Suicolen commented Oct 22, 2022

Thanks, everything works exactly as before now.

Nearly everything that I'm doing also exists as a *Script-npm library, often backed by large companies

at least for this project i don't think that's the case as this is the only library i found that allowed me to easily construct glTF models in java from a set of data(positions, vertices, tex coords, joints, weights etc) and reading a glTF was very easy as well

@javagl
Copy link
Owner

javagl commented Jul 16, 2024

This is obsolete with the release of 2.0.4. This might also include "breaking changes", but hopefully very few and very narrow ones. (Yeah, I know, proper "semantic vesioning" would be nice. But I'm juggling with time and priorities here...).

I started a change log at https://github.com/javagl/JglTF/blob/master/CHANGES.md - maybe that helps for future changes.

@javagl javagl closed this as completed Jul 16, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants