|
@@ -1139,103 +1139,114 @@ THREE.GLTFLoader = ( function () {
|
|
|
function addMorphTargets( mesh, meshDef, primitiveDef, accessors ) {
|
|
|
|
|
|
var geometry = mesh.geometry;
|
|
|
- var material = mesh.material;
|
|
|
-
|
|
|
var targets = primitiveDef.targets;
|
|
|
- var morphAttributes = geometry.morphAttributes;
|
|
|
|
|
|
- morphAttributes.position = [];
|
|
|
- morphAttributes.normal = [];
|
|
|
+ var hasMorphPosition = false;
|
|
|
+ var hasMorphNormal = false;
|
|
|
+
|
|
|
+ for ( var i = 0, il = targets.length; i < il; i ++ ) {
|
|
|
+
|
|
|
+ var target = targets[ i ];
|
|
|
+
|
|
|
+ if ( target.POSITION !== undefined ) hasMorphPosition = true;
|
|
|
+ if ( target.NORMAL !== undefined ) hasMorphNormal = true;
|
|
|
+
|
|
|
+ if ( hasMorphPosition && hasMorphNormal ) break;
|
|
|
|
|
|
- material.morphTargets = true;
|
|
|
+ }
|
|
|
+
|
|
|
+ if ( ! hasMorphPosition && ! hasMorphNormal ) return;
|
|
|
+
|
|
|
+ var morphPositions = [];
|
|
|
+ var morphNormals = [];
|
|
|
|
|
|
for ( var i = 0, il = targets.length; i < il; i ++ ) {
|
|
|
|
|
|
var target = targets[ i ];
|
|
|
var attributeName = 'morphTarget' + i;
|
|
|
|
|
|
- var positionAttribute, normalAttribute;
|
|
|
-
|
|
|
- if ( target.POSITION !== undefined ) {
|
|
|
+ if ( hasMorphPosition ) {
|
|
|
|
|
|
- // Three.js morph formula is
|
|
|
- // position
|
|
|
- // + weight0 * ( morphTarget0 - position )
|
|
|
- // + weight1 * ( morphTarget1 - position )
|
|
|
+ // Three.js morph position is absolute value. The formula is
|
|
|
+ // basePosition
|
|
|
+ // + weight0 * ( morphPosition0 - basePosition )
|
|
|
+ // + weight1 * ( morphPosition1 - basePosition )
|
|
|
// ...
|
|
|
- // while the glTF one is
|
|
|
- // position
|
|
|
- // + weight0 * morphTarget0
|
|
|
- // + weight1 * morphTarget1
|
|
|
+ // while the glTF one is relative
|
|
|
+ // basePosition
|
|
|
+ // + weight0 * glTFmorphPosition0
|
|
|
+ // + weight1 * glTFmorphPosition1
|
|
|
// ...
|
|
|
- // then adding position to morphTarget.
|
|
|
- // So morphTarget value will depend on mesh's position, then cloning attribute
|
|
|
- // for the case if attribute is shared among two or more meshes.
|
|
|
+ // then we need to convert from relative to absolute here.
|
|
|
|
|
|
- positionAttribute = cloneBufferAttribute( accessors[ target.POSITION ] );
|
|
|
- var position = geometry.attributes.position;
|
|
|
+ if ( target.POSITION !== undefined ) {
|
|
|
|
|
|
- for ( var j = 0, jl = positionAttribute.count; j < jl; j ++ ) {
|
|
|
+ // Cloning not to pollute original accessor
|
|
|
+ var positionAttribute = cloneBufferAttribute( accessors[ target.POSITION ] );
|
|
|
+ positionAttribute.name = attributeName;
|
|
|
|
|
|
- positionAttribute.setXYZ(
|
|
|
- j,
|
|
|
- positionAttribute.getX( j ) + position.getX( j ),
|
|
|
- positionAttribute.getY( j ) + position.getY( j ),
|
|
|
- positionAttribute.getZ( j ) + position.getZ( j )
|
|
|
- );
|
|
|
+ var position = geometry.attributes.position;
|
|
|
|
|
|
- }
|
|
|
+ for ( var j = 0, jl = positionAttribute.count; j < jl; j ++ ) {
|
|
|
|
|
|
- } else if ( geometry.attributes.position ) {
|
|
|
+ positionAttribute.setXYZ(
|
|
|
+ j,
|
|
|
+ positionAttribute.getX( j ) + position.getX( j ),
|
|
|
+ positionAttribute.getY( j ) + position.getY( j ),
|
|
|
+ positionAttribute.getZ( j ) + position.getZ( j )
|
|
|
+ );
|
|
|
|
|
|
- // Copying the original position not to affect the final position.
|
|
|
- // See the formula above.
|
|
|
- positionAttribute = cloneBufferAttribute( geometry.attributes.position );
|
|
|
+ }
|
|
|
|
|
|
- }
|
|
|
+ } else {
|
|
|
+
|
|
|
+ positionAttribute = geometry.attributes.position;
|
|
|
|
|
|
- if ( positionAttribute !== undefined ) {
|
|
|
+ }
|
|
|
|
|
|
- positionAttribute.name = attributeName;
|
|
|
- morphAttributes.position.push( positionAttribute );
|
|
|
+ morphPositions.push( positionAttribute );
|
|
|
|
|
|
}
|
|
|
|
|
|
- if ( target.NORMAL !== undefined ) {
|
|
|
-
|
|
|
- material.morphNormals = true;
|
|
|
+ if ( hasMorphNormal ) {
|
|
|
|
|
|
// see target.POSITION's comment
|
|
|
|
|
|
- normalAttribute = cloneBufferAttribute( accessors[ target.NORMAL ] );
|
|
|
- var normal = geometry.attributes.normal;
|
|
|
+ var normalAttribute;
|
|
|
|
|
|
- for ( var j = 0, jl = normalAttribute.count; j < jl; j ++ ) {
|
|
|
+ if ( target.NORMAL !== undefined ) {
|
|
|
|
|
|
- normalAttribute.setXYZ(
|
|
|
- j,
|
|
|
- normalAttribute.getX( j ) + normal.getX( j ),
|
|
|
- normalAttribute.getY( j ) + normal.getY( j ),
|
|
|
- normalAttribute.getZ( j ) + normal.getZ( j )
|
|
|
- );
|
|
|
+ var normalAttribute = cloneBufferAttribute( accessors[ target.NORMAL ] );
|
|
|
+ normalAttribute.name = attributeName;
|
|
|
|
|
|
- }
|
|
|
+ var normal = geometry.attributes.normal;
|
|
|
|
|
|
- } else if ( geometry.attributes.normal !== undefined ) {
|
|
|
+ for ( var j = 0, jl = normalAttribute.count; j < jl; j ++ ) {
|
|
|
|
|
|
- normalAttribute = cloneBufferAttribute( geometry.attributes.normal );
|
|
|
+ normalAttribute.setXYZ(
|
|
|
+ j,
|
|
|
+ normalAttribute.getX( j ) + normal.getX( j ),
|
|
|
+ normalAttribute.getY( j ) + normal.getY( j ),
|
|
|
+ normalAttribute.getZ( j ) + normal.getZ( j )
|
|
|
+ );
|
|
|
|
|
|
- }
|
|
|
+ }
|
|
|
|
|
|
- if ( normalAttribute !== undefined ) {
|
|
|
+ } else {
|
|
|
+
|
|
|
+ normalAttribute = geometry.attributes.normal;
|
|
|
+
|
|
|
+ }
|
|
|
|
|
|
- normalAttribute.name = attributeName;
|
|
|
- morphAttributes.normal.push( normalAttribute );
|
|
|
+ morphNormals.push( normalAttribute );
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
+ if ( hasMorphPosition ) geometry.morphAttributes.position = morphPositions;
|
|
|
+ if ( hasMorphNormal ) geometry.morphAttributes.normal = morphNormals;
|
|
|
+
|
|
|
mesh.updateMorphTargets();
|
|
|
|
|
|
if ( meshDef.weights !== undefined ) {
|
|
@@ -2322,6 +2333,10 @@ THREE.GLTFLoader = ( function () {
|
|
|
|
|
|
addMorphTargets( mesh, meshDef, primitive, dependencies.accessors );
|
|
|
|
|
|
+ material.morphTargets = true;
|
|
|
+
|
|
|
+ if ( mesh.geometry.morphAttributes.normal !== undefined ) material.morphNormals = true;
|
|
|
+
|
|
|
}
|
|
|
|
|
|
if ( meshDef.extras !== undefined ) mesh.userData = meshDef.extras;
|