glTFLoader.js 70 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812
  1. import { EParameterType, ETextureFilterType, ECullingType, EBlendingFunction, EShaderType } from "./glTFLoaderInterfaces.js";
  2. import { Quaternion, Vector3, Matrix } from "@babylonjs/core/Maths/math.vector.js";
  3. import { Color3 } from "@babylonjs/core/Maths/math.color.js";
  4. import { Tools } from "@babylonjs/core/Misc/tools.js";
  5. import { Camera } from "@babylonjs/core/Cameras/camera.js";
  6. import { FreeCamera } from "@babylonjs/core/Cameras/freeCamera.js";
  7. import { Animation } from "@babylonjs/core/Animations/animation.js";
  8. import { Bone } from "@babylonjs/core/Bones/bone.js";
  9. import { Skeleton } from "@babylonjs/core/Bones/skeleton.js";
  10. import { Effect } from "@babylonjs/core/Materials/effect.js";
  11. import { Material } from "@babylonjs/core/Materials/material.js";
  12. import { MultiMaterial } from "@babylonjs/core/Materials/multiMaterial.js";
  13. import { StandardMaterial } from "@babylonjs/core/Materials/standardMaterial.js";
  14. import { ShaderMaterial } from "@babylonjs/core/Materials/shaderMaterial.js";
  15. import { Texture } from "@babylonjs/core/Materials/Textures/texture.js";
  16. import { VertexData } from "@babylonjs/core/Meshes/mesh.vertexData.js";
  17. import { VertexBuffer } from "@babylonjs/core/Buffers/buffer.js";
  18. import { Geometry } from "@babylonjs/core/Meshes/geometry.js";
  19. import { SubMesh } from "@babylonjs/core/Meshes/subMesh.js";
  20. import { AbstractMesh } from "@babylonjs/core/Meshes/abstractMesh.js";
  21. import { Mesh } from "@babylonjs/core/Meshes/mesh.js";
  22. import { HemisphericLight } from "@babylonjs/core/Lights/hemisphericLight.js";
  23. import { DirectionalLight } from "@babylonjs/core/Lights/directionalLight.js";
  24. import { PointLight } from "@babylonjs/core/Lights/pointLight.js";
  25. import { SpotLight } from "@babylonjs/core/Lights/spotLight.js";
  26. import { GLTFUtils } from "./glTFLoaderUtils.js";
  27. import { GLTFFileLoader } from "../glTFFileLoader.js";
  28. import { Constants } from "@babylonjs/core/Engines/constants.js";
  29. /**
  30. * Tokenizer. Used for shaders compatibility
  31. * Automatically map world, view, projection, worldViewProjection, attributes and so on
  32. */
  33. var ETokenType;
  34. (function (ETokenType) {
  35. ETokenType[ETokenType["IDENTIFIER"] = 1] = "IDENTIFIER";
  36. ETokenType[ETokenType["UNKNOWN"] = 2] = "UNKNOWN";
  37. ETokenType[ETokenType["END_OF_INPUT"] = 3] = "END_OF_INPUT";
  38. })(ETokenType || (ETokenType = {}));
  39. class Tokenizer {
  40. constructor(toParse) {
  41. this._pos = 0;
  42. this.currentToken = ETokenType.UNKNOWN;
  43. this.currentIdentifier = "";
  44. this.currentString = "";
  45. this.isLetterOrDigitPattern = /^[a-zA-Z0-9]+$/;
  46. this._toParse = toParse;
  47. this._maxPos = toParse.length;
  48. }
  49. getNextToken() {
  50. if (this.isEnd()) {
  51. return ETokenType.END_OF_INPUT;
  52. }
  53. this.currentString = this.read();
  54. this.currentToken = ETokenType.UNKNOWN;
  55. if (this.currentString === "_" || this.isLetterOrDigitPattern.test(this.currentString)) {
  56. this.currentToken = ETokenType.IDENTIFIER;
  57. this.currentIdentifier = this.currentString;
  58. while (!this.isEnd() && (this.isLetterOrDigitPattern.test((this.currentString = this.peek())) || this.currentString === "_")) {
  59. this.currentIdentifier += this.currentString;
  60. this.forward();
  61. }
  62. }
  63. return this.currentToken;
  64. }
  65. peek() {
  66. return this._toParse[this._pos];
  67. }
  68. read() {
  69. return this._toParse[this._pos++];
  70. }
  71. forward() {
  72. this._pos++;
  73. }
  74. isEnd() {
  75. return this._pos >= this._maxPos;
  76. }
  77. }
  78. /**
  79. * Values
  80. */
  81. const glTFTransforms = ["MODEL", "VIEW", "PROJECTION", "MODELVIEW", "MODELVIEWPROJECTION", "JOINTMATRIX"];
  82. const babylonTransforms = ["world", "view", "projection", "worldView", "worldViewProjection", "mBones"];
  83. const glTFAnimationPaths = ["translation", "rotation", "scale"];
  84. const babylonAnimationPaths = ["position", "rotationQuaternion", "scaling"];
  85. /**
  86. * Parse
  87. * @param parsedBuffers
  88. * @param gltfRuntime
  89. */
  90. const parseBuffers = (parsedBuffers, gltfRuntime) => {
  91. for (const buf in parsedBuffers) {
  92. const parsedBuffer = parsedBuffers[buf];
  93. gltfRuntime.buffers[buf] = parsedBuffer;
  94. gltfRuntime.buffersCount++;
  95. }
  96. };
  97. const parseShaders = (parsedShaders, gltfRuntime) => {
  98. for (const sha in parsedShaders) {
  99. const parsedShader = parsedShaders[sha];
  100. gltfRuntime.shaders[sha] = parsedShader;
  101. gltfRuntime.shaderscount++;
  102. }
  103. };
  104. const parseObject = (parsedObjects, runtimeProperty, gltfRuntime) => {
  105. for (const object in parsedObjects) {
  106. const parsedObject = parsedObjects[object];
  107. gltfRuntime[runtimeProperty][object] = parsedObject;
  108. }
  109. };
  110. /**
  111. * Utils
  112. * @param buffer
  113. */
  114. const normalizeUVs = (buffer) => {
  115. if (!buffer) {
  116. return;
  117. }
  118. for (let i = 0; i < buffer.length / 2; i++) {
  119. buffer[i * 2 + 1] = 1.0 - buffer[i * 2 + 1];
  120. }
  121. };
  122. const getAttribute = (attributeParameter) => {
  123. if (attributeParameter.semantic === "NORMAL") {
  124. return "normal";
  125. }
  126. else if (attributeParameter.semantic === "POSITION") {
  127. return "position";
  128. }
  129. else if (attributeParameter.semantic === "JOINT") {
  130. return "matricesIndices";
  131. }
  132. else if (attributeParameter.semantic === "WEIGHT") {
  133. return "matricesWeights";
  134. }
  135. else if (attributeParameter.semantic === "COLOR") {
  136. return "color";
  137. }
  138. else if (attributeParameter.semantic && attributeParameter.semantic.indexOf("TEXCOORD_") !== -1) {
  139. const channel = Number(attributeParameter.semantic.split("_")[1]);
  140. return "uv" + (channel === 0 ? "" : channel + 1);
  141. }
  142. return null;
  143. };
  144. /**
  145. * Loads and creates animations
  146. * @param gltfRuntime
  147. */
  148. const loadAnimations = (gltfRuntime) => {
  149. for (const anim in gltfRuntime.animations) {
  150. const animation = gltfRuntime.animations[anim];
  151. if (!animation.channels || !animation.samplers) {
  152. continue;
  153. }
  154. let lastAnimation = null;
  155. for (let i = 0; i < animation.channels.length; i++) {
  156. // Get parameters and load buffers
  157. const channel = animation.channels[i];
  158. const sampler = animation.samplers[channel.sampler];
  159. if (!sampler) {
  160. continue;
  161. }
  162. let inputData = null;
  163. let outputData = null;
  164. if (animation.parameters) {
  165. inputData = animation.parameters[sampler.input];
  166. outputData = animation.parameters[sampler.output];
  167. }
  168. else {
  169. inputData = sampler.input;
  170. outputData = sampler.output;
  171. }
  172. const bufferInput = GLTFUtils.GetBufferFromAccessor(gltfRuntime, gltfRuntime.accessors[inputData]);
  173. const bufferOutput = GLTFUtils.GetBufferFromAccessor(gltfRuntime, gltfRuntime.accessors[outputData]);
  174. const targetId = channel.target.id;
  175. let targetNode = gltfRuntime.scene.getNodeById(targetId);
  176. if (targetNode === null) {
  177. targetNode = gltfRuntime.scene.getNodeByName(targetId);
  178. }
  179. if (targetNode === null) {
  180. Tools.Warn("Creating animation named " + anim + ". But cannot find node named " + targetId + " to attach to");
  181. continue;
  182. }
  183. const isBone = targetNode instanceof Bone;
  184. // Get target path (position, rotation or scaling)
  185. let targetPath = channel.target.path;
  186. const targetPathIndex = glTFAnimationPaths.indexOf(targetPath);
  187. if (targetPathIndex !== -1) {
  188. targetPath = babylonAnimationPaths[targetPathIndex];
  189. }
  190. // Determine animation type
  191. let animationType = Animation.ANIMATIONTYPE_MATRIX;
  192. if (!isBone) {
  193. if (targetPath === "rotationQuaternion") {
  194. animationType = Animation.ANIMATIONTYPE_QUATERNION;
  195. targetNode.rotationQuaternion = new Quaternion();
  196. }
  197. else {
  198. animationType = Animation.ANIMATIONTYPE_VECTOR3;
  199. }
  200. }
  201. // Create animation and key frames
  202. let babylonAnimation = null;
  203. const keys = [];
  204. let arrayOffset = 0;
  205. let modifyKey = false;
  206. if (isBone && lastAnimation && lastAnimation.getKeys().length === bufferInput.length) {
  207. babylonAnimation = lastAnimation;
  208. modifyKey = true;
  209. }
  210. if (!modifyKey) {
  211. gltfRuntime.scene._blockEntityCollection = !!gltfRuntime.assetContainer;
  212. babylonAnimation = new Animation(anim, isBone ? "_matrix" : targetPath, 1, animationType, Animation.ANIMATIONLOOPMODE_CYCLE);
  213. gltfRuntime.scene._blockEntityCollection = false;
  214. }
  215. // For each frame
  216. for (let j = 0; j < bufferInput.length; j++) {
  217. let value = null;
  218. if (targetPath === "rotationQuaternion") {
  219. // VEC4
  220. value = Quaternion.FromArray([bufferOutput[arrayOffset], bufferOutput[arrayOffset + 1], bufferOutput[arrayOffset + 2], bufferOutput[arrayOffset + 3]]);
  221. arrayOffset += 4;
  222. }
  223. else {
  224. // Position and scaling are VEC3
  225. value = Vector3.FromArray([bufferOutput[arrayOffset], bufferOutput[arrayOffset + 1], bufferOutput[arrayOffset + 2]]);
  226. arrayOffset += 3;
  227. }
  228. if (isBone) {
  229. const bone = targetNode;
  230. let translation = Vector3.Zero();
  231. let rotationQuaternion = new Quaternion();
  232. let scaling = Vector3.Zero();
  233. // Warning on decompose
  234. let mat = bone.getBaseMatrix();
  235. if (modifyKey && lastAnimation) {
  236. mat = lastAnimation.getKeys()[j].value;
  237. }
  238. mat.decompose(scaling, rotationQuaternion, translation);
  239. if (targetPath === "position") {
  240. translation = value;
  241. }
  242. else if (targetPath === "rotationQuaternion") {
  243. rotationQuaternion = value;
  244. }
  245. else {
  246. scaling = value;
  247. }
  248. value = Matrix.Compose(scaling, rotationQuaternion, translation);
  249. }
  250. if (!modifyKey) {
  251. keys.push({
  252. frame: bufferInput[j],
  253. value: value,
  254. });
  255. }
  256. else if (lastAnimation) {
  257. lastAnimation.getKeys()[j].value = value;
  258. }
  259. }
  260. // Finish
  261. if (!modifyKey && babylonAnimation) {
  262. babylonAnimation.setKeys(keys);
  263. targetNode.animations.push(babylonAnimation);
  264. }
  265. lastAnimation = babylonAnimation;
  266. gltfRuntime.scene.stopAnimation(targetNode);
  267. gltfRuntime.scene.beginAnimation(targetNode, 0, bufferInput[bufferInput.length - 1], true, 1.0);
  268. }
  269. }
  270. };
  271. /**
  272. * @returns the bones transformation matrix
  273. * @param node
  274. */
  275. const configureBoneTransformation = (node) => {
  276. let mat = null;
  277. if (node.translation || node.rotation || node.scale) {
  278. const scale = Vector3.FromArray(node.scale || [1, 1, 1]);
  279. const rotation = Quaternion.FromArray(node.rotation || [0, 0, 0, 1]);
  280. const position = Vector3.FromArray(node.translation || [0, 0, 0]);
  281. mat = Matrix.Compose(scale, rotation, position);
  282. }
  283. else {
  284. mat = Matrix.FromArray(node.matrix);
  285. }
  286. return mat;
  287. };
  288. /**
  289. * Returns the parent bone
  290. * @param gltfRuntime
  291. * @param skins
  292. * @param jointName
  293. * @param newSkeleton
  294. * @returns the parent bone
  295. */
  296. const getParentBone = (gltfRuntime, skins, jointName, newSkeleton) => {
  297. // Try to find
  298. for (let i = 0; i < newSkeleton.bones.length; i++) {
  299. if (newSkeleton.bones[i].name === jointName) {
  300. return newSkeleton.bones[i];
  301. }
  302. }
  303. // Not found, search in gltf nodes
  304. const nodes = gltfRuntime.nodes;
  305. for (const nde in nodes) {
  306. const node = nodes[nde];
  307. if (!node.jointName) {
  308. continue;
  309. }
  310. const children = node.children;
  311. for (let i = 0; i < children.length; i++) {
  312. const child = gltfRuntime.nodes[children[i]];
  313. if (!child.jointName) {
  314. continue;
  315. }
  316. if (child.jointName === jointName) {
  317. const mat = configureBoneTransformation(node);
  318. const bone = new Bone(node.name || "", newSkeleton, getParentBone(gltfRuntime, skins, node.jointName, newSkeleton), mat);
  319. bone.id = nde;
  320. return bone;
  321. }
  322. }
  323. }
  324. return null;
  325. };
  326. /**
  327. * Returns the appropriate root node
  328. * @param nodesToRoot
  329. * @param id
  330. * @returns the root node
  331. */
  332. const getNodeToRoot = (nodesToRoot, id) => {
  333. for (let i = 0; i < nodesToRoot.length; i++) {
  334. const nodeToRoot = nodesToRoot[i];
  335. for (let j = 0; j < nodeToRoot.node.children.length; j++) {
  336. const child = nodeToRoot.node.children[j];
  337. if (child === id) {
  338. return nodeToRoot.bone;
  339. }
  340. }
  341. }
  342. return null;
  343. };
  344. /**
  345. * Returns the node with the joint name
  346. * @param gltfRuntime
  347. * @param jointName
  348. * @returns the node with the joint name
  349. */
  350. const getJointNode = (gltfRuntime, jointName) => {
  351. const nodes = gltfRuntime.nodes;
  352. let node = nodes[jointName];
  353. if (node) {
  354. return {
  355. node: node,
  356. id: jointName,
  357. };
  358. }
  359. for (const nde in nodes) {
  360. node = nodes[nde];
  361. if (node.jointName === jointName) {
  362. return {
  363. node: node,
  364. id: nde,
  365. };
  366. }
  367. }
  368. return null;
  369. };
  370. /**
  371. * Checks if a nodes is in joints
  372. * @param skins
  373. * @param id
  374. * @returns true if the node is in joints, else false
  375. */
  376. const nodeIsInJoints = (skins, id) => {
  377. for (let i = 0; i < skins.jointNames.length; i++) {
  378. if (skins.jointNames[i] === id) {
  379. return true;
  380. }
  381. }
  382. return false;
  383. };
  384. /**
  385. * Fills the nodes to root for bones and builds hierarchy
  386. * @param gltfRuntime
  387. * @param newSkeleton
  388. * @param skins
  389. * @param nodesToRoot
  390. */
  391. const getNodesToRoot = (gltfRuntime, newSkeleton, skins, nodesToRoot) => {
  392. // Creates nodes for root
  393. for (const nde in gltfRuntime.nodes) {
  394. const node = gltfRuntime.nodes[nde];
  395. const id = nde;
  396. if (!node.jointName || nodeIsInJoints(skins, node.jointName)) {
  397. continue;
  398. }
  399. // Create node to root bone
  400. const mat = configureBoneTransformation(node);
  401. const bone = new Bone(node.name || "", newSkeleton, null, mat);
  402. bone.id = id;
  403. nodesToRoot.push({ bone: bone, node: node, id: id });
  404. }
  405. // Parenting
  406. for (let i = 0; i < nodesToRoot.length; i++) {
  407. const nodeToRoot = nodesToRoot[i];
  408. const children = nodeToRoot.node.children;
  409. for (let j = 0; j < children.length; j++) {
  410. let child = null;
  411. for (let k = 0; k < nodesToRoot.length; k++) {
  412. if (nodesToRoot[k].id === children[j]) {
  413. child = nodesToRoot[k];
  414. break;
  415. }
  416. }
  417. if (child) {
  418. child.bone._parent = nodeToRoot.bone;
  419. nodeToRoot.bone.children.push(child.bone);
  420. }
  421. }
  422. }
  423. };
  424. /**
  425. * Imports a skeleton
  426. * @param gltfRuntime
  427. * @param skins
  428. * @param mesh
  429. * @param newSkeleton
  430. * @returns the bone name
  431. */
  432. const importSkeleton = (gltfRuntime, skins, mesh, newSkeleton) => {
  433. if (!newSkeleton) {
  434. newSkeleton = new Skeleton(skins.name || "", "", gltfRuntime.scene);
  435. }
  436. if (!skins.babylonSkeleton) {
  437. return newSkeleton;
  438. }
  439. // Find the root bones
  440. const nodesToRoot = [];
  441. const nodesToRootToAdd = [];
  442. getNodesToRoot(gltfRuntime, newSkeleton, skins, nodesToRoot);
  443. newSkeleton.bones = [];
  444. // Joints
  445. for (let i = 0; i < skins.jointNames.length; i++) {
  446. const jointNode = getJointNode(gltfRuntime, skins.jointNames[i]);
  447. if (!jointNode) {
  448. continue;
  449. }
  450. const node = jointNode.node;
  451. if (!node) {
  452. Tools.Warn("Joint named " + skins.jointNames[i] + " does not exist");
  453. continue;
  454. }
  455. const id = jointNode.id;
  456. // Optimize, if the bone already exists...
  457. const existingBone = gltfRuntime.scene.getBoneById(id);
  458. if (existingBone) {
  459. newSkeleton.bones.push(existingBone);
  460. continue;
  461. }
  462. // Search for parent bone
  463. let foundBone = false;
  464. let parentBone = null;
  465. for (let j = 0; j < i; j++) {
  466. const jointNode = getJointNode(gltfRuntime, skins.jointNames[j]);
  467. if (!jointNode) {
  468. continue;
  469. }
  470. const joint = jointNode.node;
  471. if (!joint) {
  472. Tools.Warn("Joint named " + skins.jointNames[j] + " does not exist when looking for parent");
  473. continue;
  474. }
  475. const children = joint.children;
  476. if (!children) {
  477. continue;
  478. }
  479. foundBone = false;
  480. for (let k = 0; k < children.length; k++) {
  481. if (children[k] === id) {
  482. parentBone = getParentBone(gltfRuntime, skins, skins.jointNames[j], newSkeleton);
  483. foundBone = true;
  484. break;
  485. }
  486. }
  487. if (foundBone) {
  488. break;
  489. }
  490. }
  491. // Create bone
  492. const mat = configureBoneTransformation(node);
  493. if (!parentBone && nodesToRoot.length > 0) {
  494. parentBone = getNodeToRoot(nodesToRoot, id);
  495. if (parentBone) {
  496. if (nodesToRootToAdd.indexOf(parentBone) === -1) {
  497. nodesToRootToAdd.push(parentBone);
  498. }
  499. }
  500. }
  501. const bone = new Bone(node.jointName || "", newSkeleton, parentBone, mat);
  502. bone.id = id;
  503. }
  504. // Polish
  505. const bones = newSkeleton.bones;
  506. newSkeleton.bones = [];
  507. for (let i = 0; i < skins.jointNames.length; i++) {
  508. const jointNode = getJointNode(gltfRuntime, skins.jointNames[i]);
  509. if (!jointNode) {
  510. continue;
  511. }
  512. for (let j = 0; j < bones.length; j++) {
  513. if (bones[j].id === jointNode.id) {
  514. newSkeleton.bones.push(bones[j]);
  515. break;
  516. }
  517. }
  518. }
  519. newSkeleton.prepare();
  520. // Finish
  521. for (let i = 0; i < nodesToRootToAdd.length; i++) {
  522. newSkeleton.bones.push(nodesToRootToAdd[i]);
  523. }
  524. return newSkeleton;
  525. };
  526. /**
  527. * Imports a mesh and its geometries
  528. * @param gltfRuntime
  529. * @param node
  530. * @param meshes
  531. * @param id
  532. * @param newMesh
  533. * @returns the new mesh
  534. */
  535. const importMesh = (gltfRuntime, node, meshes, id, newMesh) => {
  536. if (!newMesh) {
  537. gltfRuntime.scene._blockEntityCollection = !!gltfRuntime.assetContainer;
  538. newMesh = new Mesh(node.name || "", gltfRuntime.scene);
  539. newMesh._parentContainer = gltfRuntime.assetContainer;
  540. gltfRuntime.scene._blockEntityCollection = false;
  541. newMesh.id = id;
  542. }
  543. if (!node.babylonNode) {
  544. return newMesh;
  545. }
  546. const subMaterials = [];
  547. let vertexData = null;
  548. const verticesStarts = [];
  549. const verticesCounts = [];
  550. const indexStarts = [];
  551. const indexCounts = [];
  552. for (let meshIndex = 0; meshIndex < meshes.length; meshIndex++) {
  553. const meshId = meshes[meshIndex];
  554. const mesh = gltfRuntime.meshes[meshId];
  555. if (!mesh) {
  556. continue;
  557. }
  558. // Positions, normals and UVs
  559. for (let i = 0; i < mesh.primitives.length; i++) {
  560. // Temporary vertex data
  561. const tempVertexData = new VertexData();
  562. const primitive = mesh.primitives[i];
  563. if (primitive.mode !== 4) {
  564. // continue;
  565. }
  566. const attributes = primitive.attributes;
  567. let accessor = null;
  568. let buffer = null;
  569. // Set positions, normal and uvs
  570. for (const semantic in attributes) {
  571. // Link accessor and buffer view
  572. accessor = gltfRuntime.accessors[attributes[semantic]];
  573. buffer = GLTFUtils.GetBufferFromAccessor(gltfRuntime, accessor);
  574. if (semantic === "NORMAL") {
  575. tempVertexData.normals = new Float32Array(buffer.length);
  576. tempVertexData.normals.set(buffer);
  577. }
  578. else if (semantic === "POSITION") {
  579. if (GLTFFileLoader.HomogeneousCoordinates) {
  580. tempVertexData.positions = new Float32Array(buffer.length - buffer.length / 4);
  581. for (let j = 0; j < buffer.length; j += 4) {
  582. tempVertexData.positions[j] = buffer[j];
  583. tempVertexData.positions[j + 1] = buffer[j + 1];
  584. tempVertexData.positions[j + 2] = buffer[j + 2];
  585. }
  586. }
  587. else {
  588. tempVertexData.positions = new Float32Array(buffer.length);
  589. tempVertexData.positions.set(buffer);
  590. }
  591. verticesCounts.push(tempVertexData.positions.length);
  592. }
  593. else if (semantic.indexOf("TEXCOORD_") !== -1) {
  594. const channel = Number(semantic.split("_")[1]);
  595. const uvKind = VertexBuffer.UVKind + (channel === 0 ? "" : channel + 1);
  596. const uvs = new Float32Array(buffer.length);
  597. uvs.set(buffer);
  598. normalizeUVs(uvs);
  599. tempVertexData.set(uvs, uvKind);
  600. }
  601. else if (semantic === "JOINT") {
  602. tempVertexData.matricesIndices = new Float32Array(buffer.length);
  603. tempVertexData.matricesIndices.set(buffer);
  604. }
  605. else if (semantic === "WEIGHT") {
  606. tempVertexData.matricesWeights = new Float32Array(buffer.length);
  607. tempVertexData.matricesWeights.set(buffer);
  608. }
  609. else if (semantic === "COLOR") {
  610. tempVertexData.colors = new Float32Array(buffer.length);
  611. tempVertexData.colors.set(buffer);
  612. }
  613. }
  614. // Indices
  615. accessor = gltfRuntime.accessors[primitive.indices];
  616. if (accessor) {
  617. buffer = GLTFUtils.GetBufferFromAccessor(gltfRuntime, accessor);
  618. tempVertexData.indices = new Int32Array(buffer.length);
  619. tempVertexData.indices.set(buffer);
  620. indexCounts.push(tempVertexData.indices.length);
  621. }
  622. else {
  623. // Set indices on the fly
  624. const indices = [];
  625. for (let j = 0; j < tempVertexData.positions.length / 3; j++) {
  626. indices.push(j);
  627. }
  628. tempVertexData.indices = new Int32Array(indices);
  629. indexCounts.push(tempVertexData.indices.length);
  630. }
  631. if (!vertexData) {
  632. vertexData = tempVertexData;
  633. }
  634. else {
  635. vertexData.merge(tempVertexData);
  636. }
  637. // Sub material
  638. const material = gltfRuntime.scene.getMaterialById(primitive.material);
  639. subMaterials.push(material === null ? GLTFUtils.GetDefaultMaterial(gltfRuntime.scene) : material);
  640. // Update vertices start and index start
  641. verticesStarts.push(verticesStarts.length === 0 ? 0 : verticesStarts[verticesStarts.length - 1] + verticesCounts[verticesCounts.length - 2]);
  642. indexStarts.push(indexStarts.length === 0 ? 0 : indexStarts[indexStarts.length - 1] + indexCounts[indexCounts.length - 2]);
  643. }
  644. }
  645. let material;
  646. gltfRuntime.scene._blockEntityCollection = !!gltfRuntime.assetContainer;
  647. if (subMaterials.length > 1) {
  648. material = new MultiMaterial("multimat" + id, gltfRuntime.scene);
  649. material.subMaterials = subMaterials;
  650. }
  651. else {
  652. material = new StandardMaterial("multimat" + id, gltfRuntime.scene);
  653. }
  654. if (subMaterials.length === 1) {
  655. material = subMaterials[0];
  656. }
  657. material._parentContainer = gltfRuntime.assetContainer;
  658. if (!newMesh.material) {
  659. newMesh.material = material;
  660. }
  661. // Apply geometry
  662. new Geometry(id, gltfRuntime.scene, vertexData, false, newMesh);
  663. newMesh.computeWorldMatrix(true);
  664. gltfRuntime.scene._blockEntityCollection = false;
  665. // Apply submeshes
  666. newMesh.subMeshes = [];
  667. let index = 0;
  668. for (let meshIndex = 0; meshIndex < meshes.length; meshIndex++) {
  669. const meshId = meshes[meshIndex];
  670. const mesh = gltfRuntime.meshes[meshId];
  671. if (!mesh) {
  672. continue;
  673. }
  674. for (let i = 0; i < mesh.primitives.length; i++) {
  675. if (mesh.primitives[i].mode !== 4) {
  676. //continue;
  677. }
  678. SubMesh.AddToMesh(index, verticesStarts[index], verticesCounts[index], indexStarts[index], indexCounts[index], newMesh, newMesh, true);
  679. index++;
  680. }
  681. }
  682. // Finish
  683. return newMesh;
  684. };
  685. /**
  686. * Configure node transformation from position, rotation and scaling
  687. * @param newNode
  688. * @param position
  689. * @param rotation
  690. * @param scaling
  691. */
  692. const configureNode = (newNode, position, rotation, scaling) => {
  693. if (newNode.position) {
  694. newNode.position = position;
  695. }
  696. if (newNode.rotationQuaternion || newNode.rotation) {
  697. newNode.rotationQuaternion = rotation;
  698. }
  699. if (newNode.scaling) {
  700. newNode.scaling = scaling;
  701. }
  702. };
  703. /**
  704. * Configures node from transformation matrix
  705. * @param newNode
  706. * @param node
  707. */
  708. const configureNodeFromMatrix = (newNode, node) => {
  709. if (node.matrix) {
  710. const position = new Vector3(0, 0, 0);
  711. const rotation = new Quaternion();
  712. const scaling = new Vector3(0, 0, 0);
  713. const mat = Matrix.FromArray(node.matrix);
  714. mat.decompose(scaling, rotation, position);
  715. configureNode(newNode, position, rotation, scaling);
  716. }
  717. else if (node.translation && node.rotation && node.scale) {
  718. configureNode(newNode, Vector3.FromArray(node.translation), Quaternion.FromArray(node.rotation), Vector3.FromArray(node.scale));
  719. }
  720. newNode.computeWorldMatrix(true);
  721. };
  722. /**
  723. * Imports a node
  724. * @param gltfRuntime
  725. * @param node
  726. * @param id
  727. * @returns the newly imported node
  728. */
  729. const importNode = (gltfRuntime, node, id) => {
  730. let lastNode = null;
  731. if (gltfRuntime.importOnlyMeshes && (node.skin || node.meshes)) {
  732. if (gltfRuntime.importMeshesNames && gltfRuntime.importMeshesNames.length > 0 && gltfRuntime.importMeshesNames.indexOf(node.name || "") === -1) {
  733. return null;
  734. }
  735. }
  736. // Meshes
  737. if (node.skin) {
  738. if (node.meshes) {
  739. const skin = gltfRuntime.skins[node.skin];
  740. const newMesh = importMesh(gltfRuntime, node, node.meshes, id, node.babylonNode);
  741. newMesh.skeleton = gltfRuntime.scene.getLastSkeletonById(node.skin);
  742. if (newMesh.skeleton === null) {
  743. newMesh.skeleton = importSkeleton(gltfRuntime, skin, newMesh, skin.babylonSkeleton);
  744. if (!skin.babylonSkeleton) {
  745. skin.babylonSkeleton = newMesh.skeleton;
  746. }
  747. }
  748. lastNode = newMesh;
  749. }
  750. }
  751. else if (node.meshes) {
  752. /**
  753. * Improve meshes property
  754. */
  755. const newMesh = importMesh(gltfRuntime, node, node.mesh ? [node.mesh] : node.meshes, id, node.babylonNode);
  756. lastNode = newMesh;
  757. }
  758. // Lights
  759. else if (node.light && !node.babylonNode && !gltfRuntime.importOnlyMeshes) {
  760. const light = gltfRuntime.lights[node.light];
  761. if (light) {
  762. if (light.type === "ambient") {
  763. const ambienLight = light[light.type];
  764. const hemiLight = new HemisphericLight(node.light, Vector3.Zero(), gltfRuntime.scene);
  765. hemiLight.name = node.name || "";
  766. if (ambienLight.color) {
  767. hemiLight.diffuse = Color3.FromArray(ambienLight.color);
  768. }
  769. lastNode = hemiLight;
  770. }
  771. else if (light.type === "directional") {
  772. const directionalLight = light[light.type];
  773. const dirLight = new DirectionalLight(node.light, Vector3.Zero(), gltfRuntime.scene);
  774. dirLight.name = node.name || "";
  775. if (directionalLight.color) {
  776. dirLight.diffuse = Color3.FromArray(directionalLight.color);
  777. }
  778. lastNode = dirLight;
  779. }
  780. else if (light.type === "point") {
  781. const pointLight = light[light.type];
  782. const ptLight = new PointLight(node.light, Vector3.Zero(), gltfRuntime.scene);
  783. ptLight.name = node.name || "";
  784. if (pointLight.color) {
  785. ptLight.diffuse = Color3.FromArray(pointLight.color);
  786. }
  787. lastNode = ptLight;
  788. }
  789. else if (light.type === "spot") {
  790. const spotLight = light[light.type];
  791. const spLight = new SpotLight(node.light, Vector3.Zero(), Vector3.Zero(), 0, 0, gltfRuntime.scene);
  792. spLight.name = node.name || "";
  793. if (spotLight.color) {
  794. spLight.diffuse = Color3.FromArray(spotLight.color);
  795. }
  796. if (spotLight.fallOfAngle) {
  797. spLight.angle = spotLight.fallOfAngle;
  798. }
  799. if (spotLight.fallOffExponent) {
  800. spLight.exponent = spotLight.fallOffExponent;
  801. }
  802. lastNode = spLight;
  803. }
  804. }
  805. }
  806. // Cameras
  807. else if (node.camera && !node.babylonNode && !gltfRuntime.importOnlyMeshes) {
  808. const camera = gltfRuntime.cameras[node.camera];
  809. if (camera) {
  810. gltfRuntime.scene._blockEntityCollection = !!gltfRuntime.assetContainer;
  811. if (camera.type === "orthographic") {
  812. const orthoCamera = new FreeCamera(node.camera, Vector3.Zero(), gltfRuntime.scene, false);
  813. orthoCamera.name = node.name || "";
  814. orthoCamera.mode = Camera.ORTHOGRAPHIC_CAMERA;
  815. orthoCamera.attachControl();
  816. lastNode = orthoCamera;
  817. orthoCamera._parentContainer = gltfRuntime.assetContainer;
  818. }
  819. else if (camera.type === "perspective") {
  820. const perspectiveCamera = camera[camera.type];
  821. const persCamera = new FreeCamera(node.camera, Vector3.Zero(), gltfRuntime.scene, false);
  822. persCamera.name = node.name || "";
  823. persCamera.attachControl();
  824. if (!perspectiveCamera.aspectRatio) {
  825. perspectiveCamera.aspectRatio = gltfRuntime.scene.getEngine().getRenderWidth() / gltfRuntime.scene.getEngine().getRenderHeight();
  826. }
  827. if (perspectiveCamera.znear && perspectiveCamera.zfar) {
  828. persCamera.maxZ = perspectiveCamera.zfar;
  829. persCamera.minZ = perspectiveCamera.znear;
  830. }
  831. lastNode = persCamera;
  832. persCamera._parentContainer = gltfRuntime.assetContainer;
  833. }
  834. gltfRuntime.scene._blockEntityCollection = false;
  835. }
  836. }
  837. // Empty node
  838. if (!node.jointName) {
  839. if (node.babylonNode) {
  840. return node.babylonNode;
  841. }
  842. else if (lastNode === null) {
  843. gltfRuntime.scene._blockEntityCollection = !!gltfRuntime.assetContainer;
  844. const dummy = new Mesh(node.name || "", gltfRuntime.scene);
  845. dummy._parentContainer = gltfRuntime.assetContainer;
  846. gltfRuntime.scene._blockEntityCollection = false;
  847. node.babylonNode = dummy;
  848. lastNode = dummy;
  849. }
  850. }
  851. if (lastNode !== null) {
  852. if (node.matrix && lastNode instanceof Mesh) {
  853. configureNodeFromMatrix(lastNode, node);
  854. }
  855. else {
  856. const translation = node.translation || [0, 0, 0];
  857. const rotation = node.rotation || [0, 0, 0, 1];
  858. const scale = node.scale || [1, 1, 1];
  859. configureNode(lastNode, Vector3.FromArray(translation), Quaternion.FromArray(rotation), Vector3.FromArray(scale));
  860. }
  861. lastNode.updateCache(true);
  862. node.babylonNode = lastNode;
  863. }
  864. return lastNode;
  865. };
  866. /**
  867. * Traverses nodes and creates them
  868. * @param gltfRuntime
  869. * @param id
  870. * @param parent
  871. * @param meshIncluded
  872. */
  873. const traverseNodes = (gltfRuntime, id, parent, meshIncluded = false) => {
  874. const node = gltfRuntime.nodes[id];
  875. let newNode = null;
  876. if (gltfRuntime.importOnlyMeshes && !meshIncluded && gltfRuntime.importMeshesNames) {
  877. if (gltfRuntime.importMeshesNames.indexOf(node.name || "") !== -1 || gltfRuntime.importMeshesNames.length === 0) {
  878. meshIncluded = true;
  879. }
  880. else {
  881. meshIncluded = false;
  882. }
  883. }
  884. else {
  885. meshIncluded = true;
  886. }
  887. if (!node.jointName && meshIncluded) {
  888. newNode = importNode(gltfRuntime, node, id);
  889. if (newNode !== null) {
  890. newNode.id = id;
  891. newNode.parent = parent;
  892. }
  893. }
  894. if (node.children) {
  895. for (let i = 0; i < node.children.length; i++) {
  896. traverseNodes(gltfRuntime, node.children[i], newNode, meshIncluded);
  897. }
  898. }
  899. };
  900. /**
  901. * do stuff after buffers, shaders are loaded (e.g. hook up materials, load animations, etc.)
  902. * @param gltfRuntime
  903. */
  904. const postLoad = (gltfRuntime) => {
  905. // Nodes
  906. let currentScene = gltfRuntime.currentScene;
  907. if (currentScene) {
  908. for (let i = 0; i < currentScene.nodes.length; i++) {
  909. traverseNodes(gltfRuntime, currentScene.nodes[i], null);
  910. }
  911. }
  912. else {
  913. for (const thing in gltfRuntime.scenes) {
  914. currentScene = gltfRuntime.scenes[thing];
  915. for (let i = 0; i < currentScene.nodes.length; i++) {
  916. traverseNodes(gltfRuntime, currentScene.nodes[i], null);
  917. }
  918. }
  919. }
  920. // Set animations
  921. loadAnimations(gltfRuntime);
  922. for (let i = 0; i < gltfRuntime.scene.skeletons.length; i++) {
  923. const skeleton = gltfRuntime.scene.skeletons[i];
  924. gltfRuntime.scene.beginAnimation(skeleton, 0, Number.MAX_VALUE, true, 1.0);
  925. }
  926. };
  927. /**
  928. * onBind shaderrs callback to set uniforms and matrices
  929. * @param mesh
  930. * @param gltfRuntime
  931. * @param unTreatedUniforms
  932. * @param shaderMaterial
  933. * @param technique
  934. * @param material
  935. * @param onSuccess
  936. */
  937. const onBindShaderMaterial = (mesh, gltfRuntime, unTreatedUniforms, shaderMaterial, technique, material, onSuccess) => {
  938. const materialValues = material.values || technique.parameters;
  939. for (const unif in unTreatedUniforms) {
  940. const uniform = unTreatedUniforms[unif];
  941. const type = uniform.type;
  942. if (type === EParameterType.FLOAT_MAT2 || type === EParameterType.FLOAT_MAT3 || type === EParameterType.FLOAT_MAT4) {
  943. if (uniform.semantic && !uniform.source && !uniform.node) {
  944. GLTFUtils.SetMatrix(gltfRuntime.scene, mesh, uniform, unif, shaderMaterial.getEffect());
  945. }
  946. else if (uniform.semantic && (uniform.source || uniform.node)) {
  947. let source = gltfRuntime.scene.getNodeByName(uniform.source || uniform.node || "");
  948. if (source === null) {
  949. source = gltfRuntime.scene.getNodeById(uniform.source || uniform.node || "");
  950. }
  951. if (source === null) {
  952. continue;
  953. }
  954. GLTFUtils.SetMatrix(gltfRuntime.scene, source, uniform, unif, shaderMaterial.getEffect());
  955. }
  956. }
  957. else {
  958. const value = materialValues[technique.uniforms[unif]];
  959. if (!value) {
  960. continue;
  961. }
  962. if (type === EParameterType.SAMPLER_2D) {
  963. const texture = gltfRuntime.textures[material.values ? value : uniform.value].babylonTexture;
  964. if (texture === null || texture === undefined) {
  965. continue;
  966. }
  967. shaderMaterial.getEffect().setTexture(unif, texture);
  968. }
  969. else {
  970. GLTFUtils.SetUniform(shaderMaterial.getEffect(), unif, value, type);
  971. }
  972. }
  973. }
  974. onSuccess(shaderMaterial);
  975. };
  976. /**
  977. * Prepare uniforms to send the only one time
  978. * Loads the appropriate textures
  979. * @param gltfRuntime
  980. * @param shaderMaterial
  981. * @param technique
  982. * @param material
  983. */
  984. const prepareShaderMaterialUniforms = (gltfRuntime, shaderMaterial, technique, material, unTreatedUniforms) => {
  985. const materialValues = material.values || technique.parameters;
  986. const techniqueUniforms = technique.uniforms;
  987. /**
  988. * Prepare values here (not matrices)
  989. */
  990. for (const unif in unTreatedUniforms) {
  991. const uniform = unTreatedUniforms[unif];
  992. const type = uniform.type;
  993. let value = materialValues[techniqueUniforms[unif]];
  994. if (value === undefined) {
  995. // In case the value is the same for all materials
  996. value = uniform.value;
  997. }
  998. if (!value) {
  999. continue;
  1000. }
  1001. const onLoadTexture = (uniformName) => {
  1002. return (texture) => {
  1003. if (uniform.value && uniformName) {
  1004. // Static uniform
  1005. shaderMaterial.setTexture(uniformName, texture);
  1006. delete unTreatedUniforms[uniformName];
  1007. }
  1008. };
  1009. };
  1010. // Texture (sampler2D)
  1011. if (type === EParameterType.SAMPLER_2D) {
  1012. GLTFLoaderExtension.LoadTextureAsync(gltfRuntime, material.values ? value : uniform.value, onLoadTexture(unif), () => onLoadTexture(null));
  1013. }
  1014. // Others
  1015. else {
  1016. if (uniform.value && GLTFUtils.SetUniform(shaderMaterial, unif, material.values ? value : uniform.value, type)) {
  1017. // Static uniform
  1018. delete unTreatedUniforms[unif];
  1019. }
  1020. }
  1021. }
  1022. };
  1023. /**
  1024. * Shader compilation failed
  1025. * @param program
  1026. * @param shaderMaterial
  1027. * @param onError
  1028. * @returns callback when shader is compiled
  1029. */
  1030. const onShaderCompileError = (program, shaderMaterial, onError) => {
  1031. return (effect, error) => {
  1032. shaderMaterial.dispose(true);
  1033. onError("Cannot compile program named " + program.name + ". Error: " + error + ". Default material will be applied");
  1034. };
  1035. };
  1036. /**
  1037. * Shader compilation success
  1038. * @param gltfRuntime
  1039. * @param shaderMaterial
  1040. * @param technique
  1041. * @param material
  1042. * @param unTreatedUniforms
  1043. * @param onSuccess
  1044. * @returns callback when shader is compiled
  1045. */
  1046. const onShaderCompileSuccess = (gltfRuntime, shaderMaterial, technique, material, unTreatedUniforms, onSuccess) => {
  1047. return (_) => {
  1048. prepareShaderMaterialUniforms(gltfRuntime, shaderMaterial, technique, material, unTreatedUniforms);
  1049. shaderMaterial.onBind = (mesh) => {
  1050. onBindShaderMaterial(mesh, gltfRuntime, unTreatedUniforms, shaderMaterial, technique, material, onSuccess);
  1051. };
  1052. };
  1053. };
  1054. /**
  1055. * Returns the appropriate uniform if already handled by babylon
  1056. * @param tokenizer
  1057. * @param technique
  1058. * @param unTreatedUniforms
  1059. * @returns the name of the uniform handled by babylon
  1060. */
  1061. const parseShaderUniforms = (tokenizer, technique, unTreatedUniforms) => {
  1062. for (const unif in technique.uniforms) {
  1063. const uniform = technique.uniforms[unif];
  1064. const uniformParameter = technique.parameters[uniform];
  1065. if (tokenizer.currentIdentifier === unif) {
  1066. if (uniformParameter.semantic && !uniformParameter.source && !uniformParameter.node) {
  1067. const transformIndex = glTFTransforms.indexOf(uniformParameter.semantic);
  1068. if (transformIndex !== -1) {
  1069. delete unTreatedUniforms[unif];
  1070. return babylonTransforms[transformIndex];
  1071. }
  1072. }
  1073. }
  1074. }
  1075. return tokenizer.currentIdentifier;
  1076. };
  1077. /**
  1078. * All shaders loaded. Create materials one by one
  1079. * @param gltfRuntime
  1080. */
  1081. const importMaterials = (gltfRuntime) => {
  1082. // Create materials
  1083. for (const mat in gltfRuntime.materials) {
  1084. GLTFLoaderExtension.LoadMaterialAsync(gltfRuntime, mat, () => { }, () => { });
  1085. }
  1086. };
  1087. /**
  1088. * Implementation of the base glTF spec
  1089. * @internal
  1090. */
  1091. export class GLTFLoaderBase {
  1092. static CreateRuntime(parsedData, scene, rootUrl) {
  1093. const gltfRuntime = {
  1094. extensions: {},
  1095. accessors: {},
  1096. buffers: {},
  1097. bufferViews: {},
  1098. meshes: {},
  1099. lights: {},
  1100. cameras: {},
  1101. nodes: {},
  1102. images: {},
  1103. textures: {},
  1104. shaders: {},
  1105. programs: {},
  1106. samplers: {},
  1107. techniques: {},
  1108. materials: {},
  1109. animations: {},
  1110. skins: {},
  1111. extensionsUsed: [],
  1112. scenes: {},
  1113. buffersCount: 0,
  1114. shaderscount: 0,
  1115. scene: scene,
  1116. rootUrl: rootUrl,
  1117. loadedBufferCount: 0,
  1118. loadedBufferViews: {},
  1119. loadedShaderCount: 0,
  1120. importOnlyMeshes: false,
  1121. dummyNodes: [],
  1122. assetContainer: null,
  1123. };
  1124. // Parse
  1125. if (parsedData.extensions) {
  1126. parseObject(parsedData.extensions, "extensions", gltfRuntime);
  1127. }
  1128. if (parsedData.extensionsUsed) {
  1129. parseObject(parsedData.extensionsUsed, "extensionsUsed", gltfRuntime);
  1130. }
  1131. if (parsedData.buffers) {
  1132. parseBuffers(parsedData.buffers, gltfRuntime);
  1133. }
  1134. if (parsedData.bufferViews) {
  1135. parseObject(parsedData.bufferViews, "bufferViews", gltfRuntime);
  1136. }
  1137. if (parsedData.accessors) {
  1138. parseObject(parsedData.accessors, "accessors", gltfRuntime);
  1139. }
  1140. if (parsedData.meshes) {
  1141. parseObject(parsedData.meshes, "meshes", gltfRuntime);
  1142. }
  1143. if (parsedData.lights) {
  1144. parseObject(parsedData.lights, "lights", gltfRuntime);
  1145. }
  1146. if (parsedData.cameras) {
  1147. parseObject(parsedData.cameras, "cameras", gltfRuntime);
  1148. }
  1149. if (parsedData.nodes) {
  1150. parseObject(parsedData.nodes, "nodes", gltfRuntime);
  1151. }
  1152. if (parsedData.images) {
  1153. parseObject(parsedData.images, "images", gltfRuntime);
  1154. }
  1155. if (parsedData.textures) {
  1156. parseObject(parsedData.textures, "textures", gltfRuntime);
  1157. }
  1158. if (parsedData.shaders) {
  1159. parseShaders(parsedData.shaders, gltfRuntime);
  1160. }
  1161. if (parsedData.programs) {
  1162. parseObject(parsedData.programs, "programs", gltfRuntime);
  1163. }
  1164. if (parsedData.samplers) {
  1165. parseObject(parsedData.samplers, "samplers", gltfRuntime);
  1166. }
  1167. if (parsedData.techniques) {
  1168. parseObject(parsedData.techniques, "techniques", gltfRuntime);
  1169. }
  1170. if (parsedData.materials) {
  1171. parseObject(parsedData.materials, "materials", gltfRuntime);
  1172. }
  1173. if (parsedData.animations) {
  1174. parseObject(parsedData.animations, "animations", gltfRuntime);
  1175. }
  1176. if (parsedData.skins) {
  1177. parseObject(parsedData.skins, "skins", gltfRuntime);
  1178. }
  1179. if (parsedData.scenes) {
  1180. gltfRuntime.scenes = parsedData.scenes;
  1181. }
  1182. if (parsedData.scene && parsedData.scenes) {
  1183. gltfRuntime.currentScene = parsedData.scenes[parsedData.scene];
  1184. }
  1185. return gltfRuntime;
  1186. }
  1187. static LoadBufferAsync(gltfRuntime, id, onSuccess, onError, onProgress) {
  1188. const buffer = gltfRuntime.buffers[id];
  1189. if (Tools.IsBase64(buffer.uri)) {
  1190. setTimeout(() => onSuccess(new Uint8Array(Tools.DecodeBase64(buffer.uri))));
  1191. }
  1192. else {
  1193. Tools.LoadFile(gltfRuntime.rootUrl + buffer.uri, (data) => onSuccess(new Uint8Array(data)), onProgress, undefined, true, (request) => {
  1194. if (request) {
  1195. onError(request.status + " " + request.statusText);
  1196. }
  1197. });
  1198. }
  1199. }
  1200. static LoadTextureBufferAsync(gltfRuntime, id, onSuccess, onError) {
  1201. const texture = gltfRuntime.textures[id];
  1202. if (!texture || !texture.source) {
  1203. onError("");
  1204. return;
  1205. }
  1206. if (texture.babylonTexture) {
  1207. onSuccess(null);
  1208. return;
  1209. }
  1210. const source = gltfRuntime.images[texture.source];
  1211. if (Tools.IsBase64(source.uri)) {
  1212. setTimeout(() => onSuccess(new Uint8Array(Tools.DecodeBase64(source.uri))));
  1213. }
  1214. else {
  1215. Tools.LoadFile(gltfRuntime.rootUrl + source.uri, (data) => onSuccess(new Uint8Array(data)), undefined, undefined, true, (request) => {
  1216. if (request) {
  1217. onError(request.status + " " + request.statusText);
  1218. }
  1219. });
  1220. }
  1221. }
  1222. static CreateTextureAsync(gltfRuntime, id, buffer, onSuccess) {
  1223. const texture = gltfRuntime.textures[id];
  1224. if (texture.babylonTexture) {
  1225. onSuccess(texture.babylonTexture);
  1226. return;
  1227. }
  1228. const sampler = gltfRuntime.samplers[texture.sampler];
  1229. const createMipMaps = sampler.minFilter === ETextureFilterType.NEAREST_MIPMAP_NEAREST ||
  1230. sampler.minFilter === ETextureFilterType.NEAREST_MIPMAP_LINEAR ||
  1231. sampler.minFilter === ETextureFilterType.LINEAR_MIPMAP_NEAREST ||
  1232. sampler.minFilter === ETextureFilterType.LINEAR_MIPMAP_LINEAR;
  1233. const samplingMode = Texture.BILINEAR_SAMPLINGMODE;
  1234. const blob = buffer == null ? new Blob() : new Blob([buffer]);
  1235. const blobURL = URL.createObjectURL(blob);
  1236. const revokeBlobURL = () => URL.revokeObjectURL(blobURL);
  1237. const newTexture = new Texture(blobURL, gltfRuntime.scene, !createMipMaps, true, samplingMode, revokeBlobURL, revokeBlobURL);
  1238. if (sampler.wrapS !== undefined) {
  1239. newTexture.wrapU = GLTFUtils.GetWrapMode(sampler.wrapS);
  1240. }
  1241. if (sampler.wrapT !== undefined) {
  1242. newTexture.wrapV = GLTFUtils.GetWrapMode(sampler.wrapT);
  1243. }
  1244. newTexture.name = id;
  1245. texture.babylonTexture = newTexture;
  1246. onSuccess(newTexture);
  1247. }
  1248. static LoadShaderStringAsync(gltfRuntime, id, onSuccess, onError) {
  1249. const shader = gltfRuntime.shaders[id];
  1250. if (Tools.IsBase64(shader.uri)) {
  1251. const shaderString = atob(shader.uri.split(",")[1]);
  1252. if (onSuccess) {
  1253. onSuccess(shaderString);
  1254. }
  1255. }
  1256. else {
  1257. Tools.LoadFile(gltfRuntime.rootUrl + shader.uri, onSuccess, undefined, undefined, false, (request) => {
  1258. if (request && onError) {
  1259. onError(request.status + " " + request.statusText);
  1260. }
  1261. });
  1262. }
  1263. }
  1264. static LoadMaterialAsync(gltfRuntime, id, onSuccess, onError) {
  1265. const material = gltfRuntime.materials[id];
  1266. if (!material.technique) {
  1267. if (onError) {
  1268. onError("No technique found.");
  1269. }
  1270. return;
  1271. }
  1272. const technique = gltfRuntime.techniques[material.technique];
  1273. if (!technique) {
  1274. gltfRuntime.scene._blockEntityCollection = !!gltfRuntime.assetContainer;
  1275. const defaultMaterial = new StandardMaterial(id, gltfRuntime.scene);
  1276. defaultMaterial._parentContainer = gltfRuntime.assetContainer;
  1277. gltfRuntime.scene._blockEntityCollection = false;
  1278. defaultMaterial.diffuseColor = new Color3(0.5, 0.5, 0.5);
  1279. defaultMaterial.sideOrientation = Material.CounterClockWiseSideOrientation;
  1280. onSuccess(defaultMaterial);
  1281. return;
  1282. }
  1283. const program = gltfRuntime.programs[technique.program];
  1284. const states = technique.states;
  1285. const vertexShader = Effect.ShadersStore[program.vertexShader + "VertexShader"];
  1286. const pixelShader = Effect.ShadersStore[program.fragmentShader + "PixelShader"];
  1287. let newVertexShader = "";
  1288. let newPixelShader = "";
  1289. const vertexTokenizer = new Tokenizer(vertexShader);
  1290. const pixelTokenizer = new Tokenizer(pixelShader);
  1291. const unTreatedUniforms = {};
  1292. const uniforms = [];
  1293. const attributes = [];
  1294. const samplers = [];
  1295. // Fill uniform, sampler2D and attributes
  1296. for (const unif in technique.uniforms) {
  1297. const uniform = technique.uniforms[unif];
  1298. const uniformParameter = technique.parameters[uniform];
  1299. unTreatedUniforms[unif] = uniformParameter;
  1300. if (uniformParameter.semantic && !uniformParameter.node && !uniformParameter.source) {
  1301. const transformIndex = glTFTransforms.indexOf(uniformParameter.semantic);
  1302. if (transformIndex !== -1) {
  1303. uniforms.push(babylonTransforms[transformIndex]);
  1304. delete unTreatedUniforms[unif];
  1305. }
  1306. else {
  1307. uniforms.push(unif);
  1308. }
  1309. }
  1310. else if (uniformParameter.type === EParameterType.SAMPLER_2D) {
  1311. samplers.push(unif);
  1312. }
  1313. else {
  1314. uniforms.push(unif);
  1315. }
  1316. }
  1317. for (const attr in technique.attributes) {
  1318. const attribute = technique.attributes[attr];
  1319. const attributeParameter = technique.parameters[attribute];
  1320. if (attributeParameter.semantic) {
  1321. const name = getAttribute(attributeParameter);
  1322. if (name) {
  1323. attributes.push(name);
  1324. }
  1325. }
  1326. }
  1327. // Configure vertex shader
  1328. while (!vertexTokenizer.isEnd() && vertexTokenizer.getNextToken()) {
  1329. const tokenType = vertexTokenizer.currentToken;
  1330. if (tokenType !== ETokenType.IDENTIFIER) {
  1331. newVertexShader += vertexTokenizer.currentString;
  1332. continue;
  1333. }
  1334. let foundAttribute = false;
  1335. for (const attr in technique.attributes) {
  1336. const attribute = technique.attributes[attr];
  1337. const attributeParameter = technique.parameters[attribute];
  1338. if (vertexTokenizer.currentIdentifier === attr && attributeParameter.semantic) {
  1339. newVertexShader += getAttribute(attributeParameter);
  1340. foundAttribute = true;
  1341. break;
  1342. }
  1343. }
  1344. if (foundAttribute) {
  1345. continue;
  1346. }
  1347. newVertexShader += parseShaderUniforms(vertexTokenizer, technique, unTreatedUniforms);
  1348. }
  1349. // Configure pixel shader
  1350. while (!pixelTokenizer.isEnd() && pixelTokenizer.getNextToken()) {
  1351. const tokenType = pixelTokenizer.currentToken;
  1352. if (tokenType !== ETokenType.IDENTIFIER) {
  1353. newPixelShader += pixelTokenizer.currentString;
  1354. continue;
  1355. }
  1356. newPixelShader += parseShaderUniforms(pixelTokenizer, technique, unTreatedUniforms);
  1357. }
  1358. // Create shader material
  1359. const shaderPath = {
  1360. vertex: program.vertexShader + id,
  1361. fragment: program.fragmentShader + id,
  1362. };
  1363. const options = {
  1364. attributes: attributes,
  1365. uniforms: uniforms,
  1366. samplers: samplers,
  1367. needAlphaBlending: states && states.enable && states.enable.indexOf(3042) !== -1,
  1368. };
  1369. Effect.ShadersStore[program.vertexShader + id + "VertexShader"] = newVertexShader;
  1370. Effect.ShadersStore[program.fragmentShader + id + "PixelShader"] = newPixelShader;
  1371. const shaderMaterial = new ShaderMaterial(id, gltfRuntime.scene, shaderPath, options);
  1372. shaderMaterial.onError = onShaderCompileError(program, shaderMaterial, onError);
  1373. shaderMaterial.onCompiled = onShaderCompileSuccess(gltfRuntime, shaderMaterial, technique, material, unTreatedUniforms, onSuccess);
  1374. shaderMaterial.sideOrientation = Material.CounterClockWiseSideOrientation;
  1375. if (states && states.functions) {
  1376. const functions = states.functions;
  1377. if (functions.cullFace && functions.cullFace[0] !== ECullingType.BACK) {
  1378. shaderMaterial.backFaceCulling = false;
  1379. }
  1380. const blendFunc = functions.blendFuncSeparate;
  1381. if (blendFunc) {
  1382. if (blendFunc[0] === EBlendingFunction.SRC_ALPHA &&
  1383. blendFunc[1] === EBlendingFunction.ONE_MINUS_SRC_ALPHA &&
  1384. blendFunc[2] === EBlendingFunction.ONE &&
  1385. blendFunc[3] === EBlendingFunction.ONE) {
  1386. shaderMaterial.alphaMode = Constants.ALPHA_COMBINE;
  1387. }
  1388. else if (blendFunc[0] === EBlendingFunction.ONE &&
  1389. blendFunc[1] === EBlendingFunction.ONE &&
  1390. blendFunc[2] === EBlendingFunction.ZERO &&
  1391. blendFunc[3] === EBlendingFunction.ONE) {
  1392. shaderMaterial.alphaMode = Constants.ALPHA_ONEONE;
  1393. }
  1394. else if (blendFunc[0] === EBlendingFunction.SRC_ALPHA &&
  1395. blendFunc[1] === EBlendingFunction.ONE &&
  1396. blendFunc[2] === EBlendingFunction.ZERO &&
  1397. blendFunc[3] === EBlendingFunction.ONE) {
  1398. shaderMaterial.alphaMode = Constants.ALPHA_ADD;
  1399. }
  1400. else if (blendFunc[0] === EBlendingFunction.ZERO &&
  1401. blendFunc[1] === EBlendingFunction.ONE_MINUS_SRC_COLOR &&
  1402. blendFunc[2] === EBlendingFunction.ONE &&
  1403. blendFunc[3] === EBlendingFunction.ONE) {
  1404. shaderMaterial.alphaMode = Constants.ALPHA_SUBTRACT;
  1405. }
  1406. else if (blendFunc[0] === EBlendingFunction.DST_COLOR &&
  1407. blendFunc[1] === EBlendingFunction.ZERO &&
  1408. blendFunc[2] === EBlendingFunction.ONE &&
  1409. blendFunc[3] === EBlendingFunction.ONE) {
  1410. shaderMaterial.alphaMode = Constants.ALPHA_MULTIPLY;
  1411. }
  1412. else if (blendFunc[0] === EBlendingFunction.SRC_ALPHA &&
  1413. blendFunc[1] === EBlendingFunction.ONE_MINUS_SRC_COLOR &&
  1414. blendFunc[2] === EBlendingFunction.ONE &&
  1415. blendFunc[3] === EBlendingFunction.ONE) {
  1416. shaderMaterial.alphaMode = Constants.ALPHA_MAXIMIZED;
  1417. }
  1418. }
  1419. }
  1420. }
  1421. }
  1422. /**
  1423. * glTF V1 Loader
  1424. * @internal
  1425. * @deprecated
  1426. */
  1427. export class GLTFLoader {
  1428. static RegisterExtension(extension) {
  1429. if (GLTFLoader.Extensions[extension.name]) {
  1430. Tools.Error('Tool with the same name "' + extension.name + '" already exists');
  1431. return;
  1432. }
  1433. GLTFLoader.Extensions[extension.name] = extension;
  1434. }
  1435. dispose() {
  1436. // do nothing
  1437. }
  1438. _importMeshAsync(meshesNames, scene, data, rootUrl, assetContainer, onSuccess, onProgress, onError) {
  1439. scene.useRightHandedSystem = true;
  1440. GLTFLoaderExtension.LoadRuntimeAsync(scene, data, rootUrl, (gltfRuntime) => {
  1441. gltfRuntime.assetContainer = assetContainer;
  1442. gltfRuntime.importOnlyMeshes = true;
  1443. if (meshesNames === "") {
  1444. gltfRuntime.importMeshesNames = [];
  1445. }
  1446. else if (typeof meshesNames === "string") {
  1447. gltfRuntime.importMeshesNames = [meshesNames];
  1448. }
  1449. else if (meshesNames && !(meshesNames instanceof Array)) {
  1450. gltfRuntime.importMeshesNames = [meshesNames];
  1451. }
  1452. else {
  1453. gltfRuntime.importMeshesNames = [];
  1454. Tools.Warn("Argument meshesNames must be of type string or string[]");
  1455. }
  1456. // Create nodes
  1457. this._createNodes(gltfRuntime);
  1458. const meshes = [];
  1459. const skeletons = [];
  1460. // Fill arrays of meshes and skeletons
  1461. for (const nde in gltfRuntime.nodes) {
  1462. const node = gltfRuntime.nodes[nde];
  1463. if (node.babylonNode instanceof AbstractMesh) {
  1464. meshes.push(node.babylonNode);
  1465. }
  1466. }
  1467. for (const skl in gltfRuntime.skins) {
  1468. const skin = gltfRuntime.skins[skl];
  1469. if (skin.babylonSkeleton instanceof Skeleton) {
  1470. skeletons.push(skin.babylonSkeleton);
  1471. }
  1472. }
  1473. // Load buffers, shaders, materials, etc.
  1474. this._loadBuffersAsync(gltfRuntime, () => {
  1475. this._loadShadersAsync(gltfRuntime, () => {
  1476. importMaterials(gltfRuntime);
  1477. postLoad(gltfRuntime);
  1478. if (!GLTFFileLoader.IncrementalLoading && onSuccess) {
  1479. onSuccess(meshes, skeletons);
  1480. }
  1481. });
  1482. });
  1483. if (GLTFFileLoader.IncrementalLoading && onSuccess) {
  1484. onSuccess(meshes, skeletons);
  1485. }
  1486. }, onError);
  1487. return true;
  1488. }
  1489. /**
  1490. * Imports one or more meshes from a loaded gltf file and adds them to the scene
  1491. * @param meshesNames a string or array of strings of the mesh names that should be loaded from the file
  1492. * @param scene the scene the meshes should be added to
  1493. * @param assetContainer defines the asset container to use (can be null)
  1494. * @param data gltf data containing information of the meshes in a loaded file
  1495. * @param rootUrl root url to load from
  1496. * @param onProgress event that fires when loading progress has occured
  1497. * @returns a promise containg the loaded meshes, particles, skeletons and animations
  1498. */
  1499. importMeshAsync(meshesNames, scene, assetContainer, data, rootUrl, onProgress) {
  1500. return new Promise((resolve, reject) => {
  1501. this._importMeshAsync(meshesNames, scene, data, rootUrl, assetContainer, (meshes, skeletons) => {
  1502. resolve({
  1503. meshes: meshes,
  1504. particleSystems: [],
  1505. skeletons: skeletons,
  1506. animationGroups: [],
  1507. lights: [],
  1508. transformNodes: [],
  1509. geometries: [],
  1510. spriteManagers: [],
  1511. });
  1512. }, onProgress, (message) => {
  1513. reject(new Error(message));
  1514. });
  1515. });
  1516. }
  1517. _loadAsync(scene, data, rootUrl, onSuccess, onProgress, onError) {
  1518. scene.useRightHandedSystem = true;
  1519. GLTFLoaderExtension.LoadRuntimeAsync(scene, data, rootUrl, (gltfRuntime) => {
  1520. // Load runtime extensios
  1521. GLTFLoaderExtension.LoadRuntimeExtensionsAsync(gltfRuntime, () => {
  1522. // Create nodes
  1523. this._createNodes(gltfRuntime);
  1524. // Load buffers, shaders, materials, etc.
  1525. this._loadBuffersAsync(gltfRuntime, () => {
  1526. this._loadShadersAsync(gltfRuntime, () => {
  1527. importMaterials(gltfRuntime);
  1528. postLoad(gltfRuntime);
  1529. if (!GLTFFileLoader.IncrementalLoading) {
  1530. onSuccess();
  1531. }
  1532. });
  1533. });
  1534. if (GLTFFileLoader.IncrementalLoading) {
  1535. onSuccess();
  1536. }
  1537. }, onError);
  1538. }, onError);
  1539. }
  1540. /**
  1541. * Imports all objects from a loaded gltf file and adds them to the scene
  1542. * @param scene the scene the objects should be added to
  1543. * @param data gltf data containing information of the meshes in a loaded file
  1544. * @param rootUrl root url to load from
  1545. * @param onProgress event that fires when loading progress has occured
  1546. * @returns a promise which completes when objects have been loaded to the scene
  1547. */
  1548. loadAsync(scene, data, rootUrl, onProgress) {
  1549. return new Promise((resolve, reject) => {
  1550. this._loadAsync(scene, data, rootUrl, () => {
  1551. resolve();
  1552. }, onProgress, (message) => {
  1553. reject(new Error(message));
  1554. });
  1555. });
  1556. }
  1557. _loadShadersAsync(gltfRuntime, onload) {
  1558. let hasShaders = false;
  1559. const processShader = (sha, shader) => {
  1560. GLTFLoaderExtension.LoadShaderStringAsync(gltfRuntime, sha, (shaderString) => {
  1561. if (shaderString instanceof ArrayBuffer) {
  1562. return;
  1563. }
  1564. gltfRuntime.loadedShaderCount++;
  1565. if (shaderString) {
  1566. Effect.ShadersStore[sha + (shader.type === EShaderType.VERTEX ? "VertexShader" : "PixelShader")] = shaderString;
  1567. }
  1568. if (gltfRuntime.loadedShaderCount === gltfRuntime.shaderscount) {
  1569. onload();
  1570. }
  1571. }, () => {
  1572. Tools.Error("Error when loading shader program named " + sha + " located at " + shader.uri);
  1573. });
  1574. };
  1575. for (const sha in gltfRuntime.shaders) {
  1576. hasShaders = true;
  1577. const shader = gltfRuntime.shaders[sha];
  1578. if (shader) {
  1579. processShader.bind(this, sha, shader)();
  1580. }
  1581. else {
  1582. Tools.Error("No shader named: " + sha);
  1583. }
  1584. }
  1585. if (!hasShaders) {
  1586. onload();
  1587. }
  1588. }
  1589. _loadBuffersAsync(gltfRuntime, onLoad) {
  1590. let hasBuffers = false;
  1591. const processBuffer = (buf, buffer) => {
  1592. GLTFLoaderExtension.LoadBufferAsync(gltfRuntime, buf, (bufferView) => {
  1593. gltfRuntime.loadedBufferCount++;
  1594. if (bufferView) {
  1595. if (bufferView.byteLength != gltfRuntime.buffers[buf].byteLength) {
  1596. Tools.Error("Buffer named " + buf + " is length " + bufferView.byteLength + ". Expected: " + buffer.byteLength); // Improve error message
  1597. }
  1598. gltfRuntime.loadedBufferViews[buf] = bufferView;
  1599. }
  1600. if (gltfRuntime.loadedBufferCount === gltfRuntime.buffersCount) {
  1601. onLoad();
  1602. }
  1603. }, () => {
  1604. Tools.Error("Error when loading buffer named " + buf + " located at " + buffer.uri);
  1605. });
  1606. };
  1607. for (const buf in gltfRuntime.buffers) {
  1608. hasBuffers = true;
  1609. const buffer = gltfRuntime.buffers[buf];
  1610. if (buffer) {
  1611. processBuffer.bind(this, buf, buffer)();
  1612. }
  1613. else {
  1614. Tools.Error("No buffer named: " + buf);
  1615. }
  1616. }
  1617. if (!hasBuffers) {
  1618. onLoad();
  1619. }
  1620. }
  1621. _createNodes(gltfRuntime) {
  1622. let currentScene = gltfRuntime.currentScene;
  1623. if (currentScene) {
  1624. // Only one scene even if multiple scenes are defined
  1625. for (let i = 0; i < currentScene.nodes.length; i++) {
  1626. traverseNodes(gltfRuntime, currentScene.nodes[i], null);
  1627. }
  1628. }
  1629. else {
  1630. // Load all scenes
  1631. for (const thing in gltfRuntime.scenes) {
  1632. currentScene = gltfRuntime.scenes[thing];
  1633. for (let i = 0; i < currentScene.nodes.length; i++) {
  1634. traverseNodes(gltfRuntime, currentScene.nodes[i], null);
  1635. }
  1636. }
  1637. }
  1638. }
  1639. }
  1640. GLTFLoader.Extensions = {};
  1641. /** @internal */
  1642. export class GLTFLoaderExtension {
  1643. constructor(name) {
  1644. this._name = name;
  1645. }
  1646. get name() {
  1647. return this._name;
  1648. }
  1649. /**
  1650. * Defines an override for loading the runtime
  1651. * Return true to stop further extensions from loading the runtime
  1652. * @param scene
  1653. * @param data
  1654. * @param rootUrl
  1655. * @param onSuccess
  1656. * @param onError
  1657. * @returns true to stop further extensions from loading the runtime
  1658. */
  1659. loadRuntimeAsync(scene, data, rootUrl, onSuccess, onError) {
  1660. return false;
  1661. }
  1662. /**
  1663. * Defines an onverride for creating gltf runtime
  1664. * Return true to stop further extensions from creating the runtime
  1665. * @param gltfRuntime
  1666. * @param onSuccess
  1667. * @param onError
  1668. * @returns true to stop further extensions from creating the runtime
  1669. */
  1670. loadRuntimeExtensionsAsync(gltfRuntime, onSuccess, onError) {
  1671. return false;
  1672. }
  1673. /**
  1674. * Defines an override for loading buffers
  1675. * Return true to stop further extensions from loading this buffer
  1676. * @param gltfRuntime
  1677. * @param id
  1678. * @param onSuccess
  1679. * @param onError
  1680. * @param onProgress
  1681. * @returns true to stop further extensions from loading this buffer
  1682. */
  1683. loadBufferAsync(gltfRuntime, id, onSuccess, onError, onProgress) {
  1684. return false;
  1685. }
  1686. /**
  1687. * Defines an override for loading texture buffers
  1688. * Return true to stop further extensions from loading this texture data
  1689. * @param gltfRuntime
  1690. * @param id
  1691. * @param onSuccess
  1692. * @param onError
  1693. * @returns true to stop further extensions from loading this texture data
  1694. */
  1695. loadTextureBufferAsync(gltfRuntime, id, onSuccess, onError) {
  1696. return false;
  1697. }
  1698. /**
  1699. * Defines an override for creating textures
  1700. * Return true to stop further extensions from loading this texture
  1701. * @param gltfRuntime
  1702. * @param id
  1703. * @param buffer
  1704. * @param onSuccess
  1705. * @param onError
  1706. * @returns true to stop further extensions from loading this texture
  1707. */
  1708. createTextureAsync(gltfRuntime, id, buffer, onSuccess, onError) {
  1709. return false;
  1710. }
  1711. /**
  1712. * Defines an override for loading shader strings
  1713. * Return true to stop further extensions from loading this shader data
  1714. * @param gltfRuntime
  1715. * @param id
  1716. * @param onSuccess
  1717. * @param onError
  1718. * @returns true to stop further extensions from loading this shader data
  1719. */
  1720. loadShaderStringAsync(gltfRuntime, id, onSuccess, onError) {
  1721. return false;
  1722. }
  1723. /**
  1724. * Defines an override for loading materials
  1725. * Return true to stop further extensions from loading this material
  1726. * @param gltfRuntime
  1727. * @param id
  1728. * @param onSuccess
  1729. * @param onError
  1730. * @returns true to stop further extensions from loading this material
  1731. */
  1732. loadMaterialAsync(gltfRuntime, id, onSuccess, onError) {
  1733. return false;
  1734. }
  1735. // ---------
  1736. // Utilities
  1737. // ---------
  1738. static LoadRuntimeAsync(scene, data, rootUrl, onSuccess, onError) {
  1739. GLTFLoaderExtension._ApplyExtensions((loaderExtension) => {
  1740. return loaderExtension.loadRuntimeAsync(scene, data, rootUrl, onSuccess, onError);
  1741. }, () => {
  1742. setTimeout(() => {
  1743. if (!onSuccess) {
  1744. return;
  1745. }
  1746. onSuccess(GLTFLoaderBase.CreateRuntime(data.json, scene, rootUrl));
  1747. });
  1748. });
  1749. }
  1750. static LoadRuntimeExtensionsAsync(gltfRuntime, onSuccess, onError) {
  1751. GLTFLoaderExtension._ApplyExtensions((loaderExtension) => {
  1752. return loaderExtension.loadRuntimeExtensionsAsync(gltfRuntime, onSuccess, onError);
  1753. }, () => {
  1754. setTimeout(() => {
  1755. onSuccess();
  1756. });
  1757. });
  1758. }
  1759. static LoadBufferAsync(gltfRuntime, id, onSuccess, onError, onProgress) {
  1760. GLTFLoaderExtension._ApplyExtensions((loaderExtension) => {
  1761. return loaderExtension.loadBufferAsync(gltfRuntime, id, onSuccess, onError, onProgress);
  1762. }, () => {
  1763. GLTFLoaderBase.LoadBufferAsync(gltfRuntime, id, onSuccess, onError, onProgress);
  1764. });
  1765. }
  1766. static LoadTextureAsync(gltfRuntime, id, onSuccess, onError) {
  1767. GLTFLoaderExtension._LoadTextureBufferAsync(gltfRuntime, id, (buffer) => {
  1768. if (buffer) {
  1769. GLTFLoaderExtension._CreateTextureAsync(gltfRuntime, id, buffer, onSuccess, onError);
  1770. }
  1771. }, onError);
  1772. }
  1773. static LoadShaderStringAsync(gltfRuntime, id, onSuccess, onError) {
  1774. GLTFLoaderExtension._ApplyExtensions((loaderExtension) => {
  1775. return loaderExtension.loadShaderStringAsync(gltfRuntime, id, onSuccess, onError);
  1776. }, () => {
  1777. GLTFLoaderBase.LoadShaderStringAsync(gltfRuntime, id, onSuccess, onError);
  1778. });
  1779. }
  1780. static LoadMaterialAsync(gltfRuntime, id, onSuccess, onError) {
  1781. GLTFLoaderExtension._ApplyExtensions((loaderExtension) => {
  1782. return loaderExtension.loadMaterialAsync(gltfRuntime, id, onSuccess, onError);
  1783. }, () => {
  1784. GLTFLoaderBase.LoadMaterialAsync(gltfRuntime, id, onSuccess, onError);
  1785. });
  1786. }
  1787. static _LoadTextureBufferAsync(gltfRuntime, id, onSuccess, onError) {
  1788. GLTFLoaderExtension._ApplyExtensions((loaderExtension) => {
  1789. return loaderExtension.loadTextureBufferAsync(gltfRuntime, id, onSuccess, onError);
  1790. }, () => {
  1791. GLTFLoaderBase.LoadTextureBufferAsync(gltfRuntime, id, onSuccess, onError);
  1792. });
  1793. }
  1794. static _CreateTextureAsync(gltfRuntime, id, buffer, onSuccess, onError) {
  1795. GLTFLoaderExtension._ApplyExtensions((loaderExtension) => {
  1796. return loaderExtension.createTextureAsync(gltfRuntime, id, buffer, onSuccess, onError);
  1797. }, () => {
  1798. GLTFLoaderBase.CreateTextureAsync(gltfRuntime, id, buffer, onSuccess);
  1799. });
  1800. }
  1801. static _ApplyExtensions(func, defaultFunc) {
  1802. for (const extensionName in GLTFLoader.Extensions) {
  1803. const loaderExtension = GLTFLoader.Extensions[extensionName];
  1804. if (func(loaderExtension)) {
  1805. return;
  1806. }
  1807. }
  1808. defaultFunc();
  1809. }
  1810. }
  1811. GLTFFileLoader._CreateGLTF1Loader = () => new GLTFLoader();
  1812. //# sourceMappingURL=glTFLoader.js.map