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
GLTFLoader .createParser() #15508
GLTFLoader .createParser() #15508
Conversation
examples/js/loaders/GLTFLoader.js
Outdated
|
||
}, | ||
|
||
_load: function ( url, onLoad, onProgress, onError, getParser ) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
'_' suffix method name indicates private here. If we want real private method we can rewrite
function loadGLTF( gltfLoader, url, onLoad, onProgress, onError, getParser ) {
...
}
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
_load
is fine with me. 👍
Let's name the getParser
parameter parserOnly
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Renamed getParser
to parserOnly
, thanks.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This looks like a good approach, thanks!
</p> | ||
<p> | ||
Begin loading from url and call the callback function with the parser without parsing. | ||
Note that we don't guarantee that the parser's API will remain the same over time. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Suggested wording:
Fetch the asset without its dependencies, and return a parser for incrementally constructing asset content. Resources (e.g. binary or texture files) will be loaded only when needed. For example, when using the asset as a material library the parser can load a particular material and its textures while ignoring the others.
The parser API is primarily designed for internal use. It may require some understanding of the glTF format to use effectively, and may receive breaking changes more frequently than the default .load() method.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Updated, thanks.
examples/js/loaders/GLTFLoader.js
Outdated
|
||
}, | ||
|
||
_load: function ( url, onLoad, onProgress, onError, getParser ) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
_load
is fine with me. 👍
Let's name the getParser
parameter parserOnly
.
examples/js/loaders/GLTFLoader.js
Outdated
|
||
}, | ||
|
||
getParser: function ( url, onLoad, onProgress, onError ) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm a little conflicted on the getParser
name here. Other ideas:
- createParser
- initParser
- loadPartial
- loadIncremental
Since this method will make an initial request to get the JSON, I think a verb that implies more side effects than "get" might be better. 🤔
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I can understand. In the list createParser
sounds good to me.
This method itself initializes and creates parser
then IMO loadPartial/Incremental
doesn't really express the behavior of the method. For example, user may want to use this method just for editing JSON data before parsing, not for partial/incremental load.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Renamed getParser
to createParser
so far.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks! :)
I'm sure this has been discussed already (I'm having a de ja vu myself)... Why not splitting it into |
As input, the parser needs access to JSON and any extension objects. So to instantiate one, users must download the file themselves and replecate the ~100 lines here: three.js/examples/js/loaders/GLTFLoader.js Lines 141 to 243 in edada31
I guess we could move all of that, except the initial request, into the GLTFParser constructor, like: parser = new GLTFLoader.Parser( stringOrArrayBuffer, { ... } ); |
Yeah. That seems like a nicer API already. |
|
@takahirox I don't know if I see the difference — it seems like the same amount is exposed either way, except that the API for creating the parser is different? |
Here exposing instance vs exposing class. I think exposing instance is a bit better encapsulation than exposing class, for example users can't (easily) extend class if we don't expose class. |
|
Any reasons why exposing class sounds better than exposing instance to you? |
I'm not good at use English so let me talk in actual coding language, here's what I want: MyGLTFParser = class extends THREE.GLTFParser {
loadMaterial(materialIndex) {
return super.loadMaterial(materialIndex).then((material) => {
// do `material.userData.gltfIndex = {}`-like stuff
material.userData.gltfIndex.materials = materialIndex;
// or I can just refer VRM's metadata using `materialIndex` at this point, it's just an example!
});
}
}
// then replace GLTFLoader's parser using some sort of magic Doesn't the implementation sound straightforward?
Yes it's also the point, but I don't think exposing instances instead solves the issue. |
I think ppl who want the Parser may not need loading feature. Therefore, How about like this for ppl who want both loader and custom parser? const myParser = new MyGLTFParser();
loader.setParser( myParser ); |
My main concern is the parser is primarily designed for internal use so we don't guarantee the parser's API remain the same. I don't want users to extend the parser because it should be fragile, and I don't want such extended parsers to oppose the gltf parser's refactoring. So if we expose the parser class, I'd like to make clear which methods should be public and which ones should be hidden. I'm thinking of exposing only /cc @donmccurdy |
That would be great as a first step! |
I don't think |
I meant, either way exposing instance or class (or even without the change because we're already exposing instance via Even if we don't technically make the other methods private, I think better to add _ prefix like other modules do. With accessibility clarification, I have no reason opposing to exposing the parser class. It should be simpler. I'd like to divide the PR into two PRs.
I'll make soon. |
Sounds good! |
@donmccurdy @takahirox |
@donmccurdy how do you feel about this PR? |
Ah, sorry for pending. As I posted above, I was thinking of dividing this PR into two. (And exposing class rather than instance.) So, please don't merge this PR. Closing so far. |
One thing I've been thinking about exposing. I've been working on GLTFLoader plugin system in #11682 (Sorry for delaying. I took a vacation. I'm back and going to start working on that again.) And coming to think that, do we still really need to expose the parser even if we introduce plugin system? IIRC, the purposes of exposing are 1. custom operation 2. enable to partial/lazy load on demand. I'm wondering if plugin system would cover 1. I'm glad If anyone shares any "custom operation" use cases where plugin system can't handle. But yeah plugin system doesn't solve 2, we need another discussion of course tho. |
This PR adds
.getParser()
method toGLTFLoader
.Currently
GLTFLoader
providesparser
instance as an argument ofonLoad()
callback function of.load/parse()
to users who want to do some extra works in user side, for example handling their custom extensions.But it doesn't satisfy some use cases because
onLoad()
is called after parsing entire data. For exampleThen #14492 is proposed, the option giving
parser
instance without parsing to user viaonLoad()
callback.Here I'd like to suggest another API idea
.getParser()
, and removingparser
argument fromonLoad()
callback. I think separatingparser
fromload/parse()
's callback function is good because most of users don't needparser
.parser
is the core ofGLTFLoader
. Unnecessarily givingparser
to user is exposing the inside too much.And
parser
has some complexity and difficulty for users to use so it may be safer that only users who knows the complexity get theparser
with explicit getter call . The examples of the complexity are,parser
) to release resources..loadMesh()
forSkinnedMesh
. Such cloned objects can't be gotten byparser.getDependency()
.Examples:
Other relating threads: #15477