SkinnedMesh class
class SkinnedMesh extends Mesh {
	bool useVertexTexture;
	num boneTextureWidth, boneTextureHeight;
	List bones;
	List boneMatrices;
	Matrix4 identityMatrix;
	DataTexture boneTexture;
	SkinnedMesh( geometry, material, {this.useVertexTexture: true} )
     : identityMatrix = new Matrix4.identity(),
       bones = [],
       boneMatrices = [],
       super(geometry, material) {
   var gbone, bone;
   var p, q, s;
   if ( geometry["bones"] != null ) {
     for( gbone in geometry["bones"]) {
       p = gbone.pos;
       q = gbone.rotq;
       s = gbone.scl;
       bone = addBone();
       bone.name = gbone.name;
       bone.position.set( p[0], p[1], p[2] );
       bone.quaternion.set( q[0], q[1], q[2], q[3] );
       bone.useQuaternion = true;
       if ( s != null ) {
         bone.scale.set( s[0], s[1], s[2] );
       } else {
         bone.scale.set( 1, 1, 1 );
       }
     }
     for ( var b = 0; b < this.bones.length; b ++ ) {
       gbone = geometry["bones"][ b ];
       bone = bones[ b ];
       if ( gbone.parent == -1 ) {
         this.add( bone );
       } else {
         bones[ gbone.parent ].add( bone );
       }
     }
     //
     var nBones = bones.length;
     if ( useVertexTexture ) {
       // layout (1 matrix = 4 pixels)
       //  RGBA RGBA RGBA RGBA (=> column1, column2, column3, column4)
       //  with  8x8  pixel texture max   16 bones  (8 * 8  / 4)
       //     16x16 pixel texture max   64 bones (16 * 16 / 4)
       //     32x32 pixel texture max  256 bones (32 * 32 / 4)
       //     64x64 pixel texture max 1024 bones (64 * 64 / 4)
       var size;
       if ( nBones > 256 ) {
         size = 64;
       } else if ( nBones > 64 ) {
         size = 32;
       } else if ( nBones > 16 ) {
         size = 16;
       } else {
         size = 8;
       }
       boneTextureWidth = size;
       boneTextureHeight = size;
       boneMatrices = new Float32List( boneTextureWidth * boneTextureHeight * 4 ); // 4 floats per RGBA pixel
       boneTexture = new DataTexture( boneMatrices, boneTextureWidth, boneTextureHeight, RGBAFormat, type: FloatType );
       boneTexture.minFilter = NearestFilter;
       boneTexture.magFilter = NearestFilter;
       boneTexture.generateMipmaps = false;
       boneTexture.flipY = false;
     } else {
       boneMatrices = new Float32List( 16 * nBones );
     }
     pose();
   }
	}
	addBone( {Bone bone} ) {
	  if ( bone == null ) {
	    bone = new Bone( this );
	  }
	  bones.add( bone );
	  return bone;
	}
	updateMatrixWorld({force: false}) {
	  if(matrixAutoUpdate) updateMatrix();
	  // update matrixWorld
	  if ( matrixWorldNeedsUpdate || force ) {
	    if ( parent != null) {
	      matrixWorld = parent.matrixWorld * matrix;
	    } else {
	      matrixWorld.setFrom( matrix );
	    }
	    matrixWorldNeedsUpdate = false;
	    force = true;
	  }
	  // update children
	  children.forEach((child) {
	    if ( child is Bone ) {
	      child.update( identityMatrix, false );
	    } else {
	      child.updateMatrixWorld( true );
	    }
	  });
	  // flatten bone matrices to array
	  var b, bl = this.bones.length,
	      ba = this.bones,
	      bm = this.boneMatrices;
	  for ( b = 0; b < bl; b ++ ) {
	    ba[ b ].skinMatrix.flattenToArrayOffset( bm, b * 16 );
	  }
	  if ( useVertexTexture ) {
	    boneTexture.needsUpdate = true;
	  }
	}
	/*
	 * Pose
	 */
	pose() {
	  updateMatrixWorld( force: true );
	  var bim, bone;
	  List<Matrix4> boneInverses = [];
	  for ( var b = 0; b < bones.length; b ++ ) {
	    bone = bones[ b ];
	    var inverseMatrix = bone.skinMatrix.clone();
	    inverseMatrix.invert();
	    boneInverses.add( inverseMatrix );
	    bone.skinMatrix.flattenToArrayOffset( boneMatrices, b * 16 );
	  }
	  // project vertices to local
	  if ( geometry["skinVerticesA"] == null ) {
	    geometry["skinVerticesA"] = [];
	    geometry["skinVerticesA"] = [];
	    var orgVertex, vertex;
	    for ( var i = 0; i < geometry.skinIndices.length; i ++ ) {
	      orgVertex = geometry.vertices[ i ];
	      var indexA = geometry.skinIndices[ i ].x;
	      var indexB = geometry.skinIndices[ i ].y;
	      vertex = new Vector3( orgVertex.x, orgVertex.y, orgVertex.z );
	      geometry["skinVerticesA"].add(vertex.applyProjection(boneInverses[indexA]));
	      vertex = new Vector3( orgVertex.x, orgVertex.y, orgVertex.z );
	      geometry["skinVerticesA"].add(vertex.applyProjection(boneInverses[indexB]));
	      // todo: add more influences
	      // normalize weights
	      if ( geometry.skinWeights[ i ].x + geometry.skinWeights[ i ].y != 1 ) {
	        var len = ( 1.0 - ( geometry.skinWeights[ i ].x + geometry.skinWeights[ i ].y ) ) * 0.5;
	        geometry.skinWeights[ i ].x += len;
	        geometry.skinWeights[ i ].y += len;
	      }
	    }
	  }
	}
}
Extends
Constructors
new SkinnedMesh(geometry, material, {bool useVertexTexture: true}) #
Creates a new Object instance.
Object instances have no meaningful state, and are only useful through their identity. An Object instance is equal to itself only.
docs inherited from Object 
SkinnedMesh( geometry, material, {this.useVertexTexture: true} )
    : identityMatrix = new Matrix4.identity(),
      bones = [],
      boneMatrices = [],
      super(geometry, material) {
  var gbone, bone;
  var p, q, s;
  if ( geometry["bones"] != null ) {
    for( gbone in geometry["bones"]) {
      p = gbone.pos;
      q = gbone.rotq;
      s = gbone.scl;
      bone = addBone();
      bone.name = gbone.name;
      bone.position.set( p[0], p[1], p[2] );
      bone.quaternion.set( q[0], q[1], q[2], q[3] );
      bone.useQuaternion = true;
      if ( s != null ) {
        bone.scale.set( s[0], s[1], s[2] );
      } else {
        bone.scale.set( 1, 1, 1 );
      }
    }
    for ( var b = 0; b < this.bones.length; b ++ ) {
      gbone = geometry["bones"][ b ];
      bone = bones[ b ];
      if ( gbone.parent == -1 ) {
        this.add( bone );
      } else {
        bones[ gbone.parent ].add( bone );
      }
    }
    //
    var nBones = bones.length;
    if ( useVertexTexture ) {
      // layout (1 matrix = 4 pixels)
      //  RGBA RGBA RGBA RGBA (=> column1, column2, column3, column4)
      //  with  8x8  pixel texture max   16 bones  (8 * 8  / 4)
      //     16x16 pixel texture max   64 bones (16 * 16 / 4)
      //     32x32 pixel texture max  256 bones (32 * 32 / 4)
      //     64x64 pixel texture max 1024 bones (64 * 64 / 4)
      var size;
      if ( nBones > 256 ) {
        size = 64;
      } else if ( nBones > 64 ) {
        size = 32;
      } else if ( nBones > 16 ) {
        size = 16;
      } else {
        size = 8;
      }
      boneTextureWidth = size;
      boneTextureHeight = size;
      boneMatrices = new Float32List( boneTextureWidth * boneTextureHeight * 4 ); // 4 floats per RGBA pixel
      boneTexture = new DataTexture( boneMatrices, boneTextureWidth, boneTextureHeight, RGBAFormat, type: FloatType );
      boneTexture.minFilter = NearestFilter;
      boneTexture.magFilter = NearestFilter;
      boneTexture.generateMipmaps = false;
      boneTexture.flipY = false;
    } else {
      boneMatrices = new Float32List( 16 * nBones );
    }
    pose();
  }
	}
Properties
DataTexture boneTexture #
DataTexture boneTexture
bool frustumCulled #
inherited from Object3D 
bool visible = false, castShadow = false, receiveShadow = false, frustumCulled = false
bool isDynamic #
inherited from Object3D 
bool get isDynamic => _dynamic;
set isDynamic(bool flag) => _dynamic = flag;
Matrix4 matrixRotationWorld #
inherited from Object3D 
Matrix4 matrix, matrixWorld, matrixRotationWorld
bool matrixWorldNeedsUpdate #
inherited from Object3D 
bool matrixAutoUpdate = false, matrixWorldNeedsUpdate = false
bool receiveShadow #
inherited from Object3D 
bool visible = false, castShadow = false, receiveShadow = false
Operators
Methods
void add(Object3D object) #
inherited from Object3D 
void add( Object3D object ) {
 if ( object == this ) {
   print( 'THREE.Object3D.add: An object can\'t be added as a child of itself.' );
   return;
 }
 if ( object.parent != null ) {
   object.parent.remove( object );
 }
 object.parent = this;
 children.add( object );
 // add to scene
 Object3D scene = this;
 while ( scene.parent != null ) {
   scene = scene.parent;
 }
 if ( scene is Scene ) {
   scene.addObject( object );
 }
}
dynamic addBone({Bone bone}) #
addBone( {Bone bone} ) {
	  if ( bone == null ) {
	    bone = new Bone( this );
	  }
	  bones.add( bone );
	  return bone;
	}
void applyMatrix(Matrix4 matrix) #
inherited from Object3D 
void applyMatrix ( Matrix4 matrix ) {
 this.matrix = matrix * this.matrix;
 this.scale = getScaleFromMatrix( this.matrix );
 Matrix4 mat = extractRotation(new Matrix4.identity(), this.matrix );
 this.rotation = calcEulerFromRotationMatrix( mat, this.eulerOrder );
 this.position = this.matrix.getTranslation();
}
Object3D getChildByName(String name, bool doRecurse) #
inherited from Object3D 
Object3D getChildByName( String name, bool doRecurse ) {
 int c;
 int cl = children.length;
 Object3D child, recurseResult;
 children.forEach((child){
   if ( child.name == name ) {
     return child;
   }
   if ( doRecurse ) {
     recurseResult = child.getChildByName( name, doRecurse );
     if ( recurseResult != null ) {
       return recurseResult;
     }
   }
 });
 return null;
}
num getMorphTargetIndexByName(name) #
inherited from Mesh 
num getMorphTargetIndexByName( name ) {
 if ( _morphTargetDictionary[ name ] != null ) {
   return _morphTargetDictionary[ name ];
 }
 print( "THREE.Mesh.getMorphTargetIndexByName: morph target $name does not exist. Returning 0." );
 return 0;
}
dynamic localToWorld(Vector3 vector) #
inherited from Object3D 
localToWorld(Vector3 vector) => vector.applyProjection(matrixWorld);
void lookAt(Vector3 vector) #
inherited from Object3D 
void lookAt( Vector3 vector ) {
 // TODO: Add hierarchy support.
 makeLookAt( matrix, vector, position, up );
 if ( rotationAutoUpdate ) {
   if(useQuaternion)
     quaternion.setFromRotationMatrix(matrix);
   else
     rotation = calcEulerFromRotationMatrix( matrix, eulerOrder );
 }
}
dynamic pose() #
pose() {
	  updateMatrixWorld( force: true );
	  var bim, bone;
	  List<Matrix4> boneInverses = [];
	  for ( var b = 0; b < bones.length; b ++ ) {
	    bone = bones[ b ];
	    var inverseMatrix = bone.skinMatrix.clone();
	    inverseMatrix.invert();
	    boneInverses.add( inverseMatrix );
	    bone.skinMatrix.flattenToArrayOffset( boneMatrices, b * 16 );
	  }
	  // project vertices to local
	  if ( geometry["skinVerticesA"] == null ) {
	    geometry["skinVerticesA"] = [];
	    geometry["skinVerticesA"] = [];
	    var orgVertex, vertex;
	    for ( var i = 0; i < geometry.skinIndices.length; i ++ ) {
	      orgVertex = geometry.vertices[ i ];
	      var indexA = geometry.skinIndices[ i ].x;
	      var indexB = geometry.skinIndices[ i ].y;
	      vertex = new Vector3( orgVertex.x, orgVertex.y, orgVertex.z );
	      geometry["skinVerticesA"].add(vertex.applyProjection(boneInverses[indexA]));
	      vertex = new Vector3( orgVertex.x, orgVertex.y, orgVertex.z );
	      geometry["skinVerticesA"].add(vertex.applyProjection(boneInverses[indexB]));
	      // todo: add more influences
	      // normalize weights
	      if ( geometry.skinWeights[ i ].x + geometry.skinWeights[ i ].y != 1 ) {
	        var len = ( 1.0 - ( geometry.skinWeights[ i ].x + geometry.skinWeights[ i ].y ) ) * 0.5;
	        geometry.skinWeights[ i ].x += len;
	        geometry.skinWeights[ i ].y += len;
	      }
	    }
	  }
	}
void remove(Object3D object) #
inherited from Object3D 
void remove( Object3D object ) {
 int index = children.indexOf( object );
 if ( index != - 1 ){
   object.parent = null;
   children.removeAt(index);
   // remove from scene
   Object3D scene = this;
   while ( scene.parent != null ) {
     scene = scene.parent;
   }
   if (scene is Scene ) {
     scene.removeObject( object );
   }
 }
}
void translate(num distance, Vector3 axis) #
inherited from Object3D 
void translate( num distance, Vector3 axis ) {
 matrix.rotate3( axis );
 axis.normalize();
 position.add( axis.scale( distance ) );
}
void translateX(num distance) #
inherited from Object3D 
void translateX( num distance ) => translate( distance, _vector.setValues( 1.0, 0.0, 0.0 ) );
void translateY(num distance) #
inherited from Object3D 
void translateY( num distance ) => translate( distance, _vector.setValues( 0.0, 1.0, 0.0 ) );
void translateZ(num distance) #
inherited from Object3D 
void translateZ( num distance ) => translate( distance, _vector.setValues( 0.0, 0.0, 1.0 ) );
void updateMatrix() #
inherited from Object3D 
void updateMatrix() {
 if ( useQuaternion ) {
   setRotationFromQuaternion( matrix, quaternion );
 } else {
   setRotationFromEuler( matrix, rotation, eulerOrder );
 }
 matrix.setTranslation( position );
 if ( scale.x != 1.0 || scale.y != 1.0 || scale.z != 1.0 ) {
   matrix.scale( scale );
   boundRadiusScale = Math.max( scale.x, Math.max( scale.y, scale.z ) );
 }
 matrixWorldNeedsUpdate = true;
}
dynamic updateMatrixWorld({force: false}) #
updateMatrixWorld({force: false}) {
	  if(matrixAutoUpdate) updateMatrix();
	  // update matrixWorld
	  if ( matrixWorldNeedsUpdate || force ) {
	    if ( parent != null) {
	      matrixWorld = parent.matrixWorld * matrix;
	    } else {
	      matrixWorld.setFrom( matrix );
	    }
	    matrixWorldNeedsUpdate = false;
	    force = true;
	  }
	  // update children
	  children.forEach((child) {
	    if ( child is Bone ) {
	      child.update( identityMatrix, false );
	    } else {
	      child.updateMatrixWorld( true );
	    }
	  });
	  // flatten bone matrices to array
	  var b, bl = this.bones.length,
	      ba = this.bones,
	      bm = this.boneMatrices;
	  for ( b = 0; b < bl; b ++ ) {
	    ba[ b ].skinMatrix.flattenToArrayOffset( bm, b * 16 );
	  }
	  if ( useVertexTexture ) {
	    boneTexture.needsUpdate = true;
	  }
	}