three.js: THREE.PropertyBinding.parseTrackName() throws Error if bone name is Japanese

Description of the problem

THREE.PropertyBinding.parseTrackName() throws Error when I attempt to do Skeletal Animation with THREE.AnimationMixer if bone names are Japanese.

I think this problem is caused by that the regular expression in THREE.PropertyBinding.parseTrackName() doesn’t match Japanese characters.

var re = /^(([\w]+/)*)([\w-\d]+)?(.([\w]+)([([\w\d[].:- ]+)])?)?(.([\w.]+)([([\w\d[]. ]+)])?)$/; var matches = re.exec(trackName);

if( ! matches ) { throw new Error( "cannot parse trackName at all: " + trackName ); }

The root issue seems that \w doesn’t match Japanese character.

On console.

var re = /^(([\w]+/)*)([\w-\d]+)?(.([\w]+)([([\w\d[].:- ]+)])?)?(.([\w.]+)([([\w\d[]. ]+)])?)$/; -> undefined re.exec(‘.bone[Armature.DEF_cog].position’) -> [“.bone[Armature.DEF_cog].position”, “”, …] re.exec(‘.bone[あいうえお].position’) -> null

I know names shouldn’t be Japanese character but I’d be very pleased if it supports because generally MMD bone names are Japanese.

Three.js version
  • Dev
  • r77
Browser
  • All of them (maybe)
  • Chrome
  • Firefox
  • Internet Explorer
OS
  • All of them (maybe)
  • Windows
  • Linux
  • Android
  • IOS
Hardware Requirements (graphics card, VR Device, …)

About this issue

  • Original URL
  • State: closed
  • Created 8 years ago
  • Comments: 25 (13 by maintainers)

Most upvoted comments

@takahirox Sounds fantastic!

My focus was not sooo much on the added feature (although it’s really nice to have) but to achieve a straightforward implementation (guessing the segmentation approach will lead us there). Although the first regular expression is technically rather simple - just repetitive - it’s not all too easy to read and to actually notice it 😃.

Then there is an additional advantage, namely being able to process property paths with any number of segments. Consider animation code in a custom vertex shader, for instance…

Should PropertyBinding accept the path with any number of segments? I think we should first specify the path strings PropertyBinding can accepts. I expected what it should accept are only the variations written in the comment.

    // matches strings in the form of:
    //    nodeName.property
    //    nodeName.property[accessor]
    //    nodeName.material.property[accessor]
    //    uuid.property[accessor]
    //    uuid.objectName[objectIndex].propertyName[propertyIndex]
    //    parentName/nodeName.property
    //    parentName/parentName/nodeName.property[index]
    //    .bone[Armature.DEF_cog].position

If it accepts only the variations above, I prefer

var re = /^([^.[\]]+)?(?:\.([^.[\]]+)(?:\[([^[\]]+)\])?)?\.(?:([^.[\]]+)(?:\[([^[\]]+)\])?)$/;

If it accepts the path with any number of segments, regex should be like this

var re = /(?:^|\.)([^.[\]]+)(?:\[([^[\]]+)\])?/g;

I think the problem would be simpler if we first extract directoryName, like this.

var index = trackName.lastIndexOf( '/' );
var directoryName = trackName.slice( 0, Math.max( 0, index ) );
trackName = trackName.slice( index + 1 );

Now, we don’t need to care ‘/’ delimiter.

Then, the regex will be,

var re = /^([^.[\]]+)?(?:\.([^.[\]]+)(?:\[([^[\]]+)\])?)?\.(?:([^.[\]]+)(?:\[([^[\]]+)\])?)$/;

I think this’s good enough because it isn’t too complex.

FYI this is a great tool for testing a regex http://regexr.com/ since no sane human can understand a regex that has some form of complexity to it