1 line
15 KiB
Plaintext
1 line
15 KiB
Plaintext
|
|
{"version":3,"file":"BVHLoader.cjs","sources":["../../src/loaders/BVHLoader.js"],"sourcesContent":["import {\n AnimationClip,\n Bone,\n FileLoader,\n Loader,\n Quaternion,\n QuaternionKeyframeTrack,\n Skeleton,\n Vector3,\n VectorKeyframeTrack,\n} from 'three'\n\n/**\n * Description: reads BVH files and outputs a single Skeleton and an AnimationClip\n *\n * Currently only supports bvh files containing a single root.\n *\n */\n\nclass BVHLoader extends Loader {\n constructor(manager) {\n super(manager)\n\n this.animateBonePositions = true\n this.animateBoneRotations = true\n }\n\n load(url, onLoad, onProgress, onError) {\n const scope = this\n\n const loader = new FileLoader(scope.manager)\n loader.setPath(scope.path)\n loader.setRequestHeader(scope.requestHeader)\n loader.setWithCredentials(scope.withCredentials)\n loader.load(\n url,\n function (text) {\n try {\n onLoad(scope.parse(text))\n } catch (e) {\n if (onError) {\n onError(e)\n } else {\n console.error(e)\n }\n\n scope.manager.itemError(url)\n }\n },\n onProgress,\n onError,\n )\n }\n\n parse(text) {\n /*\n\t\t\treads a string array (lines) from a BVH file\n\t\t\tand outputs a skeleton structure including motion data\n\n\t\t\treturns thee root node:\n\t\t\t{ name: '', channels: [], children: [] }\n\t\t*/\n function readBvh(lines) {\n // read model structure\n\n if (nextLine(lines) !== 'HIERARCHY') {\n console.error('THREE.BVHLoader: HIERARCHY expected.')\n }\n\n const list = [] // collects flat array of all bones\n const root = readNode(lines, nextLine(lines), list)\n\n // read motion data\n\n if (nextLine(lines) !== 'MOTION') {\n console.error('THREE.BVHLoader: MOTION expected.')\n }\n\n // number of frames\n\n let tokens = nextLine(lines).split(/[\\s]+/)\n const numFrames = parseInt(tokens[1])\n\n if (isNaN(numFrames)) {\n console.error('THREE.BVHLoader: Failed to read number of frames.')\n }\n\n // frame time\n\n tokens = nextLine(lines).split(/[\\s]+/)\n const frameTime = parseFloat(tokens[2])\n\n if (isNaN(frameTime)) {\n console.error('THREE.BVHLoader: Failed to read frame time.')\n }\n\n // read frame data line by line\n\n for (let i = 0; i < numFrames; i++) {\n tokens = nextLine(lines).split(/[\\s]+/)\n readFrameData(tokens, i * frameTime, root)\n }\n\n return list\n }\n\n /*\n\t\t\tRecursively reads data from a single frame into the bone hierarchy.\n\t\t\tThe passed bone hierarchy has to be structured in the same order as the BVH file.\n\t\t\tkeyframe data is stored in bone.frames.\n\n\t\t\t- data: splitted string array (frame values), values are shift()ed so\n\t\t\tthis should be empty after parsing the whole hierarchy.\n\t\t\t- frameTime: playback time for this keyframe.\n\t\t\t- bone: the bone to read frame data from.\n\t\t*/\n function readFrameData(data, frameTime, bone) {\n // end sites have no motion data\n\n if (bone.type === 'ENDSITE') return\n\n // add keyframe\n\n const keyframe = {\n time: frameTime,\n position: new Vector3(),\n rotation: new Quaternion(),\n }\n\n bone.frames.push(keyframe)\n\n const quat = new Quaternion()\n\n const vx = new Vector3(1, 0, 0)\n const vy = new Vector3(0, 1, 0)\n const vz = new Vector3(0, 0, 1)\n\n // parse values for each channel in node\n\n for (let i = 0; i < bone.channels.length; i++) {\n switch (bone.channels[i]) {\n case 'Xposition':\n keyframe.position.x = parseFloat(data.shift().trim())\n break\n case 'Yposition':\n keyframe.position.y = parseFloat(data.shift().trim())\n break\n case 'Zposition':\n keyframe.position.z = parseFloat(data.shift().trim())\n break\n case 'Xrotation':\n quat.
|