|
@@ -4,7 +4,6 @@
|
|
|
|
|
|
|
|
|
THREE.glTFLoader = function () {
|
|
|
-
|
|
|
this.meshesRequested = 0;
|
|
|
this.meshesLoaded = 0;
|
|
|
this.pendingMeshes = [];
|
|
@@ -15,7 +14,6 @@ THREE.glTFLoader = function () {
|
|
|
this.shadersLoaded = 0;
|
|
|
this.shaders = {};
|
|
|
THREE.Loader.call( this );
|
|
|
-
|
|
|
};
|
|
|
|
|
|
THREE.glTFLoader.prototype = Object.create( THREE.Loader.prototype );
|
|
@@ -26,45 +24,39 @@ THREE.glTFLoader.prototype.load = function( url, callback ) {
|
|
|
var theLoader = this;
|
|
|
// Utilities
|
|
|
|
|
|
- function RgbArraytoHex( colorArray ) {
|
|
|
-
|
|
|
- if ( ! colorArray ) return 0xFFFFFFFF;
|
|
|
- var r = Math.floor( colorArray[ 0 ] * 255 ),
|
|
|
- g = Math.floor( colorArray[ 1 ] * 255 ),
|
|
|
- b = Math.floor( colorArray[ 2 ] * 255 ),
|
|
|
+ function RgbArraytoHex(colorArray) {
|
|
|
+ if (!colorArray) return 0xFFFFFFFF;
|
|
|
+ var r = Math.floor(colorArray[0] * 255),
|
|
|
+ g = Math.floor(colorArray[1] * 255),
|
|
|
+ b = Math.floor(colorArray[2] * 255),
|
|
|
a = 255;
|
|
|
|
|
|
- var color = ( a << 24 ) + ( r << 16 ) + ( g << 8 ) + b;
|
|
|
+ var color = (a << 24) + (r << 16) + (g << 8) + b;
|
|
|
|
|
|
return color;
|
|
|
-
|
|
|
}
|
|
|
|
|
|
- function convertAxisAngleToQuaternion( rotations, count ) {
|
|
|
-
|
|
|
+ function convertAxisAngleToQuaternion(rotations, count)
|
|
|
+ {
|
|
|
var q = new THREE.Quaternion;
|
|
|
var axis = new THREE.Vector3;
|
|
|
var euler = new THREE.Vector3;
|
|
|
|
|
|
var i;
|
|
|
- for ( i = 0; i < count; i ++ ) {
|
|
|
-
|
|
|
- axis.set( rotations[ i * 4 ], rotations[ i * 4 + 1 ],
|
|
|
- rotations[ i * 4 + 2 ] ).normalize();
|
|
|
- var angle = rotations[ i * 4 + 3 ];
|
|
|
- q.setFromAxisAngle( axis, angle );
|
|
|
- rotations[ i * 4 ] = q.x;
|
|
|
- rotations[ i * 4 + 1 ] = q.y;
|
|
|
- rotations[ i * 4 + 2 ] = q.z;
|
|
|
- rotations[ i * 4 + 3 ] = q.w;
|
|
|
-
|
|
|
+ for (i = 0; i < count; i ++) {
|
|
|
+ axis.set(rotations[i * 4], rotations[i * 4 + 1],
|
|
|
+ rotations[i * 4 + 2]).normalize();
|
|
|
+ var angle = rotations[i * 4 + 3];
|
|
|
+ q.setFromAxisAngle(axis, angle);
|
|
|
+ rotations[i * 4] = q.x;
|
|
|
+ rotations[i * 4 + 1] = q.y;
|
|
|
+ rotations[i * 4 + 2] = q.z;
|
|
|
+ rotations[i * 4 + 3] = q.w;
|
|
|
}
|
|
|
-
|
|
|
}
|
|
|
|
|
|
- function componentsPerElementForGLType( glType ) {
|
|
|
-
|
|
|
- switch ( glType ) {
|
|
|
+ function componentsPerElementForGLType(glType) {
|
|
|
+ switch (glType) {
|
|
|
case WebGLRenderingContext.FLOAT :
|
|
|
case WebGLRenderingContext.UNSIGNED_BYTE :
|
|
|
case WebGLRenderingContext.UNSIGNED_SHORT :
|
|
@@ -80,21 +72,15 @@ THREE.glTFLoader.prototype.load = function( url, callback ) {
|
|
|
default:
|
|
|
return null;
|
|
|
}
|
|
|
-
|
|
|
}
|
|
|
|
|
|
- function LoadTexture( src ) {
|
|
|
-
|
|
|
- if ( ! src ) {
|
|
|
-
|
|
|
- return null;
|
|
|
-
|
|
|
- }
|
|
|
- return THREE.ImageUtils.loadTexture( src );
|
|
|
|
|
|
+ function LoadTexture(src) {
|
|
|
+ if (!src) { return null; }
|
|
|
+ return THREE.ImageUtils.loadTexture(src);
|
|
|
}
|
|
|
|
|
|
- // Geometry processing
|
|
|
+ // Geometry processing
|
|
|
|
|
|
var ClassicGeometry = function() {
|
|
|
|
|
@@ -109,361 +95,276 @@ THREE.glTFLoader.prototype.load = function( url, callback ) {
|
|
|
|
|
|
this.uvs = null;
|
|
|
this.indexArray = null;
|
|
|
-
|
|
|
};
|
|
|
|
|
|
ClassicGeometry.prototype.constructor = ClassicGeometry;
|
|
|
|
|
|
ClassicGeometry.prototype.buildBufferGeometry = function() {
|
|
|
-
|
|
|
- // Build indexed mesh
|
|
|
+ // Build indexed mesh
|
|
|
var geometry = this.geometry;
|
|
|
|
|
|
geometry.addAttribute( 'index', new THREE.BufferAttribute( this.indexArray, 1 ) );
|
|
|
geometry.addDrawCall( 0, this.indexArray.length );
|
|
|
|
|
|
geometry.computeBoundingSphere();
|
|
|
-
|
|
|
};
|
|
|
|
|
|
ClassicGeometry.prototype.checkFinished = function() {
|
|
|
-
|
|
|
- if ( this.indexArray && this.loadedAttributes === this.totalAttributes ) {
|
|
|
+ if (this.indexArray && this.loadedAttributes === this.totalAttributes) {
|
|
|
|
|
|
this.buildBufferGeometry();
|
|
|
|
|
|
this.finished = true;
|
|
|
|
|
|
- if ( this.onload ) {
|
|
|
-
|
|
|
+ if (this.onload) {
|
|
|
this.onload();
|
|
|
-
|
|
|
}
|
|
|
-
|
|
|
}
|
|
|
-
|
|
|
};
|
|
|
|
|
|
- // Delegate for processing index buffers
|
|
|
+ // Delegate for processing index buffers
|
|
|
var IndicesDelegate = function() {};
|
|
|
|
|
|
- IndicesDelegate.prototype.handleError = function( errorCode, info ) {
|
|
|
-
|
|
|
- // FIXME: report error
|
|
|
- console.log( "ERROR(IndicesDelegate):" + errorCode + ":" + info );
|
|
|
-
|
|
|
+ IndicesDelegate.prototype.handleError = function(errorCode, info) {
|
|
|
+ // FIXME: report error
|
|
|
+ console.log("ERROR(IndicesDelegate):" + errorCode + ":" + info);
|
|
|
};
|
|
|
|
|
|
- IndicesDelegate.prototype.convert = function( resource, ctx ) {
|
|
|
-
|
|
|
- return new Uint16Array( resource, 0, ctx.indices.count );
|
|
|
-
|
|
|
+ IndicesDelegate.prototype.convert = function(resource, ctx) {
|
|
|
+ return new Uint16Array(resource, 0, ctx.indices.count);
|
|
|
};
|
|
|
|
|
|
- IndicesDelegate.prototype.resourceAvailable = function( glResource, ctx ) {
|
|
|
-
|
|
|
+ IndicesDelegate.prototype.resourceAvailable = function(glResource, ctx) {
|
|
|
var geometry = ctx.geometry;
|
|
|
geometry.indexArray = glResource;
|
|
|
geometry.checkFinished();
|
|
|
return true;
|
|
|
-
|
|
|
};
|
|
|
|
|
|
var indicesDelegate = new IndicesDelegate();
|
|
|
|
|
|
- var IndicesContext = function( indices, geometry ) {
|
|
|
-
|
|
|
+ var IndicesContext = function(indices, geometry) {
|
|
|
this.indices = indices;
|
|
|
this.geometry = geometry;
|
|
|
-
|
|
|
};
|
|
|
|
|
|
- // Delegate for processing vertex attribute buffers
|
|
|
+ // Delegate for processing vertex attribute buffers
|
|
|
var VertexAttributeDelegate = function() {};
|
|
|
|
|
|
- VertexAttributeDelegate.prototype.handleError = function( errorCode, info ) {
|
|
|
-
|
|
|
- // FIXME: report error
|
|
|
- console.log( "ERROR(VertexAttributeDelegate):" + errorCode + ":" + info );
|
|
|
-
|
|
|
+ VertexAttributeDelegate.prototype.handleError = function(errorCode, info) {
|
|
|
+ // FIXME: report error
|
|
|
+ console.log("ERROR(VertexAttributeDelegate):" + errorCode + ":" + info);
|
|
|
};
|
|
|
|
|
|
- VertexAttributeDelegate.prototype.convert = function( resource, ctx ) {
|
|
|
-
|
|
|
+ VertexAttributeDelegate.prototype.convert = function(resource, ctx) {
|
|
|
return resource;
|
|
|
-
|
|
|
};
|
|
|
|
|
|
- VertexAttributeDelegate.prototype.arrayResourceAvailable = function( glResource, ctx ) {
|
|
|
|
|
|
+
|
|
|
+ VertexAttributeDelegate.prototype.arrayResourceAvailable = function(glResource, ctx) {
|
|
|
var geom = ctx.geometry;
|
|
|
var attribute = ctx.attribute;
|
|
|
var semantic = ctx.semantic;
|
|
|
var floatArray;
|
|
|
var i, l;
|
|
|
- //FIXME: Float32 is assumed here, but should be checked.
|
|
|
-
|
|
|
- if ( semantic == "POSITION" ) {
|
|
|
-
|
|
|
- // TODO: Should be easy to take strides into account here
|
|
|
- floatArray = new Float32Array( glResource, 0, attribute.count * componentsPerElementForGLType( attribute.type ) );
|
|
|
- for ( i = 0, l = floatArray.length; i < l; i += 3 ) {
|
|
|
-
|
|
|
- geom.geometry.vertices.push( new THREE.Vector3( floatArray[ i ], floatArray[ i + 1 ], floatArray[ i + 2 ] ) );
|
|
|
+ //FIXME: Float32 is assumed here, but should be checked.
|
|
|
|
|
|
+ if (semantic == "POSITION") {
|
|
|
+ // TODO: Should be easy to take strides into account here
|
|
|
+ floatArray = new Float32Array(glResource, 0, attribute.count * componentsPerElementForGLType(attribute.type));
|
|
|
+ for (i = 0, l = floatArray.length; i < l; i += 3) {
|
|
|
+ geom.geometry.vertices.push( new THREE.Vector3( floatArray[i], floatArray[i + 1], floatArray[i + 2] ) );
|
|
|
}
|
|
|
-
|
|
|
- } else if ( semantic == "NORMAL" ) {
|
|
|
-
|
|
|
+ } else if (semantic == "NORMAL") {
|
|
|
geom.geometry.normals = [];
|
|
|
- floatArray = new Float32Array( glResource, 0, attribute.count * componentsPerElementForGLType( attribute.type ) );
|
|
|
- for ( i = 0, l = floatArray.length; i < l; i += 3 ) {
|
|
|
-
|
|
|
- geom.geometry.normals.push( new THREE.Vector3( floatArray[ i ], floatArray[ i + 1 ], floatArray[ i + 2 ] ) );
|
|
|
-
|
|
|
+ floatArray = new Float32Array(glResource, 0, attribute.count * componentsPerElementForGLType(attribute.type));
|
|
|
+ for (i = 0, l = floatArray.length; i < l; i += 3) {
|
|
|
+ geom.geometry.normals.push( new THREE.Vector3( floatArray[i], floatArray[i + 1], floatArray[i + 2] ) );
|
|
|
}
|
|
|
-
|
|
|
- } else if ( ( semantic == "TEXCOORD_0" ) || ( semantic == "TEXCOORD" ) ) {
|
|
|
-
|
|
|
+ } else if ((semantic == "TEXCOORD_0") || (semantic == "TEXCOORD" )) {
|
|
|
geom.uvs = [];
|
|
|
- floatArray = new Float32Array( glResource, 0, attribute.count * componentsPerElementForGLType( attribute.type ) );
|
|
|
- for ( i = 0, l = floatArray.length; i < l; i += 2 ) {
|
|
|
-
|
|
|
- geom.uvs.push( new THREE.Vector2( floatArray[ i ], 1.0 - floatArray[ i + 1 ] ) );
|
|
|
-
|
|
|
- }
|
|
|
-
|
|
|
- }
|
|
|
- else if ( semantic == "WEIGHT" ) {
|
|
|
-
|
|
|
- nComponents = componentsPerElementForGLType( attribute.type );
|
|
|
- floatArray = new Float32Array( glResource, 0, attribute.count * nComponents );
|
|
|
- for ( i = 0, l = floatArray.length; i < l; i += 4 ) {
|
|
|
-
|
|
|
- geom.geometry.skinWeights.push( new THREE.Vector4( floatArray[ i ], floatArray[ i + 1 ], floatArray[ i + 2 ], floatArray[ i + 3 ] ) );
|
|
|
-
|
|
|
- }
|
|
|
-
|
|
|
- }
|
|
|
- else if ( semantic == "JOINT" ) {
|
|
|
-
|
|
|
- nComponents = componentsPerElementForGLType( attribute.type );
|
|
|
- floatArray = new Float32Array( glResource, 0, attribute.count * nComponents );
|
|
|
- for ( i = 0, l = floatArray.length; i < l; i += 4 ) {
|
|
|
-
|
|
|
- geom.geometry.skinIndices.push( new THREE.Vector4( floatArray[ i ], floatArray[ i + 1 ], floatArray[ i + 2 ], floatArray[ i + 3 ] ) );
|
|
|
-
|
|
|
+ floatArray = new Float32Array(glResource, 0, attribute.count * componentsPerElementForGLType(attribute.type));
|
|
|
+ for (i = 0, l = floatArray.length; i < l; i += 2) {
|
|
|
+ geom.uvs.push( new THREE.Vector2( floatArray[i], 1.0 - floatArray[i + 1] ) );
|
|
|
}
|
|
|
-
|
|
|
}
|
|
|
-
|
|
|
+ else if (semantic == "WEIGHT") {
|
|
|
+ nComponents = componentsPerElementForGLType(attribute.type);
|
|
|
+ floatArray = new Float32Array(glResource, 0, attribute.count * nComponents);
|
|
|
+ for (i = 0, l = floatArray.length; i < l; i += 4) {
|
|
|
+ geom.geometry.skinWeights.push( new THREE.Vector4( floatArray[i], floatArray[i + 1], floatArray[i + 2], floatArray[i + 3] ) );
|
|
|
+ }
|
|
|
+ }
|
|
|
+ else if (semantic == "JOINT") {
|
|
|
+ nComponents = componentsPerElementForGLType(attribute.type);
|
|
|
+ floatArray = new Float32Array(glResource, 0, attribute.count * nComponents);
|
|
|
+ for (i = 0, l = floatArray.length; i < l; i += 4) {
|
|
|
+ geom.geometry.skinIndices.push( new THREE.Vector4( floatArray[i], floatArray[i + 1], floatArray[i + 2], floatArray[i + 3] ) );
|
|
|
+ }
|
|
|
+ }
|
|
|
};
|
|
|
|
|
|
- VertexAttributeDelegate.prototype.bufferResourceAvailable = function( glResource, ctx ) {
|
|
|
-
|
|
|
+ VertexAttributeDelegate.prototype.bufferResourceAvailable = function(glResource, ctx) {
|
|
|
var geom = ctx.geometry;
|
|
|
var attribute = ctx.attribute;
|
|
|
var semantic = ctx.semantic;
|
|
|
var floatArray;
|
|
|
var i, l;
|
|
|
var nComponents;
|
|
|
- //FIXME: Float32 is assumed here, but should be checked.
|
|
|
-
|
|
|
- if ( semantic == "POSITION" ) {
|
|
|
+ //FIXME: Float32 is assumed here, but should be checked.
|
|
|
|
|
|
- // TODO: Should be easy to take strides into account here
|
|
|
- floatArray = new Float32Array( glResource, 0, attribute.count * componentsPerElementForGLType( attribute.type ) );
|
|
|
+ if (semantic == "POSITION") {
|
|
|
+ // TODO: Should be easy to take strides into account here
|
|
|
+ floatArray = new Float32Array(glResource, 0, attribute.count * componentsPerElementForGLType(attribute.type));
|
|
|
geom.geometry.addAttribute( 'position', new THREE.BufferAttribute( floatArray, 3 ) );
|
|
|
-
|
|
|
- } else if ( semantic == "NORMAL" ) {
|
|
|
-
|
|
|
- floatArray = new Float32Array( glResource, 0, attribute.count * componentsPerElementForGLType( attribute.type ) );
|
|
|
+ } else if (semantic == "NORMAL") {
|
|
|
+ floatArray = new Float32Array(glResource, 0, attribute.count * componentsPerElementForGLType(attribute.type));
|
|
|
geom.geometry.addAttribute( 'normal', new THREE.BufferAttribute( floatArray, 3 ) );
|
|
|
+ } else if ((semantic == "TEXCOORD_0") || (semantic == "TEXCOORD" )) {
|
|
|
|
|
|
- } else if ( ( semantic == "TEXCOORD_0" ) || ( semantic == "TEXCOORD" ) ) {
|
|
|
-
|
|
|
- nComponents = componentsPerElementForGLType( attribute.type );
|
|
|
- floatArray = new Float32Array( glResource, 0, attribute.count * nComponents );
|
|
|
- // N.B.: flip Y value... should we just set texture.flipY everywhere?
|
|
|
- for ( i = 0; i < floatArray.length / 2; i ++ ) {
|
|
|
-
|
|
|
- floatArray[ i * 2 + 1 ] = 1.0 - floatArray[ i * 2 + 1 ];
|
|
|
-
|
|
|
+ nComponents = componentsPerElementForGLType(attribute.type);
|
|
|
+ floatArray = new Float32Array(glResource, 0, attribute.count * nComponents);
|
|
|
+ // N.B.: flip Y value... should we just set texture.flipY everywhere?
|
|
|
+ for (i = 0; i < floatArray.length / 2; i ++) {
|
|
|
+ floatArray[i * 2 + 1] = 1.0 - floatArray[i * 2 + 1];
|
|
|
}
|
|
|
geom.geometry.addAttribute( 'uv', new THREE.BufferAttribute( floatArray, nComponents ) );
|
|
|
-
|
|
|
- }
|
|
|
- else if ( semantic == "WEIGHT" ) {
|
|
|
-
|
|
|
- nComponents = componentsPerElementForGLType( attribute.type );
|
|
|
- floatArray = new Float32Array( glResource, 0, attribute.count * nComponents );
|
|
|
- geom.geometry.addAttribute( 'skinWeight', new THREE.BufferAttribute( floatArray, nComponents ) );
|
|
|
-
|
|
|
- }
|
|
|
- else if ( semantic == "JOINT" ) {
|
|
|
-
|
|
|
- nComponents = componentsPerElementForGLType( attribute.type );
|
|
|
- floatArray = new Float32Array( glResource, 0, attribute.count * nComponents );
|
|
|
- geom.geometry.addAttribute( 'skinIndex', new THREE.BufferAttribute( floatArray, nComponents ) );
|
|
|
-
|
|
|
}
|
|
|
-
|
|
|
+ else if (semantic == "WEIGHT") {
|
|
|
+ nComponents = componentsPerElementForGLType(attribute.type);
|
|
|
+ floatArray = new Float32Array(glResource, 0, attribute.count * nComponents);
|
|
|
+ geom.geometry.addAttribute( 'skinWeight', new THREE.BufferAttribute( floatArray, nComponents ) );
|
|
|
+ }
|
|
|
+ else if (semantic == "JOINT") {
|
|
|
+ nComponents = componentsPerElementForGLType(attribute.type);
|
|
|
+ floatArray = new Float32Array(glResource, 0, attribute.count * nComponents);
|
|
|
+ geom.geometry.addAttribute( 'skinIndex', new THREE.BufferAttribute( floatArray, nComponents ) );
|
|
|
+ }
|
|
|
};
|
|
|
|
|
|
- VertexAttributeDelegate.prototype.resourceAvailable = function( glResource, ctx ) {
|
|
|
+ VertexAttributeDelegate.prototype.resourceAvailable = function(glResource, ctx) {
|
|
|
|
|
|
- this.bufferResourceAvailable( glResource, ctx );
|
|
|
+ this.bufferResourceAvailable(glResource, ctx);
|
|
|
|
|
|
var geom = ctx.geometry;
|
|
|
geom.loadedAttributes ++;
|
|
|
geom.checkFinished();
|
|
|
return true;
|
|
|
-
|
|
|
};
|
|
|
|
|
|
var vertexAttributeDelegate = new VertexAttributeDelegate();
|
|
|
|
|
|
- var VertexAttributeContext = function( attribute, semantic, geometry ) {
|
|
|
-
|
|
|
+ var VertexAttributeContext = function(attribute, semantic, geometry) {
|
|
|
this.attribute = attribute;
|
|
|
this.semantic = semantic;
|
|
|
this.geometry = geometry;
|
|
|
-
|
|
|
};
|
|
|
|
|
|
var Mesh = function() {
|
|
|
-
|
|
|
this.primitives = [];
|
|
|
this.materialsPending = [];
|
|
|
this.loadedGeometry = 0;
|
|
|
this.onCompleteCallbacks = [];
|
|
|
-
|
|
|
};
|
|
|
|
|
|
- Mesh.prototype.addPrimitive = function( geometry, material ) {
|
|
|
+ Mesh.prototype.addPrimitive = function(geometry, material) {
|
|
|
|
|
|
var self = this;
|
|
|
geometry.onload = function() {
|
|
|
-
|
|
|
self.loadedGeometry ++;
|
|
|
self.checkComplete();
|
|
|
-
|
|
|
};
|
|
|
|
|
|
- this.primitives.push( {
|
|
|
- geometry: geometry,
|
|
|
- material: material,
|
|
|
- mesh: null
|
|
|
- } );
|
|
|
-
|
|
|
+ this.primitives.push({
|
|
|
+ geometry: geometry,
|
|
|
+ material: material,
|
|
|
+ mesh: null
|
|
|
+ });
|
|
|
};
|
|
|
|
|
|
- Mesh.prototype.onComplete = function( callback ) {
|
|
|
-
|
|
|
- this.onCompleteCallbacks.push( callback );
|
|
|
+ Mesh.prototype.onComplete = function(callback) {
|
|
|
+ this.onCompleteCallbacks.push(callback);
|
|
|
this.checkComplete();
|
|
|
-
|
|
|
};
|
|
|
|
|
|
Mesh.prototype.checkComplete = function() {
|
|
|
-
|
|
|
var self = this;
|
|
|
- if ( this.onCompleteCallbacks.length && this.primitives.length == this.loadedGeometry ) {
|
|
|
-
|
|
|
- this.onCompleteCallbacks.forEach( function( callback ) {
|
|
|
-
|
|
|
- callback( self );
|
|
|
-
|
|
|
- } );
|
|
|
+ if (this.onCompleteCallbacks.length && this.primitives.length == this.loadedGeometry) {
|
|
|
+ this.onCompleteCallbacks.forEach(function(callback) {
|
|
|
+ callback(self);
|
|
|
+ });
|
|
|
this.onCompleteCallbacks = [];
|
|
|
-
|
|
|
}
|
|
|
-
|
|
|
};
|
|
|
|
|
|
- Mesh.prototype.attachToNode = function( threeNode ) {
|
|
|
-
|
|
|
- // Assumes that the geometry is complete
|
|
|
- this.primitives.forEach( function( primitive ) {
|
|
|
-
|
|
|
- /*if(!primitive.mesh) {
|
|
|
- primitive.mesh = new THREE.Mesh(primitive.geometry, primitive.material);
|
|
|
- }*/
|
|
|
+ Mesh.prototype.attachToNode = function(threeNode) {
|
|
|
+ // Assumes that the geometry is complete
|
|
|
+ this.primitives.forEach(function(primitive) {
|
|
|
+ /*if(!primitive.mesh) {
|
|
|
+ primitive.mesh = new THREE.Mesh(primitive.geometry, primitive.material);
|
|
|
+ }*/
|
|
|
var material = primitive.material;
|
|
|
- if ( ! ( material instanceof THREE.Material ) ) {
|
|
|
-
|
|
|
- material = theLoader.createShaderMaterial( material );
|
|
|
-
|
|
|
+ if (!(material instanceof THREE.Material)) {
|
|
|
+ material = theLoader.createShaderMaterial(material);
|
|
|
}
|
|
|
|
|
|
- var threeMesh = new THREE.Mesh( primitive.geometry.geometry, material );
|
|
|
+ var threeMesh = new THREE.Mesh(primitive.geometry.geometry, material);
|
|
|
threeMesh.castShadow = true;
|
|
|
- threeNode.add( threeMesh );
|
|
|
-
|
|
|
- } );
|
|
|
-
|
|
|
+ threeNode.add(threeMesh);
|
|
|
+ });
|
|
|
};
|
|
|
|
|
|
- // Delayed-loaded material
|
|
|
- var Material = function( params ) {
|
|
|
-
|
|
|
+ // Delayed-loaded material
|
|
|
+ var Material = function(params) {
|
|
|
this.params = params;
|
|
|
-
|
|
|
};
|
|
|
|
|
|
- // Delegate for processing animation parameter buffers
|
|
|
+ // Delegate for processing animation parameter buffers
|
|
|
var AnimationParameterDelegate = function() {};
|
|
|
|
|
|
- AnimationParameterDelegate.prototype.handleError = function( errorCode, info ) {
|
|
|
-
|
|
|
- // FIXME: report error
|
|
|
- console.log( "ERROR(AnimationParameterDelegate):" + errorCode + ":" + info );
|
|
|
-
|
|
|
+ AnimationParameterDelegate.prototype.handleError = function(errorCode, info) {
|
|
|
+ // FIXME: report error
|
|
|
+ console.log("ERROR(AnimationParameterDelegate):" + errorCode + ":" + info);
|
|
|
};
|
|
|
|
|
|
- AnimationParameterDelegate.prototype.convert = function( resource, ctx ) {
|
|
|
-
|
|
|
+ AnimationParameterDelegate.prototype.convert = function(resource, ctx) {
|
|
|
var parameter = ctx.parameter;
|
|
|
|
|
|
var glResource = null;
|
|
|
- switch ( parameter.type ) {
|
|
|
+ switch (parameter.type) {
|
|
|
case WebGLRenderingContext.FLOAT :
|
|
|
case WebGLRenderingContext.FLOAT_VEC2 :
|
|
|
case WebGLRenderingContext.FLOAT_VEC3 :
|
|
|
case WebGLRenderingContext.FLOAT_VEC4 :
|
|
|
- glResource = new Float32Array( resource, 0, parameter.count * componentsPerElementForGLType( parameter.type ) );
|
|
|
+ glResource = new Float32Array(resource, 0, parameter.count * componentsPerElementForGLType(parameter.type));
|
|
|
break;
|
|
|
default:
|
|
|
break;
|
|
|
}
|
|
|
|
|
|
return glResource;
|
|
|
-
|
|
|
};
|
|
|
|
|
|
- AnimationParameterDelegate.prototype.resourceAvailable = function( glResource, ctx ) {
|
|
|
-
|
|
|
+ AnimationParameterDelegate.prototype.resourceAvailable = function(glResource, ctx) {
|
|
|
var animation = ctx.animation;
|
|
|
var parameter = ctx.parameter;
|
|
|
parameter.data = glResource;
|
|
|
- animation.handleParameterLoaded( parameter );
|
|
|
+ animation.handleParameterLoaded(parameter);
|
|
|
return true;
|
|
|
-
|
|
|
};
|
|
|
|
|
|
var animationParameterDelegate = new AnimationParameterDelegate();
|
|
|
|
|
|
- var AnimationParameterContext = function( parameter, animation ) {
|
|
|
-
|
|
|
+ var AnimationParameterContext = function(parameter, animation) {
|
|
|
this.parameter = parameter;
|
|
|
this.animation = animation;
|
|
|
-
|
|
|
};
|
|
|
|
|
|
- // Animations
|
|
|
+ // Animations
|
|
|
var Animation = function() {
|
|
|
|
|
|
- // create Three.js keyframe here
|
|
|
+ // create Three.js keyframe here
|
|
|
this.totalParameters = 0;
|
|
|
this.loadedParameters = 0;
|
|
|
this.parameters = {};
|
|
@@ -474,1445 +375,1180 @@ THREE.glTFLoader.prototype.load = function( url, callback ) {
|
|
|
|
|
|
Animation.prototype.constructor = Animation;
|
|
|
|
|
|
- Animation.prototype.handleParameterLoaded = function( parameter ) {
|
|
|
-
|
|
|
- this.parameters[ parameter.name ] = parameter;
|
|
|
+ Animation.prototype.handleParameterLoaded = function(parameter) {
|
|
|
+ this.parameters[parameter.name] = parameter;
|
|
|
this.loadedParameters ++;
|
|
|
this.checkFinished();
|
|
|
-
|
|
|
};
|
|
|
|
|
|
Animation.prototype.checkFinished = function() {
|
|
|
-
|
|
|
- if ( this.loadedParameters === this.totalParameters ) {
|
|
|
-
|
|
|
- // Build animation
|
|
|
+ if (this.loadedParameters === this.totalParameters) {
|
|
|
+ // Build animation
|
|
|
this.finishedLoading = true;
|
|
|
|
|
|
- if ( this.onload ) {
|
|
|
-
|
|
|
+ if (this.onload) {
|
|
|
this.onload();
|
|
|
-
|
|
|
}
|
|
|
-
|
|
|
}
|
|
|
-
|
|
|
};
|
|
|
|
|
|
- // Delegate for processing inverse bind matrices buffer
|
|
|
+ // Delegate for processing inverse bind matrices buffer
|
|
|
var InverseBindMatricesDelegate = function() {};
|
|
|
|
|
|
- InverseBindMatricesDelegate.prototype.handleError = function( errorCode, info ) {
|
|
|
-
|
|
|
- // FIXME: report error
|
|
|
- console.log( "ERROR(InverseBindMatricesDelegate):" + errorCode + ":" + info );
|
|
|
-
|
|
|
+ InverseBindMatricesDelegate.prototype.handleError = function(errorCode, info) {
|
|
|
+ // FIXME: report error
|
|
|
+ console.log("ERROR(InverseBindMatricesDelegate):" + errorCode + ":" + info);
|
|
|
};
|
|
|
|
|
|
- InverseBindMatricesDelegate.prototype.convert = function( resource, ctx ) {
|
|
|
-
|
|
|
+ InverseBindMatricesDelegate.prototype.convert = function(resource, ctx) {
|
|
|
var parameter = ctx.parameter;
|
|
|
|
|
|
var glResource = null;
|
|
|
- switch ( parameter.type ) {
|
|
|
+ switch (parameter.type) {
|
|
|
case WebGLRenderingContext.FLOAT_MAT4 :
|
|
|
- glResource = new Float32Array( resource, 0, parameter.count * componentsPerElementForGLType( parameter.type ) );
|
|
|
+ glResource = new Float32Array(resource, 0, parameter.count * componentsPerElementForGLType(parameter.type));
|
|
|
break;
|
|
|
default:
|
|
|
break;
|
|
|
}
|
|
|
|
|
|
return glResource;
|
|
|
-
|
|
|
};
|
|
|
|
|
|
- InverseBindMatricesDelegate.prototype.resourceAvailable = function( glResource, ctx ) {
|
|
|
-
|
|
|
+ InverseBindMatricesDelegate.prototype.resourceAvailable = function(glResource, ctx) {
|
|
|
var skin = ctx.skin;
|
|
|
skin.inverseBindMatrices = glResource;
|
|
|
return true;
|
|
|
-
|
|
|
};
|
|
|
|
|
|
var inverseBindMatricesDelegate = new InverseBindMatricesDelegate();
|
|
|
|
|
|
- var InverseBindMatricesContext = function( param, skin ) {
|
|
|
-
|
|
|
+ var InverseBindMatricesContext = function(param, skin) {
|
|
|
this.parameter = param;
|
|
|
this.skin = skin;
|
|
|
-
|
|
|
};
|
|
|
|
|
|
- // Delegate for processing shaders from external files
|
|
|
+ // Delegate for processing shaders from external files
|
|
|
var ShaderDelegate = function() {};
|
|
|
|
|
|
- ShaderDelegate.prototype.handleError = function( errorCode, info ) {
|
|
|
-
|
|
|
- // FIXME: report error
|
|
|
- console.log( "ERROR(ShaderDelegate):" + errorCode + ":" + info );
|
|
|
-
|
|
|
+ ShaderDelegate.prototype.handleError = function(errorCode, info) {
|
|
|
+ // FIXME: report error
|
|
|
+ console.log("ERROR(ShaderDelegate):" + errorCode + ":" + info);
|
|
|
};
|
|
|
|
|
|
- ShaderDelegate.prototype.convert = function( resource, ctx ) {
|
|
|
-
|
|
|
+ ShaderDelegate.prototype.convert = function(resource, ctx) {
|
|
|
return resource;
|
|
|
-
|
|
|
};
|
|
|
|
|
|
- ShaderDelegate.prototype.resourceAvailable = function( data, ctx ) {
|
|
|
-
|
|
|
+ ShaderDelegate.prototype.resourceAvailable = function(data, ctx) {
|
|
|
theLoader.shadersLoaded ++;
|
|
|
- theLoader.shaders[ ctx.id ] = data;
|
|
|
+ theLoader.shaders[ctx.id] = data;
|
|
|
theLoader.checkComplete();
|
|
|
return true;
|
|
|
-
|
|
|
};
|
|
|
|
|
|
var shaderDelegate = new ShaderDelegate();
|
|
|
|
|
|
- var ShaderContext = function( id, path ) {
|
|
|
-
|
|
|
+ var ShaderContext = function(id, path) {
|
|
|
this.id = id;
|
|
|
this.path = path;
|
|
|
-
|
|
|
};
|
|
|
|
|
|
- // Resource management
|
|
|
-
|
|
|
- var ResourceEntry = function( entryID, object, description ) {
|
|
|
+ // Resource management
|
|
|
|
|
|
+ var ResourceEntry = function(entryID, object, description) {
|
|
|
this.entryID = entryID;
|
|
|
this.object = object;
|
|
|
this.description = description;
|
|
|
-
|
|
|
};
|
|
|
|
|
|
var Resources = function() {
|
|
|
-
|
|
|
this._entries = {};
|
|
|
-
|
|
|
};
|
|
|
|
|
|
- Resources.prototype.setEntry = function( entryID, object, description ) {
|
|
|
-
|
|
|
- if ( ! entryID ) {
|
|
|
-
|
|
|
- console.error( "No EntryID provided, cannot store", description );
|
|
|
+ Resources.prototype.setEntry = function(entryID, object, description) {
|
|
|
+ if (!entryID) {
|
|
|
+ console.error("No EntryID provided, cannot store", description);
|
|
|
return;
|
|
|
-
|
|
|
}
|
|
|
|
|
|
- if ( this._entries[ entryID ] ) {
|
|
|
-
|
|
|
- console.warn( "entry[" + entryID + "] is being overwritten" );
|
|
|
-
|
|
|
+ if (this._entries[entryID]) {
|
|
|
+ console.warn("entry[" + entryID + "] is being overwritten");
|
|
|
}
|
|
|
|
|
|
- this._entries[ entryID ] = new ResourceEntry( entryID, object, description );
|
|
|
-
|
|
|
+ this._entries[entryID] = new ResourceEntry(entryID, object, description );
|
|
|
};
|
|
|
|
|
|
- Resources.prototype.getEntry = function( entryID ) {
|
|
|
-
|
|
|
- return this._entries[ entryID ];
|
|
|
-
|
|
|
+ Resources.prototype.getEntry = function(entryID) {
|
|
|
+ return this._entries[entryID];
|
|
|
};
|
|
|
|
|
|
Resources.prototype.clearEntries = function() {
|
|
|
-
|
|
|
this._entries = {};
|
|
|
-
|
|
|
};
|
|
|
|
|
|
- LoadDelegate = function() {};
|
|
|
-
|
|
|
- LoadDelegate.prototype.loadCompleted = function( callback, obj ) {
|
|
|
-
|
|
|
- callback.call( Window, obj );
|
|
|
+ LoadDelegate = function() {
|
|
|
+ };
|
|
|
|
|
|
+ LoadDelegate.prototype.loadCompleted = function(callback, obj) {
|
|
|
+ callback.call(Window, obj);
|
|
|
};
|
|
|
|
|
|
- // Loader
|
|
|
-
|
|
|
- var ThreeGLTFLoader = Object.create( glTFParser, {
|
|
|
+ // Loader
|
|
|
|
|
|
- load: {
|
|
|
- enumerable: true,
|
|
|
- value: function( userInfo, options ) {
|
|
|
+ var ThreeGLTFLoader = Object.create(glTFParser, {
|
|
|
|
|
|
- this.resources = new Resources();
|
|
|
- this.cameras = [];
|
|
|
- this.lights = [];
|
|
|
- this.animations = [];
|
|
|
- this.joints = {};
|
|
|
- this.skeltons = {};
|
|
|
- THREE.GLTFLoaderUtils.init();
|
|
|
- glTFParser.load.call( this, userInfo, options );
|
|
|
+ load: {
|
|
|
+ enumerable: true,
|
|
|
+ value: function(userInfo, options) {
|
|
|
+ this.resources = new Resources();
|
|
|
+ this.cameras = [];
|
|
|
+ this.lights = [];
|
|
|
+ this.animations = [];
|
|
|
+ this.joints = {};
|
|
|
+ this.skeltons = {};
|
|
|
+ THREE.GLTFLoaderUtils.init();
|
|
|
+ glTFParser.load.call(this, userInfo, options);
|
|
|
+ }
|
|
|
+ },
|
|
|
+
|
|
|
+ cameras: {
|
|
|
+ enumerable: true,
|
|
|
+ writable: true,
|
|
|
+ value : []
|
|
|
+ },
|
|
|
+
|
|
|
+ lights: {
|
|
|
+ enumerable: true,
|
|
|
+ writable: true,
|
|
|
+ value : []
|
|
|
+ },
|
|
|
+
|
|
|
+ animations: {
|
|
|
+ enumerable: true,
|
|
|
+ writable: true,
|
|
|
+ value : []
|
|
|
+ },
|
|
|
+
|
|
|
+ // Implement WebGLTFLoader handlers
|
|
|
+
|
|
|
+ handleBuffer: {
|
|
|
+ value: function(entryID, description, userInfo) {
|
|
|
+ this.resources.setEntry(entryID, null, description);
|
|
|
+ description.type = "ArrayBuffer";
|
|
|
+ return true;
|
|
|
+ }
|
|
|
+ },
|
|
|
+
|
|
|
+ handleBufferView: {
|
|
|
+ value: function(entryID, description, userInfo) {
|
|
|
+ this.resources.setEntry(entryID, null, description);
|
|
|
+
|
|
|
+ var buffer = this.resources.getEntry(description.buffer);
|
|
|
+ description.type = "ArrayBufferView";
|
|
|
+
|
|
|
+ var bufferViewEntry = this.resources.getEntry(entryID);
|
|
|
+ bufferViewEntry.buffer = buffer;
|
|
|
+ return true;
|
|
|
+ }
|
|
|
+ },
|
|
|
+
|
|
|
+ handleShader: {
|
|
|
+ value: function(entryID, description, userInfo) {
|
|
|
+ this.resources.setEntry(entryID, null, description);
|
|
|
+ var shaderRequest = {
|
|
|
+ id : entryID,
|
|
|
+ path : description.path,
|
|
|
+ };
|
|
|
+
|
|
|
+ var shaderContext = new ShaderContext(entryID, description.path);
|
|
|
+
|
|
|
+ theLoader.shadersRequested ++;
|
|
|
+ THREE.GLTFLoaderUtils.getFile(shaderRequest, shaderDelegate, shaderContext);
|
|
|
+
|
|
|
+ return true;
|
|
|
+ }
|
|
|
+ },
|
|
|
+
|
|
|
+ handleProgram: {
|
|
|
+ value: function(entryID, description, userInfo) {
|
|
|
+ this.resources.setEntry(entryID, null, description);
|
|
|
+ return true;
|
|
|
+ }
|
|
|
+ },
|
|
|
+
|
|
|
+ handleTechnique: {
|
|
|
+ value: function(entryID, description, userInfo) {
|
|
|
+ this.resources.setEntry(entryID, null, description);
|
|
|
+ return true;
|
|
|
+ }
|
|
|
+ },
|
|
|
+
|
|
|
+ createShaderMaterial : {
|
|
|
+ value: function(material) {
|
|
|
+
|
|
|
+ var fragmentShader = theLoader.shaders[material.params.fragmentShader];
|
|
|
+ if (!fragmentShader) {
|
|
|
+ console.log("ERROR: Missing fragment shader definition:", material.params.fragmentShader);
|
|
|
+ return new THREE.MeshPhongMaterial;
|
|
|
+ }
|
|
|
|
|
|
- }
|
|
|
- },
|
|
|
+ var vertexShader = theLoader.shaders[material.params.vertexShader];
|
|
|
+ if (!fragmentShader) {
|
|
|
+ console.log("ERROR: Missing vertex shader definition:", material.params.vertexShader);
|
|
|
+ return new THREE.MeshPhongMaterial;
|
|
|
+ }
|
|
|
|
|
|
- cameras: {
|
|
|
- enumerable: true,
|
|
|
- writable: true,
|
|
|
- value : []
|
|
|
- },
|
|
|
+ var uniforms = {};
|
|
|
+ var shaderMaterial = new THREE.ShaderMaterial( {
|
|
|
|
|
|
- lights: {
|
|
|
- enumerable: true,
|
|
|
- writable: true,
|
|
|
- value : []
|
|
|
- },
|
|
|
+ fragmentShader: fragmentShader,
|
|
|
+ vertexShader: vertexShader,
|
|
|
+ uniforms: uniforms,
|
|
|
|
|
|
- animations: {
|
|
|
- enumerable: true,
|
|
|
- writable: true,
|
|
|
- value : []
|
|
|
- },
|
|
|
+ } );
|
|
|
|
|
|
- // Implement WebGLTFLoader handlers
|
|
|
+ return new THREE.MeshPhongMaterial(material.params);
|
|
|
+ }
|
|
|
+ },
|
|
|
|
|
|
- handleBuffer: {
|
|
|
- value: function( entryID, description, userInfo ) {
|
|
|
+ createShaderParams : {
|
|
|
+ value: function(materialId, values, params, instanceProgram) {
|
|
|
+ var program = this.resources.getEntry(instanceProgram.program);
|
|
|
|
|
|
- this.resources.setEntry( entryID, null, description );
|
|
|
- description.type = "ArrayBuffer";
|
|
|
- return true;
|
|
|
+ if (program) {
|
|
|
+ params.fragmentShader = program.description.fragmentShader;
|
|
|
+ params.vertexShader = program.description.vertexShader;
|
|
|
+ params.attributes = instanceProgram.attributes;
|
|
|
+ params.uniforms = instanceProgram.uniforms;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ },
|
|
|
+
|
|
|
+ threeJSMaterialType : {
|
|
|
+ value: function(materialId, technique, values, params) {
|
|
|
+
|
|
|
+ var materialType = THREE.MeshPhongMaterial;
|
|
|
+ var defaultPass = null;
|
|
|
+ if (technique && technique.description && technique.description.passes)
|
|
|
+ defaultPass = technique.description.passes.defaultPass;
|
|
|
+
|
|
|
+ if (defaultPass) {
|
|
|
+ if (defaultPass.details && defaultPass.details.commonProfile) {
|
|
|
+ var profile = technique.description.passes.defaultPass.details.commonProfile;
|
|
|
+ if (profile)
|
|
|
+ {
|
|
|
+ switch (profile.lightingModel)
|
|
|
+ {
|
|
|
+ case 'Blinn' :
|
|
|
+ case 'Phong' :
|
|
|
+ materialType = THREE.MeshPhongMaterial;
|
|
|
+ break;
|
|
|
+
|
|
|
+ case 'Lambert' :
|
|
|
+ materialType = THREE.MeshLambertMaterial;
|
|
|
+ break;
|
|
|
+
|
|
|
+ default :
|
|
|
+ materialType = THREE.MeshBasicMaterial;
|
|
|
+ break;
|
|
|
+ }
|
|
|
|
|
|
+ if (profile.extras && profile.extras.doubleSided)
|
|
|
+ {
|
|
|
+ params.side = THREE.DoubleSide;
|
|
|
+ }
|
|
|
}
|
|
|
- },
|
|
|
+ }
|
|
|
+ else if (defaultPass.instanceProgram) {
|
|
|
|
|
|
- handleBufferView: {
|
|
|
- value: function( entryID, description, userInfo ) {
|
|
|
+ var instanceProgram = defaultPass.instanceProgram;
|
|
|
|
|
|
- this.resources.setEntry( entryID, null, description );
|
|
|
+ this.createShaderParams(materialId, values, params, instanceProgram);
|
|
|
|
|
|
- var buffer = this.resources.getEntry( description.buffer );
|
|
|
- description.type = "ArrayBufferView";
|
|
|
+ var loadshaders = true;
|
|
|
+
|
|
|
+ if (loadshaders) {
|
|
|
+ materialType = Material;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
|
|
|
- var bufferViewEntry = this.resources.getEntry( entryID );
|
|
|
- bufferViewEntry.buffer = buffer;
|
|
|
- return true;
|
|
|
+ var texturePath = null;
|
|
|
+ var textureParams = null;
|
|
|
+ var diffuse = values.diffuse;
|
|
|
+ if (diffuse)
|
|
|
+ {
|
|
|
+ var texture = diffuse;
|
|
|
+ if (texture) {
|
|
|
+ var textureEntry = this.resources.getEntry(texture);
|
|
|
+ if (textureEntry) {
|
|
|
+ {
|
|
|
+ var imageEntry = this.resources.getEntry(textureEntry.description.source);
|
|
|
+ if (imageEntry) {
|
|
|
+ texturePath = imageEntry.description.path;
|
|
|
+ }
|
|
|
|
|
|
+ var samplerEntry = this.resources.getEntry(textureEntry.description.sampler);
|
|
|
+ if (samplerEntry) {
|
|
|
+ textureParams = samplerEntry.description;
|
|
|
+ }
|
|
|
+ }
|
|
|
}
|
|
|
- },
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ var texture = LoadTexture(texturePath);
|
|
|
+ if (texture && textureParams) {
|
|
|
|
|
|
- handleShader: {
|
|
|
- value: function( entryID, description, userInfo ) {
|
|
|
+ if (textureParams.wrapS == WebGLRenderingContext.REPEAT)
|
|
|
+ texture.wrapS = THREE.RepeatWrapping;
|
|
|
|
|
|
- this.resources.setEntry( entryID, null, description );
|
|
|
- var shaderRequest = {
|
|
|
- id : entryID,
|
|
|
- path : description.path,
|
|
|
- };
|
|
|
+ if (textureParams.wrapT == WebGLRenderingContext.REPEAT)
|
|
|
+ texture.wrapT = THREE.RepeatWrapping;
|
|
|
|
|
|
- var shaderContext = new ShaderContext( entryID, description.path );
|
|
|
+ if (textureParams.magFilter == WebGLRenderingContext.LINEAR)
|
|
|
+ texture.magFilter = THREE.LinearFilter;
|
|
|
|
|
|
- theLoader.shadersRequested ++;
|
|
|
- THREE.GLTFLoaderUtils.getFile( shaderRequest, shaderDelegate, shaderContext );
|
|
|
+// if (textureParams.minFilter == "LINEAR")
|
|
|
+// texture.minFilter = THREE.LinearFilter;
|
|
|
|
|
|
- return true;
|
|
|
+ params.map = texture;
|
|
|
+ }
|
|
|
+
|
|
|
+ var envMapPath = null;
|
|
|
+ var envMapParams = null;
|
|
|
+ var reflective = values.reflective;
|
|
|
+ if (reflective)
|
|
|
+ {
|
|
|
+ var texture = reflective;
|
|
|
+ if (texture) {
|
|
|
+ var textureEntry = this.resources.getEntry(texture);
|
|
|
+ if (textureEntry) {
|
|
|
+ {
|
|
|
+ var imageEntry = this.resources.getEntry(textureEntry.description.source);
|
|
|
+ if (imageEntry) {
|
|
|
+ envMapPath = imageEntry.description.path;
|
|
|
+ }
|
|
|
|
|
|
+ var samplerEntry = this.resources.getEntry(textureEntry.description.sampler);
|
|
|
+ if (samplerEntry) {
|
|
|
+ envMapParams = samplerEntry.description;
|
|
|
+ }
|
|
|
+ }
|
|
|
}
|
|
|
- },
|
|
|
+ }
|
|
|
+ }
|
|
|
|
|
|
- handleProgram: {
|
|
|
- value: function( entryID, description, userInfo ) {
|
|
|
+ var texture = LoadTexture(envMapPath);
|
|
|
+ if (texture && envMapParams) {
|
|
|
|
|
|
- this.resources.setEntry( entryID, null, description );
|
|
|
- return true;
|
|
|
+ if (envMapParams.wrapS == WebGLRenderingContext.REPEAT)
|
|
|
+ texture.wrapS = THREE.RepeatWrapping;
|
|
|
|
|
|
- }
|
|
|
- },
|
|
|
+ if (envMapParams.wrapT == WebGLRenderingContext.REPEAT)
|
|
|
+ texture.wrapT = THREE.RepeatWrapping;
|
|
|
|
|
|
- handleTechnique: {
|
|
|
- value: function( entryID, description, userInfo ) {
|
|
|
+ if (envMapParams.magFilter == WebGLRenderingContext.LINEAR)
|
|
|
+ texture.magFilter = THREE.LinearFilter;
|
|
|
|
|
|
- this.resources.setEntry( entryID, null, description );
|
|
|
- return true;
|
|
|
+// if (envMapParams.minFilter == WebGLRenderingContext.LINEAR)
|
|
|
+// texture.minFilter = THREE.LinearFilter;
|
|
|
|
|
|
- }
|
|
|
- },
|
|
|
+ params.envMap = texture;
|
|
|
+ }
|
|
|
|
|
|
- createShaderMaterial : {
|
|
|
- value: function( material ) {
|
|
|
+ var shininess = values.shininesss || values.shininess; // N.B.: typo in converter!
|
|
|
+ if (shininess)
|
|
|
+ {
|
|
|
+ shininess = shininess;
|
|
|
+ }
|
|
|
|
|
|
- var fragmentShader = theLoader.shaders[ material.params.fragmentShader ];
|
|
|
- if ( ! fragmentShader ) {
|
|
|
+ var diffuseColor = !texturePath ? diffuse : null;
|
|
|
+ var opacity = 1.0;
|
|
|
+ if (values.hasOwnProperty("transparency"))
|
|
|
+ {
|
|
|
+ var USE_A_ONE = true; // for now, hack because file format isn't telling us
|
|
|
+ opacity = USE_A_ONE ? values.transparency : (1.0 - values.transparency);
|
|
|
+ }
|
|
|
|
|
|
- console.log( "ERROR: Missing fragment shader definition:", material.params.fragmentShader );
|
|
|
- return new THREE.MeshPhongMaterial;
|
|
|
+ // if (diffuseColor) diffuseColor = [0, 1, 0];
|
|
|
|
|
|
- }
|
|
|
+ params.color = RgbArraytoHex(diffuseColor);
|
|
|
+ params.opacity = opacity;
|
|
|
+ params.transparent = opacity < 1.0;
|
|
|
+ // hack hack hack
|
|
|
+ if (texturePath && texturePath.toLowerCase().indexOf(".png") != -1)
|
|
|
+ params.transparent = true;
|
|
|
|
|
|
- var vertexShader = theLoader.shaders[ material.params.vertexShader ];
|
|
|
- if ( ! fragmentShader ) {
|
|
|
+ if (!(shininess === undefined))
|
|
|
+ {
|
|
|
+ params.shininess = shininess;
|
|
|
+ }
|
|
|
|
|
|
- console.log( "ERROR: Missing vertex shader definition:", material.params.vertexShader );
|
|
|
- return new THREE.MeshPhongMaterial;
|
|
|
+ if (!(values.emission === undefined))
|
|
|
+ {
|
|
|
+ params.emissive = RgbArraytoHex(values.emission);
|
|
|
+ }
|
|
|
|
|
|
- }
|
|
|
+ if (!(values.specular === undefined))
|
|
|
+ {
|
|
|
+ params.specular = RgbArraytoHex(values.specular);
|
|
|
+ }
|
|
|
|
|
|
- var uniforms = {};
|
|
|
- var shaderMaterial = new THREE.ShaderMaterial( {
|
|
|
+ return materialType;
|
|
|
|
|
|
- fragmentShader: fragmentShader,
|
|
|
- vertexShader: vertexShader,
|
|
|
- uniforms: uniforms,
|
|
|
+ }
|
|
|
+ },
|
|
|
|
|
|
- } );
|
|
|
+ handleMaterial: {
|
|
|
+ value: function(entryID, description, userInfo) {
|
|
|
+ //this should be rewritten using the meta datas that actually create the shader.
|
|
|
+ //here we will infer what needs to be pass to Three.js by looking inside the technique parameters.
|
|
|
+ var technique = this.resources.getEntry(description.instanceTechnique.technique);
|
|
|
+ var materialParams = {};
|
|
|
+ var values = description.instanceTechnique.values;
|
|
|
|
|
|
- return new THREE.MeshPhongMaterial( material.params );
|
|
|
+ var materialType = this.threeJSMaterialType(entryID, technique, values, materialParams);
|
|
|
|
|
|
- }
|
|
|
- },
|
|
|
+ var material = new materialType(materialParams);
|
|
|
|
|
|
- createShaderParams : {
|
|
|
- value: function( materialId, values, params, instanceProgram ) {
|
|
|
+ this.resources.setEntry(entryID, material, description);
|
|
|
|
|
|
- var program = this.resources.getEntry( instanceProgram.program );
|
|
|
+ return true;
|
|
|
+ }
|
|
|
+ },
|
|
|
|
|
|
- if ( program ) {
|
|
|
+ handleMesh: {
|
|
|
+ value: function(entryID, description, userInfo) {
|
|
|
+ var mesh = new Mesh();
|
|
|
+ this.resources.setEntry(entryID, mesh, description);
|
|
|
+ var primitivesDescription = description.primitives;
|
|
|
+ if (!primitivesDescription) {
|
|
|
+ //FIXME: not implemented in delegate
|
|
|
+ console.log("MISSING_PRIMITIVES for mesh:" + entryID);
|
|
|
+ return false;
|
|
|
+ }
|
|
|
|
|
|
- params.fragmentShader = program.description.fragmentShader;
|
|
|
- params.vertexShader = program.description.vertexShader;
|
|
|
- params.attributes = instanceProgram.attributes;
|
|
|
- params.uniforms = instanceProgram.uniforms;
|
|
|
+ for (var i = 0 ; i < primitivesDescription.length ; i ++) {
|
|
|
+ var primitiveDescription = primitivesDescription[i];
|
|
|
+
|
|
|
+ if (primitiveDescription.primitive === WebGLRenderingContext.TRIANGLES) {
|
|
|
+
|
|
|
+ var geometry = new ClassicGeometry();
|
|
|
+ var materialEntry = this.resources.getEntry(primitiveDescription.material);
|
|
|
+
|
|
|
+ mesh.addPrimitive(geometry, materialEntry.object);
|
|
|
+
|
|
|
+ var indices = this.resources.getEntry(primitiveDescription.indices);
|
|
|
+ var bufferEntry = this.resources.getEntry(indices.description.bufferView);
|
|
|
+ var indicesObject = {
|
|
|
+ bufferView : bufferEntry,
|
|
|
+ byteOffset : indices.description.byteOffset,
|
|
|
+ count : indices.description.count,
|
|
|
+ id : indices.entryID,
|
|
|
+ type : indices.description.type
|
|
|
+ };
|
|
|
+
|
|
|
+ var indicesContext = new IndicesContext(indicesObject, geometry);
|
|
|
+ var alreadyProcessedIndices = THREE.GLTFLoaderUtils.getBuffer(indicesObject, indicesDelegate, indicesContext);
|
|
|
+ /*if(alreadyProcessedIndices) {
|
|
|
+ indicesDelegate.resourceAvailable(alreadyProcessedIndices, indicesContext);
|
|
|
+ }*/
|
|
|
+
|
|
|
+ // Load Vertex Attributes
|
|
|
+ var allAttributes = Object.keys(primitiveDescription.attributes);
|
|
|
+ allAttributes.forEach( function(semantic) {
|
|
|
+ geometry.totalAttributes ++;
|
|
|
+
|
|
|
+ var attribute;
|
|
|
+ var attributeID = primitiveDescription.attributes[semantic];
|
|
|
+ var attributeEntry = this.resources.getEntry(attributeID);
|
|
|
+ if (!attributeEntry) {
|
|
|
+ //let's just use an anonymous object for the attribute
|
|
|
+ attribute = description.attributes[attributeID];
|
|
|
+ attribute.id = attributeID;
|
|
|
+ this.resources.setEntry(attributeID, attribute, attribute);
|
|
|
+
|
|
|
+ var bufferEntry = this.resources.getEntry(attribute.bufferView);
|
|
|
+ attributeEntry = this.resources.getEntry(attributeID);
|
|
|
|
|
|
+ } else {
|
|
|
+ attribute = attributeEntry.object;
|
|
|
+ attribute.id = attributeID;
|
|
|
+ var bufferEntry = this.resources.getEntry(attribute.bufferView);
|
|
|
}
|
|
|
|
|
|
+ var attributeObject = {
|
|
|
+ bufferView : bufferEntry,
|
|
|
+ byteOffset : attribute.byteOffset,
|
|
|
+ byteStride : attribute.byteStride,
|
|
|
+ count : attribute.count,
|
|
|
+ max : attribute.max,
|
|
|
+ min : attribute.min,
|
|
|
+ type : attribute.type,
|
|
|
+ id : attributeID
|
|
|
+ };
|
|
|
+
|
|
|
+ var attribContext = new VertexAttributeContext(attributeObject, semantic, geometry);
|
|
|
+
|
|
|
+ var alreadyProcessedAttribute = THREE.GLTFLoaderUtils.getBuffer(attributeObject, vertexAttributeDelegate, attribContext);
|
|
|
+ /*if(alreadyProcessedAttribute) {
|
|
|
+ vertexAttributeDelegate.resourceAvailable(alreadyProcessedAttribute, attribContext);
|
|
|
+ }*/
|
|
|
+ }, this);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ return true;
|
|
|
+ }
|
|
|
+ },
|
|
|
+
|
|
|
+ handleCamera: {
|
|
|
+ value: function(entryID, description, userInfo) {
|
|
|
+ var camera;
|
|
|
+ if (description.type == "perspective")
|
|
|
+ {
|
|
|
+ var znear = description.perspective.znear;
|
|
|
+ var zfar = description.perspective.zfar;
|
|
|
+ var yfov = description.perspective.yfov;
|
|
|
+ var xfov = description.perspective.xfov;
|
|
|
+ var aspect_ratio = description.perspective.aspect_ratio;
|
|
|
+
|
|
|
+ if (!aspect_ratio)
|
|
|
+ aspect_ratio = 1;
|
|
|
+
|
|
|
+ if (yfov === undefined)
|
|
|
+ {
|
|
|
+ if (xfov)
|
|
|
+ {
|
|
|
+ // According to COLLADA spec...
|
|
|
+ // aspect_ratio = xfov / yfov
|
|
|
+ yfov = xfov / aspect_ratio;
|
|
|
}
|
|
|
- },
|
|
|
|
|
|
- threeJSMaterialType : {
|
|
|
- value: function( materialId, technique, values, params ) {
|
|
|
+ }
|
|
|
+
|
|
|
+ if (yfov)
|
|
|
+ {
|
|
|
+ camera = new THREE.PerspectiveCamera(yfov, aspect_ratio, znear, zfar);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ camera = new THREE.OrthographicCamera( window.innerWidth / - 2, window.innerWidth / 2, window.innerHeight / 2, window.innerHeight / - 2, znear, zfar );
|
|
|
+ }
|
|
|
|
|
|
- var materialType = THREE.MeshPhongMaterial;
|
|
|
- var defaultPass = null;
|
|
|
- if ( technique && technique.description && technique.description.passes )
|
|
|
- defaultPass = technique.description.passes.defaultPass;
|
|
|
+ if (camera)
|
|
|
+ {
|
|
|
+ this.resources.setEntry(entryID, camera, description);
|
|
|
+ }
|
|
|
|
|
|
- if ( defaultPass ) {
|
|
|
+ return true;
|
|
|
+ }
|
|
|
+ },
|
|
|
|
|
|
- if ( defaultPass.details && defaultPass.details.commonProfile ) {
|
|
|
+ handleLight: {
|
|
|
+ value: function(entryID, description, userInfo) {
|
|
|
|
|
|
- var profile = technique.description.passes.defaultPass.details.commonProfile;
|
|
|
- if ( profile )
|
|
|
- {
|
|
|
+ var light = null;
|
|
|
+ var type = description.type;
|
|
|
+ if (type && description[type])
|
|
|
+ {
|
|
|
+ var lparams = description[type];
|
|
|
+ var color = RgbArraytoHex(lparams.color);
|
|
|
|
|
|
- switch ( profile.lightingModel )
|
|
|
- {
|
|
|
- case 'Blinn' :
|
|
|
- case 'Phong' :
|
|
|
- materialType = THREE.MeshPhongMaterial;
|
|
|
- break;
|
|
|
+ switch (type) {
|
|
|
+ case "directional" :
|
|
|
+ light = new THREE.DirectionalLight(color);
|
|
|
+ light.position.set(0, 0, 1);
|
|
|
+ break;
|
|
|
|
|
|
- case 'Lambert' :
|
|
|
- materialType = THREE.MeshLambertMaterial;
|
|
|
- break;
|
|
|
+ case "point" :
|
|
|
+ light = new THREE.PointLight(color);
|
|
|
+ break;
|
|
|
|
|
|
- default :
|
|
|
- materialType = THREE.MeshBasicMaterial;
|
|
|
- break;
|
|
|
- }
|
|
|
+ case "spot " :
|
|
|
+ light = new THREE.SpotLight(color);
|
|
|
+ light.position.set(0, 0, 1);
|
|
|
+ break;
|
|
|
|
|
|
- if ( profile.extras && profile.extras.doubleSided )
|
|
|
- {
|
|
|
+ case "ambient" :
|
|
|
+ light = new THREE.AmbientLight(color);
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ }
|
|
|
|
|
|
- params.side = THREE.DoubleSide;
|
|
|
+ if (light)
|
|
|
+ {
|
|
|
+ this.resources.setEntry(entryID, light, description);
|
|
|
+ }
|
|
|
|
|
|
- }
|
|
|
+ return true;
|
|
|
+ }
|
|
|
+ },
|
|
|
+
|
|
|
+ addPendingMesh: {
|
|
|
+ value: function(mesh, threeNode) {
|
|
|
+ theLoader.pendingMeshes.push({
|
|
|
+ mesh: mesh,
|
|
|
+ node: threeNode
|
|
|
+ });
|
|
|
+ }
|
|
|
+ },
|
|
|
+
|
|
|
+ handleNode: {
|
|
|
+ value: function(entryID, description, userInfo) {
|
|
|
+
|
|
|
+ var threeNode = null;
|
|
|
+ if (description.jointId) {
|
|
|
+ threeNode = new THREE.Bone();
|
|
|
+ threeNode.jointId = description.jointId;
|
|
|
+ this.joints[description.jointId] = entryID;
|
|
|
+ }
|
|
|
+ else {
|
|
|
+ threeNode = new THREE.Object3D();
|
|
|
+ }
|
|
|
+
|
|
|
+ threeNode.name = description.name;
|
|
|
+
|
|
|
+ this.resources.setEntry(entryID, threeNode, description);
|
|
|
+
|
|
|
+ var m = description.matrix;
|
|
|
+ if (m) {
|
|
|
+ threeNode.applyMatrix(new THREE.Matrix4().fromArray( m ));
|
|
|
+ threeNode.matrixAutoUpdate = false;
|
|
|
+ threeNode.matrixWorldNeedsUpdate = true;
|
|
|
+ }
|
|
|
+ else {
|
|
|
+ var t = description.translation;
|
|
|
+ var r = description.rotation;
|
|
|
+ var s = description.scale;
|
|
|
+
|
|
|
+ var position = t ? new THREE.Vector3(t[0], t[1], t[2]) :
|
|
|
+ new THREE.Vector3;
|
|
|
+ if (r) {
|
|
|
+ convertAxisAngleToQuaternion(r, 1);
|
|
|
+ }
|
|
|
+ var rotation = r ? new THREE.Quaternion(r[0], r[1], r[2], r[3]) :
|
|
|
+ new THREE.Quaternion;
|
|
|
+ var scale = s ? new THREE.Vector3(s[0], s[1], s[2]) :
|
|
|
+ new THREE.Vector3;
|
|
|
+
|
|
|
+ var matrix = new THREE.Matrix4;
|
|
|
+ matrix.compose(position, rotation, scale);
|
|
|
+ threeNode.matrixAutoUpdate = false;
|
|
|
+ threeNode.matrixWorldNeedsUpdate = true;
|
|
|
+ threeNode.applyMatrix(matrix);
|
|
|
+ }
|
|
|
|
|
|
- }
|
|
|
+ var self = this;
|
|
|
|
|
|
- }
|
|
|
- else if ( defaultPass.instanceProgram ) {
|
|
|
+ // Iterate through all node meshes and attach the appropriate objects
|
|
|
+ //FIXME: decision needs to be made between these 2 ways, probably meshes will be discarded.
|
|
|
+ var meshEntry;
|
|
|
+ if (description.mesh) {
|
|
|
+ meshEntry = this.resources.getEntry(description.mesh);
|
|
|
+ theLoader.meshesRequested ++;
|
|
|
+ meshEntry.object.onComplete(function(mesh) {
|
|
|
+ self.addPendingMesh(mesh, threeNode);
|
|
|
+ theLoader.meshesLoaded ++;
|
|
|
+ theLoader.checkComplete();
|
|
|
+ });
|
|
|
+ }
|
|
|
+
|
|
|
+ if (description.meshes) {
|
|
|
+ description.meshes.forEach( function(meshID) {
|
|
|
+ meshEntry = this.resources.getEntry(meshID);
|
|
|
+ theLoader.meshesRequested ++;
|
|
|
+ meshEntry.object.onComplete(function(mesh) {
|
|
|
+ self.addPendingMesh(mesh, threeNode);
|
|
|
+ theLoader.meshesLoaded ++;
|
|
|
+ theLoader.checkComplete();
|
|
|
+ });
|
|
|
+ }, this);
|
|
|
+ }
|
|
|
|
|
|
- var instanceProgram = defaultPass.instanceProgram;
|
|
|
+ if (description.instanceSkin) {
|
|
|
|
|
|
- this.createShaderParams( materialId, values, params, instanceProgram );
|
|
|
+ var skinEntry = this.resources.getEntry(description.instanceSkin.skin);
|
|
|
|
|
|
- var loadshaders = true;
|
|
|
+ if (skinEntry) {
|
|
|
|
|
|
- if ( loadshaders ) {
|
|
|
+ var skin = skinEntry.object;
|
|
|
+ description.instanceSkin.skin = skin;
|
|
|
+ threeNode.instanceSkin = description.instanceSkin;
|
|
|
|
|
|
- materialType = Material;
|
|
|
+ var sources = description.instanceSkin.sources;
|
|
|
+ skin.meshes = [];
|
|
|
+ sources.forEach( function(meshID) {
|
|
|
+ meshEntry = this.resources.getEntry(meshID);
|
|
|
+ theLoader.meshesRequested ++;
|
|
|
+ meshEntry.object.onComplete(function(mesh) {
|
|
|
|
|
|
- }
|
|
|
+ skin.meshes.push(mesh);
|
|
|
+ theLoader.meshesLoaded ++;
|
|
|
+ theLoader.checkComplete();
|
|
|
+ });
|
|
|
+ }, this);
|
|
|
|
|
|
- }
|
|
|
+ }
|
|
|
+ }
|
|
|
|
|
|
- }
|
|
|
+ if (description.camera) {
|
|
|
+ var cameraEntry = this.resources.getEntry(description.camera);
|
|
|
+ if (cameraEntry) {
|
|
|
+ threeNode.add(cameraEntry.object);
|
|
|
+ this.cameras.push(cameraEntry.object);
|
|
|
+ }
|
|
|
+ }
|
|
|
|
|
|
- var texturePath = null;
|
|
|
- var textureParams = null;
|
|
|
- var diffuse = values.diffuse;
|
|
|
- if ( diffuse )
|
|
|
- {
|
|
|
+ if (description.light) {
|
|
|
+ var lightEntry = this.resources.getEntry(description.light);
|
|
|
+ if (lightEntry) {
|
|
|
+ threeNode.add(lightEntry.object);
|
|
|
+ this.lights.push(lightEntry.object);
|
|
|
+ }
|
|
|
+ }
|
|
|
|
|
|
- var texture = diffuse;
|
|
|
- if ( texture ) {
|
|
|
+ return true;
|
|
|
+ }
|
|
|
+ },
|
|
|
+
|
|
|
+ buildNodeHirerachy: {
|
|
|
+ value: function(nodeEntryId, parentThreeNode) {
|
|
|
+ var nodeEntry = this.resources.getEntry(nodeEntryId);
|
|
|
+ var threeNode = nodeEntry.object;
|
|
|
+ parentThreeNode.add(threeNode);
|
|
|
+
|
|
|
+ var children = nodeEntry.description.children;
|
|
|
+ if (children) {
|
|
|
+ children.forEach( function(childID) {
|
|
|
+ this.buildNodeHirerachy(childID, threeNode);
|
|
|
+ }, this);
|
|
|
+ }
|
|
|
|
|
|
- var textureEntry = this.resources.getEntry( texture );
|
|
|
- if ( textureEntry ) {
|
|
|
+ return threeNode;
|
|
|
+ }
|
|
|
+ },
|
|
|
|
|
|
- {
|
|
|
+ buildSkin: {
|
|
|
+ value: function(node) {
|
|
|
|
|
|
- var imageEntry = this.resources.getEntry( textureEntry.description.source );
|
|
|
- if ( imageEntry ) {
|
|
|
+ var skin = node.instanceSkin.skin;
|
|
|
+ if (skin) {
|
|
|
+ node.instanceSkin.skeletons.forEach(function(skeleton) {
|
|
|
+ var nodeEntry = this.resources.getEntry(skeleton);
|
|
|
+ if (nodeEntry) {
|
|
|
|
|
|
- texturePath = imageEntry.description.path;
|
|
|
+ var rootSkeleton = nodeEntry.object;
|
|
|
|
|
|
- }
|
|
|
+ var dobones = true;
|
|
|
|
|
|
- var samplerEntry = this.resources.getEntry( textureEntry.description.sampler );
|
|
|
- if ( samplerEntry ) {
|
|
|
+ var i, len = skin.meshes.length;
|
|
|
+ for (i = 0; i < len; i ++) {
|
|
|
+ var mesh = skin.meshes[i];
|
|
|
+ var threeMesh = null;
|
|
|
+ mesh.primitives.forEach(function(primitive) {
|
|
|
|
|
|
- textureParams = samplerEntry.description;
|
|
|
+ var material = primitive.material;
|
|
|
+ if (!(material instanceof THREE.Material)) {
|
|
|
+ material = this.createShaderMaterial(material);
|
|
|
+ }
|
|
|
|
|
|
- }
|
|
|
+ threeMesh = new THREE.SkinnedMesh(primitive.geometry.geometry, material, false);
|
|
|
+ threeMesh.add(rootSkeleton);
|
|
|
|
|
|
+ var geometry = primitive.geometry.geometry;
|
|
|
+ var j;
|
|
|
+ if (geometry.vertices) {
|
|
|
+ for ( j = 0; j < geometry.vertices.length; j ++ ) {
|
|
|
+ geometry.vertices[j].applyMatrix4( skin.bindShapeMatrix );
|
|
|
+ }
|
|
|
+ }
|
|
|
+ else if (geometry.attributes.position) {
|
|
|
+ var a = geometry.attributes.position.array;
|
|
|
+ var v = new THREE.Vector3;
|
|
|
+ for ( j = 0; j < a.length / 3; j ++ ) {
|
|
|
+ v.set(a[j * 3], a[j * 3 + 1], a[j * 3 + 2]);
|
|
|
+ v.applyMatrix4( skin.bindShapeMatrix );
|
|
|
+ a[j * 3] = v.x;
|
|
|
+ a[j * 3 + 1] = v.y;
|
|
|
+ a[j * 3 + 2] = v.z;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ if (threeMesh && dobones) {
|
|
|
+
|
|
|
+ material.skinning = true;
|
|
|
+
|
|
|
+ threeMesh.boneInverses = [];
|
|
|
+ var jointsIds = skin.jointsIds;
|
|
|
+ var bones = [];
|
|
|
+ var boneInverses = [];
|
|
|
+ var i, len = jointsIds.length;
|
|
|
+ for (i = 0; i < len; i ++) {
|
|
|
+ var jointId = jointsIds[i];
|
|
|
+ var nodeForJoint = this.joints[jointId];
|
|
|
+ var joint = this.resources.getEntry(nodeForJoint).object;
|
|
|
+ if (joint) {
|
|
|
+
|
|
|
+ joint.skin = threeMesh;
|
|
|
+ bones.push(joint);
|
|
|
+
|
|
|
+ var m = skin.inverseBindMatrices;
|
|
|
+ var mat = new THREE.Matrix4().set(
|
|
|
+ m[i * 16 + 0], m[i * 16 + 4], m[i * 16 + 8], m[i * 16 + 12],
|
|
|
+ m[i * 16 + 1], m[i * 16 + 5], m[i * 16 + 9], m[i * 16 + 13],
|
|
|
+ m[i * 16 + 2], m[i * 16 + 6], m[i * 16 + 10], m[i * 16 + 14],
|
|
|
+ m[i * 16 + 3], m[i * 16 + 7], m[i * 16 + 11], m[i * 16 + 15]
|
|
|
+ );
|
|
|
+ boneInverses.push(mat);
|
|
|
+
|
|
|
+ } else {
|
|
|
+ console.log("WARNING: jointId:" + jointId + " cannot be found in skeleton:" + skeleton);
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
+ threeMesh.bind( new THREE.Skeleton( bones, boneInverses, false ), threeMesh.matrixWorld );
|
|
|
}
|
|
|
|
|
|
- }
|
|
|
+ if (threeMesh) {
|
|
|
+ threeMesh.castShadow = true;
|
|
|
+ node.add(threeMesh);
|
|
|
+ }
|
|
|
|
|
|
+ }, this);
|
|
|
}
|
|
|
|
|
|
- var texture = LoadTexture( texturePath );
|
|
|
- if ( texture && textureParams ) {
|
|
|
-
|
|
|
- if ( textureParams.wrapS == WebGLRenderingContext.REPEAT )
|
|
|
- texture.wrapS = THREE.RepeatWrapping;
|
|
|
-
|
|
|
- if ( textureParams.wrapT == WebGLRenderingContext.REPEAT )
|
|
|
- texture.wrapT = THREE.RepeatWrapping;
|
|
|
+ }
|
|
|
|
|
|
- if ( textureParams.magFilter == WebGLRenderingContext.LINEAR )
|
|
|
- texture.magFilter = THREE.LinearFilter;
|
|
|
|
|
|
- // if (textureParams.minFilter == "LINEAR")
|
|
|
- // texture.minFilter = THREE.LinearFilter;
|
|
|
+ }, this);
|
|
|
|
|
|
- params.map = texture;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ },
|
|
|
|
|
|
- }
|
|
|
+ buildSkins: {
|
|
|
+ value: function(node) {
|
|
|
|
|
|
- var envMapPath = null;
|
|
|
- var envMapParams = null;
|
|
|
- var reflective = values.reflective;
|
|
|
- if ( reflective )
|
|
|
- {
|
|
|
+ if (node.instanceSkin)
|
|
|
+ this.buildSkin(node);
|
|
|
|
|
|
- var texture = reflective;
|
|
|
- if ( texture ) {
|
|
|
+ var children = node.children;
|
|
|
+ if (children) {
|
|
|
+ children.forEach( function(child) {
|
|
|
+ this.buildSkins(child);
|
|
|
+ }, this);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ },
|
|
|
|
|
|
- var textureEntry = this.resources.getEntry( texture );
|
|
|
- if ( textureEntry ) {
|
|
|
+ createMeshAnimations : {
|
|
|
+ value : function(root) {
|
|
|
+ this.buildSkins(root);
|
|
|
+ }
|
|
|
+ },
|
|
|
|
|
|
- {
|
|
|
+ handleScene: {
|
|
|
+ value: function(entryID, description, userInfo) {
|
|
|
|
|
|
- var imageEntry = this.resources.getEntry( textureEntry.description.source );
|
|
|
- if ( imageEntry ) {
|
|
|
+ if (!description.nodes) {
|
|
|
+ console.log("ERROR: invalid file required nodes property is missing from scene");
|
|
|
+ return false;
|
|
|
+ }
|
|
|
|
|
|
- envMapPath = imageEntry.description.path;
|
|
|
+ description.nodes.forEach( function(nodeUID) {
|
|
|
+ this.buildNodeHirerachy(nodeUID, userInfo.rootObj);
|
|
|
+ }, this);
|
|
|
|
|
|
- }
|
|
|
+ if (this.delegate) {
|
|
|
+ this.delegate.loadCompleted(userInfo.callback, userInfo.rootObj);
|
|
|
+ }
|
|
|
|
|
|
- var samplerEntry = this.resources.getEntry( textureEntry.description.sampler );
|
|
|
- if ( samplerEntry ) {
|
|
|
+ return true;
|
|
|
+ }
|
|
|
+ },
|
|
|
|
|
|
- envMapParams = samplerEntry.description;
|
|
|
+ handleImage: {
|
|
|
+ value: function(entryID, description, userInfo) {
|
|
|
+ this.resources.setEntry(entryID, null, description);
|
|
|
+ return true;
|
|
|
+ }
|
|
|
+ },
|
|
|
|
|
|
- }
|
|
|
+ addNodeAnimationChannel : {
|
|
|
+ value : function(name, channel, interp) {
|
|
|
+ if (!this.nodeAnimationChannels)
|
|
|
+ this.nodeAnimationChannels = {};
|
|
|
|
|
|
- }
|
|
|
+ if (!this.nodeAnimationChannels[name]) {
|
|
|
+ this.nodeAnimationChannels[name] = [];
|
|
|
+ }
|
|
|
|
|
|
- }
|
|
|
+ this.nodeAnimationChannels[name].push(interp);
|
|
|
+ },
|
|
|
+ },
|
|
|
+
|
|
|
+ createAnimations : {
|
|
|
+ value : function() {
|
|
|
+ for (var name in this.nodeAnimationChannels) {
|
|
|
+ var nodeAnimationChannels = this.nodeAnimationChannels[name];
|
|
|
+ var i, len = nodeAnimationChannels.length;
|
|
|
+ //console.log(" animation channels for node " + name);
|
|
|
+ //for (i = 0; i < len; i++) {
|
|
|
+ // console.log(nodeAnimationChannels[i]);
|
|
|
+ //}
|
|
|
+ var anim = new THREE.glTFAnimation(nodeAnimationChannels);
|
|
|
+ anim.name = "animation_" + name;
|
|
|
+ this.animations.push(anim);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ },
|
|
|
|
|
|
- }
|
|
|
+ buildAnimation: {
|
|
|
+ value : function(animation) {
|
|
|
|
|
|
- }
|
|
|
+ var interps = [];
|
|
|
+ var i, len = animation.channels.length;
|
|
|
+ for (i = 0; i < len; i ++) {
|
|
|
|
|
|
- var texture = LoadTexture( envMapPath );
|
|
|
- if ( texture && envMapParams ) {
|
|
|
+ var channel = animation.channels[i];
|
|
|
+ var sampler = animation.samplers[channel.sampler];
|
|
|
+ if (sampler) {
|
|
|
|
|
|
- if ( envMapParams.wrapS == WebGLRenderingContext.REPEAT )
|
|
|
- texture.wrapS = THREE.RepeatWrapping;
|
|
|
+ var input = animation.parameters[sampler.input];
|
|
|
+ if (input && input.data) {
|
|
|
|
|
|
- if ( envMapParams.wrapT == WebGLRenderingContext.REPEAT )
|
|
|
- texture.wrapT = THREE.RepeatWrapping;
|
|
|
+ var output = animation.parameters[sampler.output];
|
|
|
+ if (output && output.data) {
|
|
|
|
|
|
- if ( envMapParams.magFilter == WebGLRenderingContext.LINEAR )
|
|
|
- texture.magFilter = THREE.LinearFilter;
|
|
|
+ var target = channel.target;
|
|
|
+ var node = this.resources.getEntry(target.id);
|
|
|
+ if (node) {
|
|
|
|
|
|
- // if (envMapParams.minFilter == WebGLRenderingContext.LINEAR)
|
|
|
- // texture.minFilter = THREE.LinearFilter;
|
|
|
+ var path = target.path;
|
|
|
|
|
|
- params.envMap = texture;
|
|
|
+ if (path == "rotation")
|
|
|
+ {
|
|
|
+ convertAxisAngleToQuaternion(output.data, output.count);
|
|
|
+ }
|
|
|
|
|
|
+ var interp = {
|
|
|
+ keys : input.data,
|
|
|
+ values : output.data,
|
|
|
+ count : input.count,
|
|
|
+ target : node.object,
|
|
|
+ path : path,
|
|
|
+ type : sampler.interpolation
|
|
|
+ };
|
|
|
+
|
|
|
+ this.addNodeAnimationChannel(target.id, channel, interp);
|
|
|
+ interps.push(interp);
|
|
|
+ }
|
|
|
}
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ },
|
|
|
|
|
|
- var shininess = values.shininesss || values.shininess; // N.B.: typo in converter!
|
|
|
- if ( shininess )
|
|
|
- {
|
|
|
+ handleAnimation: {
|
|
|
+ value: function(entryID, description, userInfo) {
|
|
|
|
|
|
- shininess = shininess;
|
|
|
-
|
|
|
- }
|
|
|
-
|
|
|
- var diffuseColor = ! texturePath ? diffuse : null;
|
|
|
- var opacity = 1.0;
|
|
|
- if ( values.hasOwnProperty( "transparency" ) )
|
|
|
- {
|
|
|
-
|
|
|
- var USE_A_ONE = true; // for now, hack because file format isn't telling us
|
|
|
- opacity = USE_A_ONE ? values.transparency : ( 1.0 - values.transparency );
|
|
|
-
|
|
|
- }
|
|
|
-
|
|
|
- // if (diffuseColor) diffuseColor = [0, 1, 0];
|
|
|
-
|
|
|
- params.color = RgbArraytoHex( diffuseColor );
|
|
|
- params.opacity = opacity;
|
|
|
- params.transparent = opacity < 1.0;
|
|
|
- // hack hack hack
|
|
|
- if ( texturePath && texturePath.toLowerCase().indexOf( ".png" ) != - 1 )
|
|
|
- params.transparent = true;
|
|
|
-
|
|
|
- if ( ! ( shininess === undefined ) )
|
|
|
- {
|
|
|
-
|
|
|
- params.shininess = shininess;
|
|
|
-
|
|
|
- }
|
|
|
-
|
|
|
- if ( ! ( values.emission === undefined ) )
|
|
|
- {
|
|
|
-
|
|
|
- params.emissive = RgbArraytoHex( values.emission );
|
|
|
-
|
|
|
- }
|
|
|
-
|
|
|
- if ( ! ( values.specular === undefined ) )
|
|
|
- {
|
|
|
-
|
|
|
- params.specular = RgbArraytoHex( values.specular );
|
|
|
-
|
|
|
- }
|
|
|
-
|
|
|
- return materialType;
|
|
|
-
|
|
|
- }
|
|
|
- },
|
|
|
-
|
|
|
- handleMaterial: {
|
|
|
- value: function( entryID, description, userInfo ) {
|
|
|
-
|
|
|
- //this should be rewritten using the meta datas that actually create the shader.
|
|
|
- //here we will infer what needs to be pass to Three.js by looking inside the technique parameters.
|
|
|
- var technique = this.resources.getEntry( description.instanceTechnique.technique );
|
|
|
- var materialParams = {};
|
|
|
- var values = description.instanceTechnique.values;
|
|
|
-
|
|
|
- var materialType = this.threeJSMaterialType( entryID, technique, values, materialParams );
|
|
|
-
|
|
|
- var material = new materialType( materialParams );
|
|
|
-
|
|
|
- this.resources.setEntry( entryID, material, description );
|
|
|
-
|
|
|
- return true;
|
|
|
-
|
|
|
- }
|
|
|
- },
|
|
|
-
|
|
|
- handleMesh: {
|
|
|
- value: function( entryID, description, userInfo ) {
|
|
|
-
|
|
|
- var mesh = new Mesh();
|
|
|
- this.resources.setEntry( entryID, mesh, description );
|
|
|
- var primitivesDescription = description.primitives;
|
|
|
- if ( ! primitivesDescription ) {
|
|
|
-
|
|
|
- //FIXME: not implemented in delegate
|
|
|
- console.log( "MISSING_PRIMITIVES for mesh:" + entryID );
|
|
|
- return false;
|
|
|
-
|
|
|
- }
|
|
|
-
|
|
|
- for ( var i = 0 ; i < primitivesDescription.length ; i ++ ) {
|
|
|
-
|
|
|
- var primitiveDescription = primitivesDescription[ i ];
|
|
|
-
|
|
|
- if ( primitiveDescription.primitive === WebGLRenderingContext.TRIANGLES ) {
|
|
|
-
|
|
|
- var geometry = new ClassicGeometry();
|
|
|
- var materialEntry = this.resources.getEntry( primitiveDescription.material );
|
|
|
-
|
|
|
- mesh.addPrimitive( geometry, materialEntry.object );
|
|
|
-
|
|
|
- var indices = this.resources.getEntry( primitiveDescription.indices );
|
|
|
- var bufferEntry = this.resources.getEntry( indices.description.bufferView );
|
|
|
- var indicesObject = {
|
|
|
- bufferView : bufferEntry,
|
|
|
- byteOffset : indices.description.byteOffset,
|
|
|
- count : indices.description.count,
|
|
|
- id : indices.entryID,
|
|
|
- type : indices.description.type
|
|
|
- };
|
|
|
-
|
|
|
- var indicesContext = new IndicesContext( indicesObject, geometry );
|
|
|
- var alreadyProcessedIndices = THREE.GLTFLoaderUtils.getBuffer( indicesObject, indicesDelegate, indicesContext );
|
|
|
- /*if(alreadyProcessedIndices) {
|
|
|
- indicesDelegate.resourceAvailable(alreadyProcessedIndices, indicesContext);
|
|
|
- }*/
|
|
|
-
|
|
|
- // Load Vertex Attributes
|
|
|
- var allAttributes = Object.keys( primitiveDescription.attributes );
|
|
|
- allAttributes.forEach( function( semantic ) {
|
|
|
-
|
|
|
- geometry.totalAttributes ++;
|
|
|
-
|
|
|
- var attribute;
|
|
|
- var attributeID = primitiveDescription.attributes[ semantic ];
|
|
|
- var attributeEntry = this.resources.getEntry( attributeID );
|
|
|
- if ( ! attributeEntry ) {
|
|
|
-
|
|
|
- //let's just use an anonymous object for the attribute
|
|
|
- attribute = description.attributes[ attributeID ];
|
|
|
- attribute.id = attributeID;
|
|
|
- this.resources.setEntry( attributeID, attribute, attribute );
|
|
|
-
|
|
|
- var bufferEntry = this.resources.getEntry( attribute.bufferView );
|
|
|
- attributeEntry = this.resources.getEntry( attributeID );
|
|
|
-
|
|
|
- } else {
|
|
|
-
|
|
|
- attribute = attributeEntry.object;
|
|
|
- attribute.id = attributeID;
|
|
|
- var bufferEntry = this.resources.getEntry( attribute.bufferView );
|
|
|
-
|
|
|
- }
|
|
|
-
|
|
|
- var attributeObject = {
|
|
|
- bufferView : bufferEntry,
|
|
|
- byteOffset : attribute.byteOffset,
|
|
|
- byteStride : attribute.byteStride,
|
|
|
- count : attribute.count,
|
|
|
- max : attribute.max,
|
|
|
- min : attribute.min,
|
|
|
- type : attribute.type,
|
|
|
- id : attributeID
|
|
|
- };
|
|
|
-
|
|
|
- var attribContext = new VertexAttributeContext( attributeObject, semantic, geometry );
|
|
|
-
|
|
|
- var alreadyProcessedAttribute = THREE.GLTFLoaderUtils.getBuffer( attributeObject, vertexAttributeDelegate, attribContext );
|
|
|
- /*if(alreadyProcessedAttribute) {
|
|
|
- vertexAttributeDelegate.resourceAvailable(alreadyProcessedAttribute, attribContext);
|
|
|
- }*/
|
|
|
-
|
|
|
- }, this );
|
|
|
-
|
|
|
- }
|
|
|
-
|
|
|
- }
|
|
|
- return true;
|
|
|
-
|
|
|
- }
|
|
|
- },
|
|
|
-
|
|
|
- handleCamera: {
|
|
|
- value: function( entryID, description, userInfo ) {
|
|
|
-
|
|
|
- var camera;
|
|
|
- if ( description.type == "perspective" ) {
|
|
|
-
|
|
|
- var znear = description.perspective.znear;
|
|
|
- var zfar = description.perspective.zfar;
|
|
|
- var yfov = description.perspective.yfov;
|
|
|
- var xfov = description.perspective.xfov;
|
|
|
- var aspect_ratio = description.perspective.aspect_ratio;
|
|
|
-
|
|
|
- if ( ! aspect_ratio ) {
|
|
|
-
|
|
|
- aspect_ratio = 1;
|
|
|
-
|
|
|
- }
|
|
|
-
|
|
|
- if ( yfov === undefined ) {
|
|
|
-
|
|
|
- if ( xfov ) {
|
|
|
-
|
|
|
- // According to COLLADA spec...
|
|
|
- // aspect_ratio = xfov / yfov
|
|
|
- yfov = xfov / aspect_ratio;
|
|
|
-
|
|
|
- }
|
|
|
-
|
|
|
- }
|
|
|
-
|
|
|
- if ( yfov ) {
|
|
|
-
|
|
|
- camera = new THREE.PerspectiveCamera( yfov, aspect_ratio, znear, zfar );
|
|
|
-
|
|
|
- }
|
|
|
-
|
|
|
- } else {
|
|
|
-
|
|
|
- camera = new THREE.OrthographicCamera( window.innerWidth / - 2, window.innerWidth / 2, window.innerHeight / 2, window.innerHeight / - 2, znear, zfar );
|
|
|
-
|
|
|
- }
|
|
|
-
|
|
|
- if ( camera ) {
|
|
|
-
|
|
|
- this.resources.setEntry( entryID, camera, description );
|
|
|
-
|
|
|
- }
|
|
|
-
|
|
|
- return true;
|
|
|
-
|
|
|
- }
|
|
|
- },
|
|
|
-
|
|
|
- handleLight: {
|
|
|
- value: function( entryID, description, userInfo ) {
|
|
|
-
|
|
|
- var light = null;
|
|
|
- var type = description.type;
|
|
|
- if ( type && description[ type ] ) {
|
|
|
-
|
|
|
- var lparams = description[ type ];
|
|
|
- var color = RgbArraytoHex( lparams.color );
|
|
|
-
|
|
|
- switch ( type ) {
|
|
|
- case "directional" :
|
|
|
- light = new THREE.DirectionalLight( color );
|
|
|
- light.position.set( 0, 0, 1 );
|
|
|
- break;
|
|
|
-
|
|
|
- case "point" :
|
|
|
- light = new THREE.PointLight( color );
|
|
|
- break;
|
|
|
-
|
|
|
- case "spot " :
|
|
|
- light = new THREE.SpotLight( color );
|
|
|
- light.position.set( 0, 0, 1 );
|
|
|
- break;
|
|
|
-
|
|
|
- case "ambient" :
|
|
|
- light = new THREE.AmbientLight( color );
|
|
|
- break;
|
|
|
- }
|
|
|
-
|
|
|
- }
|
|
|
-
|
|
|
- if ( light ) {
|
|
|
-
|
|
|
- this.resources.setEntry( entryID, light, description );
|
|
|
-
|
|
|
- }
|
|
|
-
|
|
|
- return true;
|
|
|
-
|
|
|
- }
|
|
|
- },
|
|
|
-
|
|
|
- addPendingMesh: {
|
|
|
- value: function( mesh, threeNode ) {
|
|
|
-
|
|
|
- theLoader.pendingMeshes.push( {
|
|
|
-
|
|
|
- mesh: mesh,
|
|
|
- node: threeNode
|
|
|
-
|
|
|
- } );
|
|
|
-
|
|
|
- }
|
|
|
- },
|
|
|
-
|
|
|
- handleNode: {
|
|
|
- value: function( entryID, description, userInfo ) {
|
|
|
-
|
|
|
- var threeNode = null;
|
|
|
- if ( description.jointId ) {
|
|
|
-
|
|
|
- threeNode = new THREE.Bone();
|
|
|
- threeNode.jointId = description.jointId;
|
|
|
- this.joints[ description.jointId ] = entryID;
|
|
|
-
|
|
|
- }
|
|
|
- else {
|
|
|
-
|
|
|
- threeNode = new THREE.Object3D();
|
|
|
-
|
|
|
- }
|
|
|
-
|
|
|
- threeNode.name = description.name;
|
|
|
-
|
|
|
- this.resources.setEntry( entryID, threeNode, description );
|
|
|
-
|
|
|
- var m = description.matrix;
|
|
|
- if ( m ) {
|
|
|
-
|
|
|
- threeNode.applyMatrix( new THREE.Matrix4().fromArray( m ) );
|
|
|
- threeNode.matrixAutoUpdate = false;
|
|
|
- threeNode.matrixWorldNeedsUpdate = true;
|
|
|
-
|
|
|
- } else {
|
|
|
-
|
|
|
- var t = description.translation;
|
|
|
- var r = description.rotation;
|
|
|
- var s = description.scale;
|
|
|
-
|
|
|
- var position = t ? new THREE.Vector3( t[ 0 ], t[ 1 ], t[ 2 ] ) : new THREE.Vector3;
|
|
|
-
|
|
|
- if ( r ) {
|
|
|
-
|
|
|
- convertAxisAngleToQuaternion( r, 1 );
|
|
|
-
|
|
|
- }
|
|
|
-
|
|
|
- var rotation = r ? new THREE.Quaternion( r[ 0 ], r[ 1 ], r[ 2 ], r[ 3 ] ) : new THREE.Quaternion;
|
|
|
- var scale = s ? new THREE.Vector3( s[ 0 ], s[ 1 ], s[ 2 ] ) : new THREE.Vector3;
|
|
|
-
|
|
|
- var matrix = new THREE.Matrix4;
|
|
|
- matrix.compose( position, rotation, scale );
|
|
|
- threeNode.matrixAutoUpdate = false;
|
|
|
- threeNode.matrixWorldNeedsUpdate = true;
|
|
|
- threeNode.applyMatrix( matrix );
|
|
|
-
|
|
|
- }
|
|
|
-
|
|
|
- var self = this;
|
|
|
-
|
|
|
- // Iterate through all node meshes and attach the appropriate objects
|
|
|
- //FIXME: decision needs to be made between these 2 ways, probably meshes will be discarded.
|
|
|
- var meshEntry;
|
|
|
- if ( description.mesh ) {
|
|
|
-
|
|
|
- meshEntry = this.resources.getEntry( description.mesh );
|
|
|
- theLoader.meshesRequested ++;
|
|
|
- meshEntry.object.onComplete( function( mesh ) {
|
|
|
-
|
|
|
- self.addPendingMesh( mesh, threeNode );
|
|
|
- theLoader.meshesLoaded ++;
|
|
|
- theLoader.checkComplete();
|
|
|
-
|
|
|
- } );
|
|
|
-
|
|
|
- }
|
|
|
-
|
|
|
- if ( description.meshes ) {
|
|
|
-
|
|
|
- description.meshes.forEach( function( meshID ) {
|
|
|
-
|
|
|
- meshEntry = this.resources.getEntry( meshID );
|
|
|
- theLoader.meshesRequested ++;
|
|
|
- meshEntry.object.onComplete( function( mesh ) {
|
|
|
-
|
|
|
- self.addPendingMesh( mesh, threeNode );
|
|
|
- theLoader.meshesLoaded ++;
|
|
|
- theLoader.checkComplete();
|
|
|
-
|
|
|
- } );
|
|
|
-
|
|
|
- }, this );
|
|
|
-
|
|
|
- }
|
|
|
-
|
|
|
- if ( description.instanceSkin ) {
|
|
|
-
|
|
|
- var skinEntry = this.resources.getEntry( description.instanceSkin.skin );
|
|
|
-
|
|
|
- if ( skinEntry ) {
|
|
|
-
|
|
|
- var skin = skinEntry.object;
|
|
|
- description.instanceSkin.skin = skin;
|
|
|
- threeNode.instanceSkin = description.instanceSkin;
|
|
|
-
|
|
|
- var sources = description.instanceSkin.sources;
|
|
|
- skin.meshes = [];
|
|
|
- sources.forEach( function( meshID ) {
|
|
|
-
|
|
|
- meshEntry = this.resources.getEntry( meshID );
|
|
|
- theLoader.meshesRequested ++;
|
|
|
- meshEntry.object.onComplete( function( mesh ) {
|
|
|
-
|
|
|
- skin.meshes.push( mesh );
|
|
|
- theLoader.meshesLoaded ++;
|
|
|
- theLoader.checkComplete();
|
|
|
-
|
|
|
- } );
|
|
|
-
|
|
|
- }, this );
|
|
|
-
|
|
|
- }
|
|
|
-
|
|
|
- }
|
|
|
-
|
|
|
- if ( description.camera ) {
|
|
|
-
|
|
|
- var cameraEntry = this.resources.getEntry( description.camera );
|
|
|
- if ( cameraEntry ) {
|
|
|
-
|
|
|
- threeNode.add( cameraEntry.object );
|
|
|
- this.cameras.push( cameraEntry.object );
|
|
|
-
|
|
|
- }
|
|
|
-
|
|
|
- }
|
|
|
-
|
|
|
- if ( description.light ) {
|
|
|
-
|
|
|
- var lightEntry = this.resources.getEntry( description.light );
|
|
|
- if ( lightEntry ) {
|
|
|
-
|
|
|
- threeNode.add( lightEntry.object );
|
|
|
- this.lights.push( lightEntry.object );
|
|
|
-
|
|
|
- }
|
|
|
-
|
|
|
- }
|
|
|
-
|
|
|
- return true;
|
|
|
-
|
|
|
- }
|
|
|
- },
|
|
|
-
|
|
|
- buildNodeHirerachy: {
|
|
|
- value: function( nodeEntryId, parentThreeNode ) {
|
|
|
-
|
|
|
- var nodeEntry = this.resources.getEntry( nodeEntryId );
|
|
|
- var threeNode = nodeEntry.object;
|
|
|
- parentThreeNode.add( threeNode );
|
|
|
-
|
|
|
- var children = nodeEntry.description.children;
|
|
|
- if ( children ) {
|
|
|
-
|
|
|
- children.forEach( function( childID ) {
|
|
|
-
|
|
|
- this.buildNodeHirerachy( childID, threeNode );
|
|
|
-
|
|
|
- }, this );
|
|
|
-
|
|
|
- }
|
|
|
-
|
|
|
- return threeNode;
|
|
|
-
|
|
|
- }
|
|
|
- },
|
|
|
-
|
|
|
- buildSkin: {
|
|
|
- value: function( node ) {
|
|
|
-
|
|
|
- var skin = node.instanceSkin.skin;
|
|
|
- if ( skin ) {
|
|
|
-
|
|
|
- node.instanceSkin.skeletons.forEach( function( skeleton ) {
|
|
|
-
|
|
|
- var nodeEntry = this.resources.getEntry( skeleton );
|
|
|
- if ( nodeEntry ) {
|
|
|
-
|
|
|
- var rootSkeleton = nodeEntry.object;
|
|
|
-
|
|
|
- var dobones = true;
|
|
|
-
|
|
|
- var i, len = skin.meshes.length;
|
|
|
- for ( i = 0; i < len; i ++ ) {
|
|
|
-
|
|
|
- var mesh = skin.meshes[ i ];
|
|
|
- var threeMesh = null;
|
|
|
- mesh.primitives.forEach( function( primitive ) {
|
|
|
-
|
|
|
- var material = primitive.material;
|
|
|
- if ( ! ( material instanceof THREE.Material ) ) {
|
|
|
-
|
|
|
- material = this.createShaderMaterial( material );
|
|
|
-
|
|
|
- }
|
|
|
-
|
|
|
- threeMesh = new THREE.SkinnedMesh( primitive.geometry.geometry, material, false );
|
|
|
- threeMesh.add( rootSkeleton );
|
|
|
-
|
|
|
- var geometry = primitive.geometry.geometry;
|
|
|
- var j;
|
|
|
- if ( geometry.vertices ) {
|
|
|
-
|
|
|
- for ( j = 0; j < geometry.vertices.length; j ++ ) {
|
|
|
-
|
|
|
- geometry.vertices[ j ].applyMatrix4( skin.bindShapeMatrix );
|
|
|
-
|
|
|
- }
|
|
|
-
|
|
|
- } else if ( geometry.attributes.position ) {
|
|
|
-
|
|
|
- var a = geometry.attributes.position.array;
|
|
|
- var v = new THREE.Vector3;
|
|
|
- for ( j = 0; j < a.length / 3; j ++ ) {
|
|
|
-
|
|
|
- v.set( a[ j * 3 ], a[ j * 3 + 1 ], a[ j * 3 + 2 ] );
|
|
|
- v.applyMatrix4( skin.bindShapeMatrix );
|
|
|
- a[ j * 3 ] = v.x;
|
|
|
- a[ j * 3 + 1 ] = v.y;
|
|
|
- a[ j * 3 + 2 ] = v.z;
|
|
|
-
|
|
|
- }
|
|
|
-
|
|
|
- }
|
|
|
-
|
|
|
- if ( threeMesh && dobones ) {
|
|
|
-
|
|
|
- material.skinning = true;
|
|
|
-
|
|
|
- threeMesh.boneInverses = [];
|
|
|
- var jointsIds = skin.jointsIds;
|
|
|
- var bones = [];
|
|
|
- var boneInverses = [];
|
|
|
- var i, len = jointsIds.length;
|
|
|
- for ( i = 0; i < len; i ++ ) {
|
|
|
-
|
|
|
- var jointId = jointsIds[ i ];
|
|
|
- var nodeForJoint = this.joints[ jointId ];
|
|
|
- var joint = this.resources.getEntry( nodeForJoint ).object;
|
|
|
- if ( joint ) {
|
|
|
-
|
|
|
- joint.skin = threeMesh;
|
|
|
- bones.push( joint );
|
|
|
-
|
|
|
- var m = skin.inverseBindMatrices;
|
|
|
- var mat = new THREE.Matrix4().set(
|
|
|
- m[ i * 16 + 0 ], m[ i * 16 + 4 ], m[ i * 16 + 8 ], m[ i * 16 + 12 ],
|
|
|
- m[ i * 16 + 1 ], m[ i * 16 + 5 ], m[ i * 16 + 9 ], m[ i * 16 + 13 ],
|
|
|
- m[ i * 16 + 2 ], m[ i * 16 + 6 ], m[ i * 16 + 10 ], m[ i * 16 + 14 ],
|
|
|
- m[ i * 16 + 3 ], m[ i * 16 + 7 ], m[ i * 16 + 11 ], m[ i * 16 + 15 ]
|
|
|
- );
|
|
|
- boneInverses.push( mat );
|
|
|
-
|
|
|
- } else {
|
|
|
-
|
|
|
- console.log( "WARNING: jointId:" + jointId + " cannot be found in skeleton:" + skeleton );
|
|
|
-
|
|
|
- }
|
|
|
-
|
|
|
- }
|
|
|
-
|
|
|
- threeMesh.bind( new THREE.Skeleton( bones, boneInverses, false ), threeMesh.matrixWorld );
|
|
|
-
|
|
|
- }
|
|
|
-
|
|
|
- if ( threeMesh ) {
|
|
|
-
|
|
|
- threeMesh.castShadow = true;
|
|
|
- node.add( threeMesh );
|
|
|
-
|
|
|
- }
|
|
|
-
|
|
|
- }, this );
|
|
|
-
|
|
|
- }
|
|
|
-
|
|
|
- }
|
|
|
-
|
|
|
-
|
|
|
- }, this );
|
|
|
-
|
|
|
- }
|
|
|
-
|
|
|
- }
|
|
|
- },
|
|
|
-
|
|
|
- buildSkins: {
|
|
|
- value: function( node ) {
|
|
|
-
|
|
|
- if ( node.instanceSkin ) {
|
|
|
- this.buildSkin( node );
|
|
|
- }
|
|
|
-
|
|
|
- var children = node.children;
|
|
|
-
|
|
|
- if ( children ) {
|
|
|
-
|
|
|
- children.forEach( function( child ) {
|
|
|
-
|
|
|
- this.buildSkins( child );
|
|
|
-
|
|
|
- }, this );
|
|
|
-
|
|
|
- }
|
|
|
-
|
|
|
- }
|
|
|
- },
|
|
|
-
|
|
|
- createMeshAnimations : {
|
|
|
- value : function( root ) {
|
|
|
-
|
|
|
- this.buildSkins( root );
|
|
|
-
|
|
|
- }
|
|
|
- },
|
|
|
-
|
|
|
- handleScene: {
|
|
|
- value: function( entryID, description, userInfo ) {
|
|
|
-
|
|
|
- if ( ! description.nodes ) {
|
|
|
-
|
|
|
- console.log( "ERROR: invalid file required nodes property is missing from scene" );
|
|
|
- return false;
|
|
|
-
|
|
|
- }
|
|
|
-
|
|
|
- description.nodes.forEach( function( nodeUID ) {
|
|
|
-
|
|
|
- this.buildNodeHirerachy( nodeUID, userInfo.rootObj );
|
|
|
-
|
|
|
- }, this );
|
|
|
-
|
|
|
- if ( this.delegate ) {
|
|
|
-
|
|
|
- this.delegate.loadCompleted( userInfo.callback, userInfo.rootObj );
|
|
|
-
|
|
|
- }
|
|
|
-
|
|
|
- return true;
|
|
|
-
|
|
|
- }
|
|
|
- },
|
|
|
-
|
|
|
- handleImage: {
|
|
|
- value: function( entryID, description, userInfo ) {
|
|
|
-
|
|
|
- this.resources.setEntry( entryID, null, description );
|
|
|
- return true;
|
|
|
-
|
|
|
- }
|
|
|
- },
|
|
|
-
|
|
|
- addNodeAnimationChannel : {
|
|
|
- value : function( name, channel, interp ) {
|
|
|
-
|
|
|
- if ( ! this.nodeAnimationChannels ) {
|
|
|
-
|
|
|
- this.nodeAnimationChannels = {};
|
|
|
-
|
|
|
- }
|
|
|
-
|
|
|
- if ( ! this.nodeAnimationChannels[ name ] ) {
|
|
|
-
|
|
|
- this.nodeAnimationChannels[ name ] = [];
|
|
|
-
|
|
|
- }
|
|
|
-
|
|
|
- this.nodeAnimationChannels[ name ].push( interp );
|
|
|
-
|
|
|
- },
|
|
|
- },
|
|
|
-
|
|
|
- createAnimations : {
|
|
|
- value : function() {
|
|
|
-
|
|
|
- for ( var name in this.nodeAnimationChannels ) {
|
|
|
-
|
|
|
- var nodeAnimationChannels = this.nodeAnimationChannels[ name ];
|
|
|
- var i, len = nodeAnimationChannels.length;
|
|
|
- //console.log(" animation channels for node " + name);
|
|
|
- //for (i = 0; i < len; i++) {
|
|
|
- // console.log(nodeAnimationChannels[i]);
|
|
|
- //}
|
|
|
- var anim = new THREE.glTFAnimation( nodeAnimationChannels );
|
|
|
- anim.name = "animation_" + name;
|
|
|
- this.animations.push( anim );
|
|
|
-
|
|
|
- }
|
|
|
-
|
|
|
- }
|
|
|
- },
|
|
|
-
|
|
|
- buildAnimation: {
|
|
|
- value : function( animation ) {
|
|
|
-
|
|
|
- var interps = [];
|
|
|
- var i, len = animation.channels.length;
|
|
|
- for ( i = 0; i < len; i ++ ) {
|
|
|
-
|
|
|
- var channel = animation.channels[ i ];
|
|
|
- var sampler = animation.samplers[ channel.sampler ];
|
|
|
- if ( sampler ) {
|
|
|
-
|
|
|
- var input = animation.parameters[ sampler.input ];
|
|
|
- if ( input && input.data ) {
|
|
|
-
|
|
|
- var output = animation.parameters[ sampler.output ];
|
|
|
- if ( output && output.data ) {
|
|
|
-
|
|
|
- var target = channel.target;
|
|
|
- var node = this.resources.getEntry( target.id );
|
|
|
- if ( node ) {
|
|
|
-
|
|
|
- var path = target.path;
|
|
|
-
|
|
|
- if ( path == "rotation" ) {
|
|
|
-
|
|
|
- convertAxisAngleToQuaternion( output.data, output.count );
|
|
|
-
|
|
|
- }
|
|
|
-
|
|
|
- var interp = {
|
|
|
- keys : input.data,
|
|
|
- values : output.data,
|
|
|
- count : input.count,
|
|
|
- target : node.object,
|
|
|
- path : path,
|
|
|
- type : sampler.interpolation
|
|
|
- };
|
|
|
-
|
|
|
- this.addNodeAnimationChannel( target.id, channel, interp );
|
|
|
- interps.push( interp );
|
|
|
-
|
|
|
- }
|
|
|
-
|
|
|
- }
|
|
|
-
|
|
|
- }
|
|
|
-
|
|
|
- }
|
|
|
-
|
|
|
- }
|
|
|
-
|
|
|
- }
|
|
|
- },
|
|
|
-
|
|
|
- handleAnimation: {
|
|
|
- value: function( entryID, description, userInfo ) {
|
|
|
-
|
|
|
- var self = this;
|
|
|
- theLoader.animationsRequested ++;
|
|
|
- var animation = new Animation();
|
|
|
- animation.name = entryID;
|
|
|
- animation.onload = function() {
|
|
|
-
|
|
|
- // self.buildAnimation(animation);
|
|
|
- theLoader.animationsLoaded ++;
|
|
|
- theLoader.animations.push( animation );
|
|
|
- theLoader.checkComplete();
|
|
|
-
|
|
|
- };
|
|
|
-
|
|
|
- animation.channels = description.channels;
|
|
|
- animation.samplers = description.samplers;
|
|
|
- this.resources.setEntry( entryID, animation, description );
|
|
|
- var parameters = description.parameters;
|
|
|
- if ( ! parameters ) {
|
|
|
-
|
|
|
- //FIXME: not implemented in delegate
|
|
|
- console.log( "MISSING_PARAMETERS for animation:" + entryID );
|
|
|
- return false;
|
|
|
-
|
|
|
- }
|
|
|
-
|
|
|
- // Load parameter buffers
|
|
|
- var params = Object.keys( parameters );
|
|
|
- params.forEach( function( param ) {
|
|
|
-
|
|
|
- animation.totalParameters ++;
|
|
|
- var parameter = parameters[ param ];
|
|
|
- var accessor = this.resources.getEntry( parameter );
|
|
|
-
|
|
|
- if ( ! accessor ) {
|
|
|
- debugger;
|
|
|
- }
|
|
|
-
|
|
|
- accessor = accessor.object;
|
|
|
- var bufferView = this.resources.getEntry( accessor.bufferView );
|
|
|
- var paramObject = {
|
|
|
- bufferView : bufferView,
|
|
|
- byteOffset : accessor.byteOffset,
|
|
|
- count : accessor.count,
|
|
|
- type : accessor.type,
|
|
|
- id : accessor.bufferView,
|
|
|
- name : param
|
|
|
- };
|
|
|
-
|
|
|
- var paramContext = new AnimationParameterContext( paramObject, animation );
|
|
|
-
|
|
|
- var alreadyProcessedAttribute = THREE.GLTFLoaderUtils.getBuffer( paramObject, animationParameterDelegate, paramContext );
|
|
|
- /*if ( alreadyProcessedAttribute ) {
|
|
|
- vertexAttributeDelegate.resourceAvailable(alreadyProcessedAttribute, attribContext);
|
|
|
+ var self = this;
|
|
|
+ theLoader.animationsRequested ++;
|
|
|
+ var animation = new Animation();
|
|
|
+ animation.name = entryID;
|
|
|
+ animation.onload = function() {
|
|
|
+ // self.buildAnimation(animation);
|
|
|
+ theLoader.animationsLoaded ++;
|
|
|
+ theLoader.animations.push(animation);
|
|
|
+ theLoader.checkComplete();
|
|
|
+ };
|
|
|
+
|
|
|
+ animation.channels = description.channels;
|
|
|
+ animation.samplers = description.samplers;
|
|
|
+ this.resources.setEntry(entryID, animation, description);
|
|
|
+ var parameters = description.parameters;
|
|
|
+ if (!parameters) {
|
|
|
+ //FIXME: not implemented in delegate
|
|
|
+ console.log("MISSING_PARAMETERS for animation:" + entryID);
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+
|
|
|
+ // Load parameter buffers
|
|
|
+ var params = Object.keys(parameters);
|
|
|
+ params.forEach( function(param) {
|
|
|
+
|
|
|
+ animation.totalParameters ++;
|
|
|
+ var parameter = parameters[param];
|
|
|
+ var accessor = this.resources.getEntry(parameter);
|
|
|
+ if (!accessor)
|
|
|
+ debugger;
|
|
|
+ accessor = accessor.object;
|
|
|
+ var bufferView = this.resources.getEntry(accessor.bufferView);
|
|
|
+ var paramObject = {
|
|
|
+ bufferView : bufferView,
|
|
|
+ byteOffset : accessor.byteOffset,
|
|
|
+ count : accessor.count,
|
|
|
+ type : accessor.type,
|
|
|
+ id : accessor.bufferView,
|
|
|
+ name : param
|
|
|
+ };
|
|
|
+
|
|
|
+ var paramContext = new AnimationParameterContext(paramObject, animation);
|
|
|
+
|
|
|
+ var alreadyProcessedAttribute = THREE.GLTFLoaderUtils.getBuffer(paramObject, animationParameterDelegate, paramContext);
|
|
|
+ /*if(alreadyProcessedAttribute) {
|
|
|
+ vertexAttributeDelegate.resourceAvailable(alreadyProcessedAttribute, attribContext);
|
|
|
}*/
|
|
|
-
|
|
|
- }, this );
|
|
|
-
|
|
|
- return true;
|
|
|
-
|
|
|
- }
|
|
|
- },
|
|
|
-
|
|
|
- handleAccessor: {
|
|
|
-
|
|
|
- value: function( entryID, description, userInfo ) {
|
|
|
-
|
|
|
- // Save attribute entry
|
|
|
- this.resources.setEntry( entryID, description, description );
|
|
|
- return true;
|
|
|
-
|
|
|
- }
|
|
|
- },
|
|
|
-
|
|
|
- handleSkin: {
|
|
|
-
|
|
|
- value: function( entryID, description, userInfo ) {
|
|
|
-
|
|
|
- // Save skin entry
|
|
|
-
|
|
|
- var skin = {};
|
|
|
-
|
|
|
- var m = description.bindShapeMatrix;
|
|
|
- skin.bindShapeMatrix = new THREE.Matrix4().fromArray( m );
|
|
|
-
|
|
|
- skin.jointsIds = description.joints;
|
|
|
- var inverseBindMatricesDescription = description.inverseBindMatrices;
|
|
|
- skin.inverseBindMatricesDescription = inverseBindMatricesDescription;
|
|
|
- skin.inverseBindMatricesDescription.id = entryID + "_inverseBindMatrices";
|
|
|
-
|
|
|
- var bufferEntry = this.resources.getEntry( inverseBindMatricesDescription.bufferView );
|
|
|
-
|
|
|
- var paramObject = {
|
|
|
-
|
|
|
- bufferView : bufferEntry,
|
|
|
- byteOffset : inverseBindMatricesDescription.byteOffset,
|
|
|
- count : inverseBindMatricesDescription.count,
|
|
|
- type : inverseBindMatricesDescription.type,
|
|
|
- id : inverseBindMatricesDescription.bufferView,
|
|
|
- name : skin.inverseBindMatricesDescription.id
|
|
|
-
|
|
|
- };
|
|
|
-
|
|
|
- var context = new InverseBindMatricesContext( paramObject, skin );
|
|
|
-
|
|
|
- var alreadyProcessedAttribute = THREE.GLTFLoaderUtils.getBuffer( paramObject, inverseBindMatricesDelegate, context );
|
|
|
-
|
|
|
- var bufferView = this.resources.getEntry( skin.inverseBindMatricesDescription.bufferView );
|
|
|
- skin.inverseBindMatricesDescription.bufferView =
|
|
|
- bufferView.object;
|
|
|
- this.resources.setEntry( entryID, skin, description );
|
|
|
- return true;
|
|
|
-
|
|
|
- }
|
|
|
- },
|
|
|
-
|
|
|
- handleSampler: {
|
|
|
- value: function( entryID, description, userInfo ) {
|
|
|
-
|
|
|
- // Save attribute entry
|
|
|
- this.resources.setEntry( entryID, description, description );
|
|
|
- return true;
|
|
|
-
|
|
|
- }
|
|
|
- },
|
|
|
-
|
|
|
- handleTexture: {
|
|
|
- value: function( entryID, description, userInfo ) {
|
|
|
-
|
|
|
- // Save attribute entry
|
|
|
- this.resources.setEntry( entryID, null, description );
|
|
|
- return true;
|
|
|
-
|
|
|
- }
|
|
|
- },
|
|
|
-
|
|
|
- handleError: {
|
|
|
- value: function( msg ) {
|
|
|
-
|
|
|
- throw new Error( msg );
|
|
|
- return true;
|
|
|
-
|
|
|
- }
|
|
|
- },
|
|
|
-
|
|
|
- _delegate: {
|
|
|
- value: new LoadDelegate,
|
|
|
- writable: true
|
|
|
- },
|
|
|
-
|
|
|
- delegate: {
|
|
|
- enumerable: true,
|
|
|
- get: function() {
|
|
|
-
|
|
|
- return this._delegate;
|
|
|
-
|
|
|
- },
|
|
|
- set: function( value ) {
|
|
|
-
|
|
|
- this._delegate = value;
|
|
|
-
|
|
|
- }
|
|
|
- }
|
|
|
- } );
|
|
|
-
|
|
|
-
|
|
|
- // Loader
|
|
|
-
|
|
|
- var Context = function( rootObj, callback ) {
|
|
|
-
|
|
|
+ }, this);
|
|
|
+
|
|
|
+ return true;
|
|
|
+ }
|
|
|
+ },
|
|
|
+
|
|
|
+ handleAccessor: {
|
|
|
+ value: function(entryID, description, userInfo) {
|
|
|
+ // Save attribute entry
|
|
|
+ this.resources.setEntry(entryID, description, description);
|
|
|
+ return true;
|
|
|
+ }
|
|
|
+ },
|
|
|
+
|
|
|
+ handleSkin: {
|
|
|
+ value: function(entryID, description, userInfo) {
|
|
|
+ // Save skin entry
|
|
|
+
|
|
|
+ var skin = {
|
|
|
+ };
|
|
|
+
|
|
|
+ var m = description.bindShapeMatrix;
|
|
|
+ skin.bindShapeMatrix = new THREE.Matrix4().fromArray( m );
|
|
|
+
|
|
|
+ skin.jointsIds = description.joints;
|
|
|
+ var inverseBindMatricesDescription = description.inverseBindMatrices;
|
|
|
+ skin.inverseBindMatricesDescription = inverseBindMatricesDescription;
|
|
|
+ skin.inverseBindMatricesDescription.id = entryID + "_inverseBindMatrices";
|
|
|
+
|
|
|
+ var bufferEntry = this.resources.getEntry(inverseBindMatricesDescription.bufferView);
|
|
|
+
|
|
|
+ var paramObject = {
|
|
|
+ bufferView : bufferEntry,
|
|
|
+ byteOffset : inverseBindMatricesDescription.byteOffset,
|
|
|
+ count : inverseBindMatricesDescription.count,
|
|
|
+ type : inverseBindMatricesDescription.type,
|
|
|
+ id : inverseBindMatricesDescription.bufferView,
|
|
|
+ name : skin.inverseBindMatricesDescription.id
|
|
|
+ };
|
|
|
+
|
|
|
+ var context = new InverseBindMatricesContext(paramObject, skin);
|
|
|
+
|
|
|
+ var alreadyProcessedAttribute = THREE.GLTFLoaderUtils.getBuffer(paramObject, inverseBindMatricesDelegate, context);
|
|
|
+
|
|
|
+ var bufferView = this.resources.getEntry(skin.inverseBindMatricesDescription.bufferView);
|
|
|
+ skin.inverseBindMatricesDescription.bufferView =
|
|
|
+ bufferView.object;
|
|
|
+ this.resources.setEntry(entryID, skin, description);
|
|
|
+ return true;
|
|
|
+ }
|
|
|
+ },
|
|
|
+
|
|
|
+ handleSampler: {
|
|
|
+ value: function(entryID, description, userInfo) {
|
|
|
+ // Save attribute entry
|
|
|
+ this.resources.setEntry(entryID, description, description);
|
|
|
+ return true;
|
|
|
+ }
|
|
|
+ },
|
|
|
+
|
|
|
+ handleTexture: {
|
|
|
+ value: function(entryID, description, userInfo) {
|
|
|
+ // Save attribute entry
|
|
|
+ this.resources.setEntry(entryID, null, description);
|
|
|
+ return true;
|
|
|
+ }
|
|
|
+ },
|
|
|
+
|
|
|
+ handleError: {
|
|
|
+ value: function(msg) {
|
|
|
+
|
|
|
+ throw new Error(msg);
|
|
|
+ return true;
|
|
|
+ }
|
|
|
+ },
|
|
|
+
|
|
|
+ _delegate: {
|
|
|
+ value: new LoadDelegate,
|
|
|
+ writable: true
|
|
|
+ },
|
|
|
+
|
|
|
+ delegate: {
|
|
|
+ enumerable: true,
|
|
|
+ get: function() {
|
|
|
+ return this._delegate;
|
|
|
+ },
|
|
|
+ set: function(value) {
|
|
|
+ this._delegate = value;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ });
|
|
|
+
|
|
|
+
|
|
|
+ // Loader
|
|
|
+
|
|
|
+ var Context = function(rootObj, callback) {
|
|
|
this.rootObj = rootObj;
|
|
|
this.callback = callback;
|
|
|
-
|
|
|
};
|
|
|
|
|
|
var rootObj = new THREE.Object3D();
|
|
|
|
|
|
var self = this;
|
|
|
|
|
|
- var loader = Object.create( ThreeGLTFLoader );
|
|
|
- loader.initWithPath( url );
|
|
|
- loader.load( new Context( rootObj, function( obj ) {} ), null );
|
|
|
+ var loader = Object.create(ThreeGLTFLoader);
|
|
|
+ loader.initWithPath(url);
|
|
|
+ loader.load(new Context(rootObj,
|
|
|
+ function(obj) {
|
|
|
+ }),
|
|
|
+ null);
|
|
|
|
|
|
this.loader = loader;
|
|
|
this.callback = callback;
|
|
|
this.rootObj = rootObj;
|
|
|
return rootObj;
|
|
|
-
|
|
|
};
|
|
|
|
|
|
THREE.glTFLoader.prototype.callLoadedCallback = function() {
|
|
|
-
|
|
|
var result = {
|
|
|
- scene : this.rootObj,
|
|
|
- cameras : this.loader.cameras,
|
|
|
- animations : this.loader.animations,
|
|
|
+ scene : this.rootObj,
|
|
|
+ cameras : this.loader.cameras,
|
|
|
+ animations : this.loader.animations,
|
|
|
};
|
|
|
|
|
|
- this.callback( result );
|
|
|
-
|
|
|
+ this.callback(result);
|
|
|
};
|
|
|
|
|
|
THREE.glTFLoader.prototype.checkComplete = function() {
|
|
|
-
|
|
|
- if ( this.meshesLoaded == this.meshesRequested
|
|
|
+ if (this.meshesLoaded == this.meshesRequested
|
|
|
&& this.shadersLoaded == this.shadersRequested
|
|
|
- && this.animationsLoaded == this.animationsRequested )
|
|
|
+ && this.animationsLoaded == this.animationsRequested)
|
|
|
{
|
|
|
|
|
|
- for ( var i = 0; i < this.pendingMeshes.length; i ++ ) {
|
|
|
-
|
|
|
- var pending = this.pendingMeshes[ i ];
|
|
|
- pending.mesh.attachToNode( pending.node );
|
|
|
-
|
|
|
+ for (var i = 0; i < this.pendingMeshes.length; i ++) {
|
|
|
+ var pending = this.pendingMeshes[i];
|
|
|
+ pending.mesh.attachToNode(pending.node);
|
|
|
}
|
|
|
|
|
|
- for ( var i = 0; i < this.animationsLoaded; i ++ ) {
|
|
|
-
|
|
|
- var animation = this.animations[ i ];
|
|
|
- this.loader.buildAnimation( animation );
|
|
|
-
|
|
|
+ for (var i = 0; i < this.animationsLoaded; i ++) {
|
|
|
+ var animation = this.animations[i];
|
|
|
+ this.loader.buildAnimation(animation);
|
|
|
}
|
|
|
|
|
|
this.loader.createAnimations();
|
|
|
- this.loader.createMeshAnimations( this.rootObj );
|
|
|
+ this.loader.createMeshAnimations(this.rootObj);
|
|
|
|
|
|
this.callLoadedCallback();
|
|
|
-
|
|
|
}
|
|
|
-
|
|
|
};
|