提交 5dd809af 编写于 作者: D Don McCurdy

[gltf] Refactor loadMeshes.

Includes changes necessary to support the upcoming Draco extension, and more glTF primitive types.
上级 5c944f23
......@@ -1579,6 +1579,125 @@ THREE.GLTF2Loader = ( function () {
}
/**
* Specification: https://github.com/KhronosGroup/glTF/blob/master/specification/2.0/README.md#morph-targets
* @param {THREE.Mesh} mesh
* @param {GLTF.Mesh} meshDef
* @param {GLTF.Primitive} primitiveDef
* @param {Object} dependencies
*/
function addMorphTargets ( mesh, meshDef, primitiveDef, dependencies ) {
var geometry = mesh.geometry;
var material = mesh.material;
var targets = primitiveDef.targets;
var morphAttributes = geometry.morphAttributes;
morphAttributes.position = [];
morphAttributes.normal = [];
material.morphTargets = true;
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 ) {
// Three.js morph formula is
// position
// + weight0 * ( morphTarget0 - position )
// + weight1 * ( morphTarget1 - position )
// ...
// while the glTF one is
// position
// + weight0 * morphTarget0
// + weight1 * morphTarget1
// ...
// 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.
positionAttribute = dependencies.accessors[ target.POSITION ].clone();
var position = geometry.attributes.position;
for ( var j = 0, jl = positionAttribute.count; j < jl; j ++ ) {
positionAttribute.setXYZ(
j,
positionAttribute.getX( j ) + position.getX( j ),
positionAttribute.getY( j ) + position.getY( j ),
positionAttribute.getZ( j ) + position.getZ( j )
);
}
} else {
// Copying the original position not to affect the final position.
// See the formula above.
positionAttribute = geometry.attributes.position.clone();
}
if ( target.NORMAL !== undefined ) {
material.morphNormals = true;
// see target.POSITION's comment
normalAttribute = dependencies.accessors[ target.NORMAL ].clone();
var normal = geometry.attributes.normal;
for ( var j = 0, jl = normalAttribute.count; j < jl; j ++ ) {
normalAttribute.setXYZ(
j,
normalAttribute.getX( j ) + normal.getX( j ),
normalAttribute.getY( j ) + normal.getY( j ),
normalAttribute.getZ( j ) + normal.getZ( j )
);
}
} else {
normalAttribute = geometry.attributes.normal.clone();
}
if ( target.TANGENT !== undefined ) {
// TODO: implement
}
positionAttribute.name = attributeName;
normalAttribute.name = attributeName;
morphAttributes.position.push( positionAttribute );
morphAttributes.normal.push( normalAttribute );
}
mesh.updateMorphTargets();
if ( meshDef.weights !== undefined ) {
for ( var i = 0, il = meshDef.weights.length; i < il; i ++ ) {
mesh.morphTargetInfluences[ i ] = meshDef.weights[ i ];
}
}
}
// Deferred constructor for RawShaderMaterial types
function DeferredShaderMaterial( params ) {
......@@ -2116,102 +2235,126 @@ THREE.GLTF2Loader = ( function () {
};
GLTFParser.prototype.loadMeshes = function () {
GLTFParser.prototype.loadGeometries = function ( primitives ) {
var json = this.json;
var extensions = this.extensions;
return this._withDependencies( [
'accessors',
'materials'
'bufferViews',
] ).then( function ( dependencies ) {
return _each( json.meshes, function ( mesh ) {
return _each( primitives, function ( primitive ) {
var group = new THREE.Group();
if ( mesh.name !== undefined ) group.name = mesh.name;
var geometry = new THREE.BufferGeometry();
if ( mesh.extras ) group.userData = mesh.extras;
var attributes = primitive.attributes;
var primitives = mesh.primitives || [];
for ( var attributeId in attributes ) {
for ( var name in primitives ) {
var attributeEntry = attributes[ attributeId ];
var primitive = primitives[ name ];
if ( attributeEntry === undefined ) return;
var material = primitive.material !== undefined ? dependencies.materials[ primitive.material ] : createDefaultMaterial();
var bufferAttribute = dependencies.accessors[ attributeEntry ];
var geometry;
switch ( attributeId ) {
var meshNode;
case 'POSITION':
if ( primitive.mode === WEBGL_CONSTANTS.TRIANGLES || primitive.mode === undefined ) {
geometry.addAttribute( 'position', bufferAttribute );
break;
geometry = new THREE.BufferGeometry();
case 'NORMAL':
var attributes = primitive.attributes;
geometry.addAttribute( 'normal', bufferAttribute );
break;
for ( var attributeId in attributes ) {
case 'TEXCOORD_0':
case 'TEXCOORD0':
case 'TEXCOORD':
var attributeEntry = attributes[ attributeId ];
geometry.addAttribute( 'uv', bufferAttribute );
break;
if ( attributeEntry === undefined ) return;
case 'TEXCOORD_1':
var bufferAttribute = dependencies.accessors[ attributeEntry ];
geometry.addAttribute( 'uv2', bufferAttribute );
break;
switch ( attributeId ) {
case 'COLOR_0':
case 'COLOR0':
case 'COLOR':
case 'POSITION':
geometry.addAttribute( 'color', bufferAttribute );
break;
geometry.addAttribute( 'position', bufferAttribute );
break;
case 'WEIGHTS_0':
case 'WEIGHT': // WEIGHT semantic deprecated.
case 'NORMAL':
geometry.addAttribute( 'skinWeight', bufferAttribute );
break;
geometry.addAttribute( 'normal', bufferAttribute );
break;
case 'JOINTS_0':
case 'JOINT': // JOINT semantic deprecated.
case 'TEXCOORD_0':
case 'TEXCOORD0':
case 'TEXCOORD':
geometry.addAttribute( 'skinIndex', bufferAttribute );
break;
geometry.addAttribute( 'uv', bufferAttribute );
break;
}
case 'TEXCOORD_1':
}
geometry.addAttribute( 'uv2', bufferAttribute );
break;
if ( primitive.indices !== undefined ) {
case 'COLOR_0':
case 'COLOR0':
case 'COLOR':
geometry.setIndex( dependencies.accessors[ primitive.indices ] );
geometry.addAttribute( 'color', bufferAttribute );
break;
}
case 'WEIGHTS_0':
case 'WEIGHT': // WEIGHT semantic deprecated.
return geometry;
geometry.addAttribute( 'skinWeight', bufferAttribute );
break;
} );
case 'JOINTS_0':
case 'JOINT': // JOINT semantic deprecated.
} );
geometry.addAttribute( 'skinIndex', bufferAttribute );
break;
};
}
/**
* Specification: https://github.com/KhronosGroup/glTF/blob/master/specification/2.0/README.md#meshes
*/
GLTFParser.prototype.loadMeshes = function () {
}
var scope = this;
var json = this.json;
return this._withDependencies( [
if ( primitive.indices !== undefined ) {
'accessors',
'materials'
geometry.setIndex( dependencies.accessors[ primitive.indices ] );
] ).then( function ( dependencies ) {
}
return _each( json.meshes, function ( meshDef ) {
var group = new THREE.Group();
if ( meshDef.name !== undefined ) group.name = meshDef.name;
if ( meshDef.extras ) group.userData = meshDef.extras;
var primitives = meshDef.primitives || [];
return scope.loadGeometries( primitives ).then( function ( geometries ) {
for ( var name in primitives ) {
var primitive = primitives[ name ];
var geometry = geometries[ name ];
var material = primitive.material === undefined
? createDefaultMaterial()
: dependencies.materials[ primitive.material ];
if ( material.aoMap
&& geometry.attributes.uv2 === undefined
......@@ -2222,6 +2365,13 @@ THREE.GLTF2Loader = ( function () {
}
if ( geometry.attributes.color !== undefined ) {
material.vertexColors = THREE.VertexColors;
material.needsUpdate = true;
}
if ( geometry.attributes.normal === undefined ) {
if ( material.flatShading !== undefined ) {
......@@ -2237,185 +2387,39 @@ THREE.GLTF2Loader = ( function () {
}
meshNode = new THREE.Mesh( geometry, material );
meshNode.castShadow = true;
if ( primitive.targets !== undefined ) {
var targets = primitive.targets;
var morphAttributes = geometry.morphAttributes;
morphAttributes.position = [];
morphAttributes.normal = [];
material.morphTargets = true;
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 ) {
// Three.js morph formula is
// position
// + weight0 * ( morphTarget0 - position )
// + weight1 * ( morphTarget1 - position )
// ...
// while the glTF one is
// position
// + weight0 * morphTarget0
// + weight1 * morphTarget1
// ...
// 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.
positionAttribute = dependencies.accessors[ target.POSITION ].clone();
var position = geometry.attributes.position;
var mesh;
for ( var j = 0, jl = positionAttribute.count; j < jl; j ++ ) {
if ( primitive.mode === WEBGL_CONSTANTS.TRIANGLES || primitive.mode === undefined ) {
positionAttribute.setXYZ(
j,
positionAttribute.getX( j ) + position.getX( j ),
positionAttribute.getY( j ) + position.getY( j ),
positionAttribute.getZ( j ) + position.getZ( j )
);
}
} else if ( geometry.attributes.position ) {
// Copying the original position not to affect the final position.
// See the formula above.
positionAttribute = geometry.attributes.position.clone();
}
if ( target.NORMAL !== undefined ) {
material.morphNormals = true;
// see target.POSITION's comment
normalAttribute = dependencies.accessors[ target.NORMAL ].clone();
var normal = geometry.attributes.normal;
for ( var j = 0, jl = normalAttribute.count; j < jl; j ++ ) {
normalAttribute.setXYZ(
j,
normalAttribute.getX( j ) + normal.getX( j ),
normalAttribute.getY( j ) + normal.getY( j ),
normalAttribute.getZ( j ) + normal.getZ( j )
);
}
} else if ( geometry.attributes.normal ) {
normalAttribute = geometry.attributes.normal.clone();
}
// TODO: implement
if ( target.TANGENT !== undefined ) {
}
mesh = new THREE.Mesh( geometry, material );
if ( positionAttribute ) {
} else if ( primitive.mode === WEBGL_CONSTANTS.LINES ) {
positionAttribute.name = attributeName;
morphAttributes.position.push( positionAttribute );
mesh = new THREE.LineSegments( geometry, material );
}
if ( normalAttribute ) {
normalAttribute.name = attributeName;
morphAttributes.normal.push( normalAttribute );
}
}
meshNode.updateMorphTargets();
if ( mesh.weights !== undefined ) {
for ( var i = 0, il = mesh.weights.length; i < il; i ++ ) {
meshNode.morphTargetInfluences[ i ] = mesh.weights[ i ];
} else {
}
}
throw new Error( 'THREE.GLTF2Loader: Only TRIANGLE and LINE primitives are supported.' );
}
} else if ( primitive.mode === WEBGL_CONSTANTS.LINES ) {
geometry = new THREE.BufferGeometry();
var attributes = primitive.attributes;
for ( var attributeId in attributes ) {
var attributeEntry = attributes[ attributeId ];
if ( ! attributeEntry ) return;
var bufferAttribute = dependencies.accessors[ attributeEntry ];
mesh.name = group.name + '_' + name;
switch ( attributeId ) {
case 'POSITION':
geometry.addAttribute( 'position', bufferAttribute );
break;
case 'COLOR_0':
case 'COLOR0':
case 'COLOR':
geometry.addAttribute( 'color', bufferAttribute );
break;
}
}
if ( primitive.indices !== undefined ) {
if ( primitive.targets !== undefined ) {
geometry.setIndex( dependencies.accessors[ primitive.indices ] );
addMorphTargets( mesh, meshDef, primitive, dependencies );
}
meshNode = new THREE.LineSegments( geometry, material );
if ( primitive.extras ) mesh.userData = primitive.extras;
} else {
throw new Error( 'THREE.GLTF2Loader: Only triangular and line primitives are supported.' );
}
if ( geometry.attributes.color !== undefined ) {
material.vertexColors = THREE.VertexColors;
material.needsUpdate = true;
group.add( mesh );
}
meshNode.name = group.name + '_' + name;
return group;
if ( primitive.extras ) meshNode.userData = primitive.extras;
group.add( meshNode );
}
return group;
} );
} );
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册