UNPKG

playcanvas

Version:

Open-source WebGL/WebGPU 3D engine for the web

118 lines (117 loc) 3.63 kB
import { path } from "../../core/path.js"; import { Quat } from "../../core/math/quat.js"; import { Vec3 } from "../../core/math/vec3.js"; import { http, Http } from "../../platform/net/http.js"; import { Animation, AnimationKey, AnimationNode } from "../../scene/animation/animation.js"; import { AnimEvents } from "../anim/evaluator/anim-events.js"; import { GlbParser } from "../parsers/glb-parser.js"; import { ResourceHandler } from "./handler.js"; class AnimationHandler extends ResourceHandler { constructor(app) { super(app, "animation"); this.device = app.graphicsDevice; this.assets = app.assets; } load(url, callback, asset) { if (typeof url === "string") { url = { load: url, original: url }; } const options = { retry: this.maxRetries > 0, maxRetries: this.maxRetries }; if (url.load.startsWith("blob:") || url.load.startsWith("data:")) { if (path.getExtension(url.original).toLowerCase() === ".glb") { options.responseType = Http.ResponseType.ARRAY_BUFFER; } else { options.responseType = Http.ResponseType.JSON; } } http.get(url.load, options, (err, response) => { if (err) { callback(`Error loading animation resource: ${url.original} [${err}]`); } else { if (path.getExtension(url.original).toLowerCase() === ".glb") { GlbParser.parse("filename.glb", "", response, this.device, this.assets, asset?.options ?? {}, (err2, parseResult) => { if (err2) { callback(err2); } else { const animations = parseResult.animations; if (asset?.data?.events) { for (let i = 0; i < animations.length; i++) { animations[i].events = new AnimEvents(Object.values(asset.data.events)); } } parseResult.destroy(); callback(null, animations); } }); } else { callback(null, this[`_parseAnimationV${response.animation.version}`](response)); } } }); } open(url, data, asset) { return data; } _parseAnimationV3(data) { const animData = data.animation; const anim = new Animation(); anim.name = animData.name; anim.duration = animData.duration; for (let i = 0; i < animData.nodes.length; i++) { const node = new AnimationNode(); const n = animData.nodes[i]; node._name = n.name; for (let j = 0; j < n.keys.length; j++) { const k = n.keys[j]; const t = k.time; const p = k.pos; const r = k.rot; const s = k.scale; const pos = new Vec3(p[0], p[1], p[2]); const rot = new Quat().setFromEulerAngles(r[0], r[1], r[2]); const scl = new Vec3(s[0], s[1], s[2]); const key = new AnimationKey(t, pos, rot, scl); node._keys.push(key); } anim.addNode(node); } return anim; } _parseAnimationV4(data) { const animData = data.animation; const anim = new Animation(); anim.name = animData.name; anim.duration = animData.duration; for (let i = 0; i < animData.nodes.length; i++) { const node = new AnimationNode(); const n = animData.nodes[i]; node._name = n.name; const defPos = n.defaults.p; const defRot = n.defaults.r; const defScl = n.defaults.s; for (let j = 0; j < n.keys.length; j++) { const k = n.keys[j]; const t = k.t; const p = defPos ? defPos : k.p; const r = defRot ? defRot : k.r; const s = defScl ? defScl : k.s; const pos = new Vec3(p[0], p[1], p[2]); const rot = new Quat().setFromEulerAngles(r[0], r[1], r[2]); const scl = new Vec3(s[0], s[1], s[2]); const key = new AnimationKey(t, pos, rot, scl); node._keys.push(key); } anim.addNode(node); } return anim; } } export { AnimationHandler };