Spaces:
Running
Running
| /** | |
| * Author: Pierre Lepers | |
| * Date: 09/12/2013 17:21 | |
| */ | |
| ( function () { | |
| var UNCOMPRESSED = 0, | |
| DEFLATE = 1, | |
| LZMA = 2, | |
| AWD_FIELD_INT8 = 1, | |
| AWD_FIELD_INT16 = 2, | |
| AWD_FIELD_INT32 = 3, | |
| AWD_FIELD_UINT8 = 4, | |
| AWD_FIELD_UINT16 = 5, | |
| AWD_FIELD_UINT32 = 6, | |
| AWD_FIELD_FLOAT32 = 7, | |
| AWD_FIELD_FLOAT64 = 8, | |
| AWD_FIELD_BOOL = 21, | |
| AWD_FIELD_COLOR = 22, | |
| AWD_FIELD_BADDR = 23, | |
| AWD_FIELD_STRING = 31, | |
| AWD_FIELD_BYTEARRAY = 32, | |
| AWD_FIELD_VECTOR2x1 = 41, | |
| AWD_FIELD_VECTOR3x1 = 42, | |
| AWD_FIELD_VECTOR4x1 = 43, | |
| AWD_FIELD_MTX3x2 = 44, | |
| AWD_FIELD_MTX3x3 = 45, | |
| AWD_FIELD_MTX4x3 = 46, | |
| AWD_FIELD_MTX4x4 = 47, | |
| BOOL = 21, | |
| COLOR = 22, | |
| BADDR = 23, | |
| INT8 = 1, | |
| INT16 = 2, | |
| INT32 = 3, | |
| UINT8 = 4, | |
| UINT16 = 5, | |
| UINT32 = 6, | |
| FLOAT32 = 7, | |
| FLOAT64 = 8; | |
| var littleEndian = true; | |
| function Block() { | |
| this.id = 0; | |
| this.data = null; | |
| } | |
| function AWDProperties() {} | |
| AWDProperties.prototype = { | |
| set: function ( key, value ) { | |
| this[ key ] = value; | |
| }, | |
| get: function ( key, fallback ) { | |
| if ( this.hasOwnProperty( key ) ) { | |
| return this[ key ]; | |
| } else { | |
| return fallback; | |
| } | |
| } | |
| }; | |
| THREE.AWDLoader = function ( manager ) { | |
| this.manager = ( manager !== undefined ) ? manager : THREE.DefaultLoadingManager; | |
| this.trunk = new THREE.Object3D(); | |
| this.materialFactory = undefined; | |
| this._url = ''; | |
| this._baseDir = ''; | |
| this._data = undefined; | |
| this._ptr = 0; | |
| this._version = []; | |
| this._streaming = false; | |
| this._optimized_for_accuracy = false; | |
| this._compression = 0; | |
| this._bodylen = 0xFFFFFFFF; | |
| this._blocks = [ new Block() ]; | |
| this._accuracyMatrix = false; | |
| this._accuracyGeo = false; | |
| this._accuracyProps = false; | |
| }; | |
| THREE.AWDLoader.prototype = { | |
| constructor: THREE.AWDLoader, | |
| load: function ( url, onLoad, onProgress, onError ) { | |
| var scope = this; | |
| this._url = url; | |
| this._baseDir = url.substr( 0, url.lastIndexOf( '/' ) + 1 ); | |
| var loader = new THREE.FileLoader( this.manager ); | |
| loader.setPath( this.path ); | |
| loader.setResponseType( 'arraybuffer' ); | |
| loader.load( url, function ( text ) { | |
| onLoad( scope.parse( text ) ); | |
| }, onProgress, onError ); | |
| }, | |
| setPath: function ( value ) { | |
| this.path = value; | |
| return this; | |
| }, | |
| parse: function ( data ) { | |
| var blen = data.byteLength; | |
| this._ptr = 0; | |
| this._data = new DataView( data ); | |
| this._parseHeader( ); | |
| if ( this._compression != 0 ) { | |
| console.error( 'compressed AWD not supported' ); | |
| } | |
| if ( ! this._streaming && this._bodylen != data.byteLength - this._ptr ) { | |
| console.error( 'AWDLoader: body len does not match file length', this._bodylen, blen - this._ptr ); | |
| } | |
| while ( this._ptr < blen ) { | |
| this.parseNextBlock(); | |
| } | |
| return this.trunk; | |
| }, | |
| parseNextBlock: function () { | |
| var assetData, | |
| ns, type, len, block, | |
| blockId = this.readU32(), | |
| ns = this.readU8(), | |
| type = this.readU8(), | |
| flags = this.readU8(), | |
| len = this.readU32(); | |
| switch ( type ) { | |
| case 1: | |
| assetData = this.parseMeshData( len ); | |
| break; | |
| case 22: | |
| assetData = this.parseContainer( len ); | |
| break; | |
| case 23: | |
| assetData = this.parseMeshInstance( len ); | |
| break; | |
| case 81: | |
| assetData = this.parseMaterial( len ); | |
| break; | |
| case 82: | |
| assetData = this.parseTexture( len ); | |
| break; | |
| case 101: | |
| assetData = this.parseSkeleton( len ); | |
| break; | |
| // case 111: | |
| // assetData = this.parseMeshPoseAnimation(len, true); | |
| // break; | |
| case 112: | |
| assetData = this.parseMeshPoseAnimation( len, false ); | |
| break; | |
| case 113: | |
| assetData = this.parseVertexAnimationSet( len ); | |
| break; | |
| case 102: | |
| assetData = this.parseSkeletonPose( len ); | |
| break; | |
| case 103: | |
| assetData = this.parseSkeletonAnimation( len ); | |
| break; | |
| case 122: | |
| assetData = this.parseAnimatorSet( len ); | |
| break; | |
| // case 121: | |
| // assetData = parseUVAnimation(len); | |
| // break; | |
| default: | |
| //debug('Ignoring block!',type, len); | |
| this._ptr += len; | |
| break; | |
| } | |
| // Store block reference for later use | |
| this._blocks[ blockId ] = block = new Block(); | |
| block.data = assetData; | |
| block.id = blockId; | |
| }, | |
| _parseHeader: function () { | |
| var version = this._version, | |
| awdmagic = ( this.readU8() << 16 ) | ( this.readU8() << 8 ) | this.readU8(); | |
| if ( awdmagic != 4282180 ) | |
| throw new Error( "AWDLoader - bad magic" ); | |
| version[ 0 ] = this.readU8(); | |
| version[ 1 ] = this.readU8(); | |
| var flags = this.readU16(); | |
| this._streaming = ( flags & 0x1 ) == 0x1; | |
| if ( ( version[ 0 ] === 2 ) && ( version[ 1 ] === 1 ) ) { | |
| this._accuracyMatrix = ( flags & 0x2 ) === 0x2; | |
| this._accuracyGeo = ( flags & 0x4 ) === 0x4; | |
| this._accuracyProps = ( flags & 0x8 ) === 0x8; | |
| } | |
| this._geoNrType = this._accuracyGeo ? FLOAT64 : FLOAT32; | |
| this._matrixNrType = this._accuracyMatrix ? FLOAT64 : FLOAT32; | |
| this._propsNrType = this._accuracyProps ? FLOAT64 : FLOAT32; | |
| this._optimized_for_accuracy = ( flags & 0x2 ) === 0x2; | |
| this._compression = this.readU8(); | |
| this._bodylen = this.readU32(); | |
| }, | |
| parseContainer: function ( len ) { | |
| var parent, | |
| ctr = new THREE.Object3D(), | |
| par_id = this.readU32(), | |
| mtx = this.parseMatrix4(); | |
| ctr.name = this.readUTF(); | |
| ctr.applyMatrix( mtx ); | |
| parent = this._blocks[ par_id ].data || this.trunk; | |
| parent.add( ctr ); | |
| this.parseProperties( { | |
| 1: this._matrixNrType, | |
| 2: this._matrixNrType, | |
| 3: this._matrixNrType, | |
| 4: UINT8 | |
| } ); | |
| ctr.extra = this.parseUserAttributes(); | |
| return ctr; | |
| }, | |
| parseMeshInstance: function ( len ) { | |
| var name, | |
| mesh, geometries, meshLen, meshes, | |
| par_id, data_id, | |
| mtx, | |
| materials, mat, mat_id, | |
| num_materials, | |
| parent, | |
| i; | |
| par_id = this.readU32(); | |
| mtx = this.parseMatrix4(); | |
| name = this.readUTF(); | |
| data_id = this.readU32(); | |
| num_materials = this.readU16(); | |
| geometries = this.getBlock( data_id ); | |
| materials = []; | |
| for ( i = 0; i < num_materials; i ++ ) { | |
| mat_id = this.readU32(); | |
| mat = this.getBlock( mat_id ); | |
| materials.push( mat ); | |
| } | |
| meshLen = geometries.length; | |
| meshes = []; | |
| // TODO : BufferGeometry don't support "geometryGroups" for now. | |
| // so we create sub meshes for each groups | |
| if ( meshLen > 1 ) { | |
| mesh = new THREE.Object3D(); | |
| for ( i = 0; i < meshLen; i ++ ) { | |
| var sm = new THREE.Mesh( geometries[ i ] ); | |
| meshes.push( sm ); | |
| mesh.add( sm ); | |
| } | |
| } else { | |
| mesh = new THREE.Mesh( geometries[ 0 ] ); | |
| meshes.push( mesh ); | |
| } | |
| mesh.applyMatrix( mtx ); | |
| mesh.name = name; | |
| parent = this.getBlock( par_id ) || this.trunk; | |
| parent.add( mesh ); | |
| var matLen = materials.length; | |
| var maxLen = Math.max( meshLen, matLen ); | |
| for ( i = 0; i < maxLen; i ++ ) | |
| meshes[ i % meshLen ].material = materials[ i % matLen ]; | |
| // Ignore for now | |
| this.parseProperties( null ); | |
| mesh.extra = this.parseUserAttributes(); | |
| return mesh; | |
| }, | |
| parseMaterial: function ( len ) { | |
| var name, | |
| type, | |
| props, | |
| mat, | |
| attributes, | |
| finalize, | |
| num_methods, | |
| methods_parsed; | |
| name = this.readUTF(); | |
| type = this.readU8(); | |
| num_methods = this.readU8(); | |
| //log( "AWDLoader parseMaterial ",name ) | |
| // Read material numerical properties | |
| // (1=color, 2=bitmap url, 11=alpha_blending, 12=alpha_threshold, 13=repeat) | |
| props = this.parseProperties( { | |
| 1: AWD_FIELD_INT32, | |
| 2: AWD_FIELD_BADDR, | |
| 11: AWD_FIELD_BOOL, | |
| 12: AWD_FIELD_FLOAT32, | |
| 13: AWD_FIELD_BOOL | |
| } ); | |
| methods_parsed = 0; | |
| while ( methods_parsed < num_methods ) { | |
| var method_type = this.readU16(); | |
| this.parseProperties( null ); | |
| this.parseUserAttributes(); | |
| } | |
| attributes = this.parseUserAttributes(); | |
| if ( this.materialFactory !== undefined ) { | |
| mat = this.materialFactory( name ); | |
| if ( mat ) return mat; | |
| } | |
| mat = new THREE.MeshPhongMaterial(); | |
| if ( type === 1 ) { | |
| // Color material | |
| mat.color.setHex( props.get( 1, 0xcccccc ) ); | |
| } else if ( type === 2 ) { | |
| // Bitmap material | |
| var tex_addr = props.get( 2, 0 ); | |
| mat.map = this.getBlock( tex_addr ); | |
| } | |
| mat.extra = attributes; | |
| mat.alphaThreshold = props.get( 12, 0.0 ); | |
| mat.repeat = props.get( 13, false ); | |
| return mat; | |
| }, | |
| parseTexture: function ( len ) { | |
| var name = this.readUTF(), | |
| type = this.readU8(), | |
| asset, | |
| data_len; | |
| // External | |
| if ( type === 0 ) { | |
| data_len = this.readU32(); | |
| var url = this.readUTFBytes( data_len ); | |
| console.log( url ); | |
| asset = this.loadTexture( url ); | |
| } else { | |
| // embed texture not supported | |
| } | |
| // Ignore for now | |
| this.parseProperties( null ); | |
| this.parseUserAttributes(); | |
| return asset; | |
| }, | |
| loadTexture: function ( url ) { | |
| var tex = new THREE.Texture(); | |
| var loader = new THREE.ImageLoader( this.manager ); | |
| loader.load( this._baseDir + url, function ( image ) { | |
| tex.image = image; | |
| tex.needsUpdate = true; | |
| } ); | |
| return tex; | |
| }, | |
| parseSkeleton: function ( len ) { | |
| // Array<Bone> | |
| var name = this.readUTF(), | |
| num_joints = this.readU16(), | |
| skeleton = [], | |
| joints_parsed = 0; | |
| this.parseProperties( null ); | |
| while ( joints_parsed < num_joints ) { | |
| var joint, ibp; | |
| // Ignore joint id | |
| this.readU16(); | |
| joint = new THREE.Bone(); | |
| joint.parent = this.readU16() - 1; // 0=null in AWD | |
| joint.name = this.readUTF(); | |
| ibp = this.parseMatrix4(); | |
| joint.skinMatrix = ibp; | |
| // Ignore joint props/attributes for now | |
| this.parseProperties( null ); | |
| this.parseUserAttributes(); | |
| skeleton.push( joint ); | |
| joints_parsed ++; | |
| } | |
| // Discard attributes for now | |
| this.parseUserAttributes(); | |
| return skeleton; | |
| }, | |
| parseSkeletonPose: function ( blockID ) { | |
| var name = this.readUTF(); | |
| var num_joints = this.readU16(); | |
| this.parseProperties( null ); | |
| // debug( 'parse Skeleton Pose. joints : ' + num_joints); | |
| var pose = []; | |
| var joints_parsed = 0; | |
| while ( joints_parsed < num_joints ) { | |
| var joint_pose; | |
| var has_transform; //:uint; | |
| var mtx_data; | |
| has_transform = this.readU8(); | |
| if ( has_transform === 1 ) { | |
| mtx_data = this.parseMatrix4(); | |
| } else { | |
| mtx_data = new THREE.Matrix4(); | |
| } | |
| pose[ joints_parsed ] = mtx_data; | |
| joints_parsed ++; | |
| } | |
| // Skip attributes for now | |
| this.parseUserAttributes(); | |
| return pose; | |
| }, | |
| parseSkeletonAnimation: function ( blockID ) { | |
| var frame_dur; | |
| var pose_addr; | |
| var pose; | |
| var name = this.readUTF(); | |
| var clip = []; | |
| var num_frames = this.readU16(); | |
| this.parseProperties( null ); | |
| var frames_parsed = 0; | |
| var returnedArray; | |
| // debug( 'parse Skeleton Animation. frames : ' + num_frames); | |
| while ( frames_parsed < num_frames ) { | |
| pose_addr = this.readU32(); | |
| frame_dur = this.readU16(); | |
| pose = this._blocks[ pose_addr ].data; | |
| // debug( 'pose address ',pose[2].elements[12],pose[2].elements[13],pose[2].elements[14] ); | |
| clip.push( { | |
| pose: pose, | |
| duration: frame_dur | |
| } ); | |
| frames_parsed ++; | |
| } | |
| if ( clip.length === 0 ) { | |
| // debug("Could not this SkeletonClipNode, because no Frames where set."); | |
| return; | |
| } | |
| // Ignore attributes for now | |
| this.parseUserAttributes(); | |
| return clip; | |
| }, | |
| parseVertexAnimationSet: function ( len ) { | |
| var poseBlockAdress, | |
| name = this.readUTF(), | |
| num_frames = this.readU16(), | |
| props = this.parseProperties( { 1: UINT16 } ), | |
| frames_parsed = 0, | |
| skeletonFrames = []; | |
| while ( frames_parsed < num_frames ) { | |
| poseBlockAdress = this.readU32(); | |
| skeletonFrames.push( this._blocks[ poseBlockAdress ].data ); | |
| frames_parsed ++; | |
| } | |
| this.parseUserAttributes(); | |
| return skeletonFrames; | |
| }, | |
| parseAnimatorSet: function ( len ) { | |
| var targetMesh; | |
| var animSetBlockAdress; //:int | |
| var targetAnimationSet; //:AnimationSetBase; | |
| var outputString = ""; //:String = ""; | |
| var name = this.readUTF(); | |
| var type = this.readU16(); | |
| var props = this.parseProperties( { 1: BADDR } ); | |
| animSetBlockAdress = this.readU32(); | |
| var targetMeshLength = this.readU16(); | |
| var meshAdresses = []; //:Vector.<uint> = new Vector.<uint>; | |
| for ( var i = 0; i < targetMeshLength; i ++ ) | |
| meshAdresses.push( this.readU32() ); | |
| var activeState = this.readU16(); | |
| var autoplay = Boolean( this.readU8() ); | |
| this.parseUserAttributes(); | |
| this.parseUserAttributes(); | |
| var returnedArray; | |
| var targetMeshes = []; //:Vector.<Mesh> = new Vector.<Mesh>; | |
| for ( i = 0; i < meshAdresses.length; i ++ ) { | |
| // returnedArray = getAssetByID(meshAdresses[i], [AssetType.MESH]); | |
| // if (returnedArray[0]) | |
| targetMeshes.push( this._blocks[ meshAdresses[ i ] ].data ); | |
| } | |
| targetAnimationSet = this._blocks[ animSetBlockAdress ].data; | |
| var thisAnimator; | |
| if ( type == 1 ) { | |
| thisAnimator = { | |
| animationSet: targetAnimationSet, | |
| skeleton: this._blocks[ props.get( 1, 0 ) ].data | |
| }; | |
| } else if ( type == 2 ) { | |
| // debug( "vertex Anim???"); | |
| } | |
| for ( i = 0; i < targetMeshes.length; i ++ ) { | |
| targetMeshes[ i ].animator = thisAnimator; | |
| } | |
| // debug("Parsed a Animator: Name = " + name); | |
| return thisAnimator; | |
| }, | |
| parseMeshData: function ( len ) { | |
| var name = this.readUTF(), | |
| num_subs = this.readU16(), | |
| geom, | |
| subs_parsed = 0, | |
| buffer, | |
| skinW, skinI, | |
| geometries = []; | |
| // Ignore for now | |
| this.parseProperties( { 1: this._geoNrType, 2: this._geoNrType } ); | |
| // Loop through sub meshes | |
| while ( subs_parsed < num_subs ) { | |
| var sm_len, sm_end, attrib; | |
| geom = new THREE.BufferGeometry(); | |
| geom.name = name; | |
| geometries.push( geom ); | |
| sm_len = this.readU32(); | |
| sm_end = this._ptr + sm_len; | |
| // Ignore for now | |
| this.parseProperties( { 1: this._geoNrType, 2: this._geoNrType } ); | |
| // Loop through data streams | |
| while ( this._ptr < sm_end ) { | |
| var idx = 0, | |
| str_type = this.readU8(), | |
| str_ftype = this.readU8(), | |
| str_len = this.readU32(), | |
| str_end = str_len + this._ptr; | |
| if ( str_type === 1 ) { | |
| // VERTICES | |
| buffer = new Float32Array( ( str_len / 12 ) * 3 ); | |
| attrib = new THREE.BufferAttribute( buffer, 3 ); | |
| geom.addAttribute( 'position', attrib ); | |
| idx = 0; | |
| while ( this._ptr < str_end ) { | |
| buffer[ idx ] = - this.readF32(); | |
| buffer[ idx + 1 ] = this.readF32(); | |
| buffer[ idx + 2 ] = this.readF32(); | |
| idx += 3; | |
| } | |
| } else if ( str_type === 2 ) { | |
| // INDICES | |
| buffer = new Uint16Array( str_len / 2 ); | |
| attrib = new THREE.BufferAttribute( buffer, 1 ); | |
| geom.setIndex( attrib ); | |
| idx = 0; | |
| while ( this._ptr < str_end ) { | |
| buffer[ idx + 1 ] = this.readU16(); | |
| buffer[ idx ] = this.readU16(); | |
| buffer[ idx + 2 ] = this.readU16(); | |
| idx += 3; | |
| } | |
| } else if ( str_type === 3 ) { | |
| // UVS | |
| buffer = new Float32Array( ( str_len / 8 ) * 2 ); | |
| attrib = new THREE.BufferAttribute( buffer, 2 ); | |
| geom.addAttribute( 'uv', attrib ); | |
| idx = 0; | |
| while ( this._ptr < str_end ) { | |
| buffer[ idx ] = this.readF32(); | |
| buffer[ idx + 1 ] = 1.0 - this.readF32(); | |
| idx += 2; | |
| } | |
| } else if ( str_type === 4 ) { | |
| // NORMALS | |
| buffer = new Float32Array( ( str_len / 12 ) * 3 ); | |
| attrib = new THREE.BufferAttribute( buffer, 3 ); | |
| geom.addAttribute( 'normal', attrib ); | |
| idx = 0; | |
| while ( this._ptr < str_end ) { | |
| buffer[ idx ] = - this.readF32(); | |
| buffer[ idx + 1 ] = this.readF32(); | |
| buffer[ idx + 2 ] = this.readF32(); | |
| idx += 3; | |
| } | |
| } else { | |
| this._ptr = str_end; | |
| } | |
| } | |
| this.parseUserAttributes(); | |
| geom.computeBoundingSphere(); | |
| subs_parsed ++; | |
| } | |
| //geom.computeFaceNormals(); | |
| this.parseUserAttributes(); | |
| //finalizeAsset(geom, name); | |
| return geometries; | |
| }, | |
| parseMeshPoseAnimation: function ( len, poseOnly ) { | |
| var num_frames = 1, | |
| num_submeshes, | |
| frames_parsed, | |
| subMeshParsed, | |
| frame_dur, | |
| x, y, z, | |
| str_len, | |
| str_end, | |
| geom, | |
| subGeom, | |
| idx = 0, | |
| clip = {}, | |
| indices, | |
| verts, | |
| num_Streams, | |
| streamsParsed, | |
| streamtypes = [], | |
| props, | |
| thisGeo, | |
| name = this.readUTF(), | |
| geoAdress = this.readU32(); | |
| var mesh = this.getBlock( geoAdress ); | |
| if ( mesh === null ) { | |
| console.log( "parseMeshPoseAnimation target mesh not found at:", geoAdress ); | |
| return; | |
| } | |
| geom = mesh.geometry; | |
| geom.morphTargets = []; | |
| if ( ! poseOnly ) | |
| num_frames = this.readU16(); | |
| num_submeshes = this.readU16(); | |
| num_Streams = this.readU16(); | |
| // debug("VA num_frames : ", num_frames ); | |
| // debug("VA num_submeshes : ", num_submeshes ); | |
| // debug("VA numstreams : ", num_Streams ); | |
| streamsParsed = 0; | |
| while ( streamsParsed < num_Streams ) { | |
| streamtypes.push( this.readU16() ); | |
| streamsParsed ++; | |
| } | |
| props = this.parseProperties( { 1: BOOL, 2: BOOL } ); | |
| clip.looping = props.get( 1, true ); | |
| clip.stitchFinalFrame = props.get( 2, false ); | |
| frames_parsed = 0; | |
| while ( frames_parsed < num_frames ) { | |
| frame_dur = this.readU16(); | |
| subMeshParsed = 0; | |
| while ( subMeshParsed < num_submeshes ) { | |
| streamsParsed = 0; | |
| str_len = this.readU32(); | |
| str_end = this._ptr + str_len; | |
| while ( streamsParsed < num_Streams ) { | |
| if ( streamtypes[ streamsParsed ] === 1 ) { | |
| //geom.addAttribute( 'morphTarget'+frames_parsed, Float32Array, str_len/12, 3 ); | |
| var buffer = new Float32Array( str_len / 4 ); | |
| geom.morphTargets.push( { | |
| array: buffer | |
| } ); | |
| //buffer = geom.attributes['morphTarget'+frames_parsed].array | |
| idx = 0; | |
| while ( this._ptr < str_end ) { | |
| buffer[ idx ] = this.readF32(); | |
| buffer[ idx + 1 ] = this.readF32(); | |
| buffer[ idx + 2 ] = this.readF32(); | |
| idx += 3; | |
| } | |
| subMeshParsed ++; | |
| } else | |
| this._ptr = str_end; | |
| streamsParsed ++; | |
| } | |
| } | |
| frames_parsed ++; | |
| } | |
| this.parseUserAttributes(); | |
| return null; | |
| }, | |
| getBlock: function ( id ) { | |
| return this._blocks[ id ].data; | |
| }, | |
| parseMatrix4: function () { | |
| var mtx = new THREE.Matrix4(); | |
| var e = mtx.elements; | |
| e[ 0 ] = this.readF32(); | |
| e[ 1 ] = this.readF32(); | |
| e[ 2 ] = this.readF32(); | |
| e[ 3 ] = 0.0; | |
| //e[3] = 0.0; | |
| e[ 4 ] = this.readF32(); | |
| e[ 5 ] = this.readF32(); | |
| e[ 6 ] = this.readF32(); | |
| //e[7] = this.readF32(); | |
| e[ 7 ] = 0.0; | |
| e[ 8 ] = this.readF32(); | |
| e[ 9 ] = this.readF32(); | |
| e[ 10 ] = this.readF32(); | |
| //e[11] = this.readF32(); | |
| e[ 11 ] = 0.0; | |
| e[ 12 ] = - this.readF32(); | |
| e[ 13 ] = this.readF32(); | |
| e[ 14 ] = this.readF32(); | |
| //e[15] = this.readF32(); | |
| e[ 15 ] = 1.0; | |
| return mtx; | |
| }, | |
| parseProperties: function ( expected ) { | |
| var list_len = this.readU32(); | |
| var list_end = this._ptr + list_len; | |
| var props = new AWDProperties(); | |
| if ( expected ) { | |
| while ( this._ptr < list_end ) { | |
| var key = this.readU16(); | |
| var len = this.readU32(); | |
| var type; | |
| if ( expected.hasOwnProperty( key ) ) { | |
| type = expected[ key ]; | |
| props.set( key, this.parseAttrValue( type, len ) ); | |
| } else { | |
| this._ptr += len; | |
| } | |
| } | |
| } | |
| return props; | |
| }, | |
| parseUserAttributes: function () { | |
| // skip for now | |
| this._ptr = this.readU32() + this._ptr; | |
| return null; | |
| }, | |
| parseAttrValue: function ( type, len ) { | |
| var elem_len; | |
| var read_func; | |
| switch ( type ) { | |
| case AWD_FIELD_INT8: | |
| elem_len = 1; | |
| read_func = this.readI8; | |
| break; | |
| case AWD_FIELD_INT16: | |
| elem_len = 2; | |
| read_func = this.readI16; | |
| break; | |
| case AWD_FIELD_INT32: | |
| elem_len = 4; | |
| read_func = this.readI32; | |
| break; | |
| case AWD_FIELD_BOOL: | |
| case AWD_FIELD_UINT8: | |
| elem_len = 1; | |
| read_func = this.readU8; | |
| break; | |
| case AWD_FIELD_UINT16: | |
| elem_len = 2; | |
| read_func = this.readU16; | |
| break; | |
| case AWD_FIELD_UINT32: | |
| case AWD_FIELD_BADDR: | |
| elem_len = 4; | |
| read_func = this.readU32; | |
| break; | |
| case AWD_FIELD_FLOAT32: | |
| elem_len = 4; | |
| read_func = this.readF32; | |
| break; | |
| case AWD_FIELD_FLOAT64: | |
| elem_len = 8; | |
| read_func = this.readF64; | |
| break; | |
| case AWD_FIELD_VECTOR2x1: | |
| case AWD_FIELD_VECTOR3x1: | |
| case AWD_FIELD_VECTOR4x1: | |
| case AWD_FIELD_MTX3x2: | |
| case AWD_FIELD_MTX3x3: | |
| case AWD_FIELD_MTX4x3: | |
| case AWD_FIELD_MTX4x4: | |
| elem_len = 8; | |
| read_func = this.readF64; | |
| break; | |
| } | |
| if ( elem_len < len ) { | |
| var list; | |
| var num_read; | |
| var num_elems; | |
| list = []; | |
| num_read = 0; | |
| num_elems = len / elem_len; | |
| while ( num_read < num_elems ) { | |
| list.push( read_func.call( this ) ); | |
| num_read ++; | |
| } | |
| return list; | |
| } else { | |
| return read_func.call( this ); | |
| } | |
| }, | |
| readU8: function () { | |
| return this._data.getUint8( this._ptr ++ ); | |
| }, | |
| readI8: function () { | |
| return this._data.getInt8( this._ptr ++ ); | |
| }, | |
| readU16: function () { | |
| var a = this._data.getUint16( this._ptr, littleEndian ); | |
| this._ptr += 2; | |
| return a; | |
| }, | |
| readI16: function () { | |
| var a = this._data.getInt16( this._ptr, littleEndian ); | |
| this._ptr += 2; | |
| return a; | |
| }, | |
| readU32: function () { | |
| var a = this._data.getUint32( this._ptr, littleEndian ); | |
| this._ptr += 4; | |
| return a; | |
| }, | |
| readI32: function () { | |
| var a = this._data.getInt32( this._ptr, littleEndian ); | |
| this._ptr += 4; | |
| return a; | |
| }, | |
| readF32: function () { | |
| var a = this._data.getFloat32( this._ptr, littleEndian ); | |
| this._ptr += 4; | |
| return a; | |
| }, | |
| readF64: function () { | |
| var a = this._data.getFloat64( this._ptr, littleEndian ); | |
| this._ptr += 8; | |
| return a; | |
| }, | |
| /** | |
| * Converts a UTF-8 byte array to JavaScript's 16-bit Unicode. | |
| * @param {Array.<number>} bytes UTF-8 byte array. | |
| * @return {string} 16-bit Unicode string. | |
| */ | |
| readUTF: function () { | |
| var len = this.readU16(); | |
| return this.readUTFBytes( len ); | |
| }, | |
| /** | |
| * Converts a UTF-8 byte array to JavaScript's 16-bit Unicode. | |
| * @param {Array.<number>} bytes UTF-8 byte array. | |
| * @return {string} 16-bit Unicode string. | |
| */ | |
| readUTFBytes: function ( len ) { | |
| // TODO(user): Use native implementations if/when available | |
| var out = [], c = 0; | |
| while ( out.length < len ) { | |
| var c1 = this._data.getUint8( this._ptr ++, littleEndian ); | |
| if ( c1 < 128 ) { | |
| out[ c ++ ] = String.fromCharCode( c1 ); | |
| } else if ( c1 > 191 && c1 < 224 ) { | |
| var c2 = this._data.getUint8( this._ptr ++, littleEndian ); | |
| out[ c ++ ] = String.fromCharCode( ( c1 & 31 ) << 6 | c2 & 63 ); | |
| } else { | |
| var c2 = this._data.getUint8( this._ptr ++, littleEndian ); | |
| var c3 = this._data.getUint8( this._ptr ++, littleEndian ); | |
| out[ c ++ ] = String.fromCharCode( ( c1 & 15 ) << 12 | ( c2 & 63 ) << 6 | c3 & 63 ); | |
| } | |
| } | |
| return out.join( '' ); | |
| } | |
| }; | |
| } )(); | |