Skip to content

Conversation

@hybridherbst
Copy link
Contributor

@hybridherbst hybridherbst commented Oct 10, 2022

Related issue: #24108

Description

Unfortunately there hasn't been much movement on merging my PRs for KHR_animation_pointer (#24252, #24193 in preparation for #24108). In the meantime, people have starting using the extension and are bringing files to three.js that then fail with an exception.

This PR fixes the exception and makes sure people can at least load files that have KHR_animation_pointer marked as optional extension (according to glTF spec: when an extension is marked as optional implementations are fine to ignore it but should still display the rest of the file).

An open question would be whether to return "null" AnimationClips, thus potentially breaking external code that assumes that whenever an animation is loaded an AnimationClip is returned, or returning a clip with no tracks:

return new AnimationClip( animationName, undefined, [] );

I went with the latter here. There will be a log in the console that the extension isn't supported and people get empty tracks back instead of the current exception that looks like this:
image

My preference would definitely be KHR_animation_pointer support in three but in the meantime at least it shouldn't crash anymore for people.

This contribution is funded by Needle

@hybridherbst
Copy link
Contributor Author

@donmccurdy any opinion/objections here?

@donmccurdy
Copy link
Collaborator

@hybridherbst the core specification states —

When node isn’t defined, channel SHOULD be ignored.

I'd support a change doing that, but the current PR causes the entire animation (and all channels it contains) to be ignored. Could we ignore just the affected channel?

I'm also fine with merging your other PRs instead, though I think there is an issue to be addressed in #24193 (comment).

@hybridherbst hybridherbst force-pushed the prevent-load-exception-for-anim-pointer branch from ab6d6d3 to 1d98d60 Compare November 24, 2022 23:35
@hybridherbst
Copy link
Contributor Author

That return was totally unintended, sorry for the delay – uses continue now.

Here's me loading one of our animation pointer sample models:
image

Regarding testing this more, I don't think a file with mixed animations (some animation pointer, some not) currently exists, but that may not be a blocker for this PR.

@takahirox
Copy link
Collaborator

I think this change is good because target.node is optional in glTF core spec.

https://registry.khronos.org/glTF/specs/2.0/glTF-2.0.html#reference-animation-channel-target

@donmccurdy The spec describes that "When (target.node is) undefined, the animated object MAY be defined by an extension." If target.node is undefined and an extension defines it, should the extension be in extensionsRequired? Or not really because it is MAY not MUST?

@donmccurdy
Copy link
Collaborator

The spec describes that "When (target.node is) undefined, the animated object MAY be defined by an extension." If target.node is undefined and an extension defines it, should the extension be in extensionsRequired? Or not really because it is MAY not MUST?

I think the extension itself could decide one way or another here, e.g. to mandate extensionsRequired for itself. But from a core spec perspective, the file is valid whether or not an extension provides the target.

@takahirox
Copy link
Collaborator

takahirox commented Dec 15, 2022

An open question would be whether to return "null" AnimationClips, thus potentially breaking external code that assumes that whenever an animation is loaded an AnimationClip is returned, or returning a clip with no tracks:

I started to feel that it would be good to return a clip with tracks with empty target name.

If target.node is undefined, the target node is expected to be specified with a certain extension in general case.

Returning a clip with tracks with emptry target name will help the extension handlers like

// a certain extension plugin
async loadAnimation(animationIndex) {
  const animationDef = this.parser.json.animations[animationIndex];
  const extensionDef = animationDef.extensions[this.name];
  const clip = await this.parser.loadAnimation(animationIndex);
  for (const track of clip.tracks) {
    track.name = this._getTargetName(extensionDef) + track.name;
  }
  return clip;
}

Another option may be adding a new hook for animation target like getAnimationTarget() or getAnimationTargetName(). We may not want to add fine grained hooks because it may end up with having tons of fine grained hooks, but in this case it might be acceptable because the spec describes that the target node may be specified by a certain extension so not adding a new random hook point.

@takahirox takahirox changed the title GLTFLoader: Prevent load exception for assets that use KHR_animation_pointer GLTFLoader: Prevent load exception for assets that animation.target.node is undefined Dec 15, 2022
@hybridherbst
Copy link
Contributor Author

@takahirox the animation hooks that would be needed for KHR_animation_pointer are the ones in

I just didn't get to respond yet...

…_pointer extension

fix: don't return, instead just skip the animations that aren't supported

remove warning when node is undefined, just continue
@hybridherbst
Copy link
Contributor Author

Rebased on latest, I think this PR was already approved - would be great to get it merged :)

@hybridherbst hybridherbst force-pushed the prevent-load-exception-for-anim-pointer branch from 2060505 to a981cfa Compare March 28, 2023 07:59
@Mugen87 Mugen87 added this to the r151 milestone Mar 28, 2023
@Mugen87 Mugen87 merged commit bee8eaf into mrdoob:dev Mar 28, 2023
@Methuselah96 Methuselah96 mentioned this pull request Apr 25, 2023
37 tasks
@hybridherbst hybridherbst deleted the prevent-load-exception-for-anim-pointer branch May 23, 2023 21:39
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

Successfully merging this pull request may close these issues.

4 participants