babylon.glTFFileLoader.ts 64 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710
  1. module BABYLON {
  2. /**
  3. * Tokenizer. Used for shaders compatibility
  4. * Automatically map world, view, projection, worldViewProjection, attributes and so on
  5. */
  6. enum ETokenType {
  7. IDENTIFIER = 1,
  8. UNKNOWN = 2,
  9. END_OF_INPUT = 3
  10. }
  11. class Tokenizer {
  12. private _toParse: string;
  13. private _pos: number = 0;
  14. private _maxPos: number;
  15. public currentToken: ETokenType;
  16. public currentIdentifier: string;
  17. public currentString: string;
  18. public isLetterOrDigitPattern: RegExp = /^[a-zA-Z0-9]+$/;
  19. constructor(toParse: string) {
  20. this._toParse = toParse;
  21. this._maxPos = toParse.length;
  22. }
  23. public getNextToken(): ETokenType {
  24. if (this.isEnd()) return ETokenType.END_OF_INPUT;
  25. this.currentString = this.read();
  26. this.currentToken = ETokenType.UNKNOWN;
  27. if (this.currentString === "_" || this.isLetterOrDigitPattern.test(this.currentString)) {
  28. this.currentToken = ETokenType.IDENTIFIER;
  29. this.currentIdentifier = this.currentString;
  30. while (!this.isEnd() && (this.isLetterOrDigitPattern.test(this.currentString = this.peek()) || this.currentString === "_")) {
  31. this.currentIdentifier += this.currentString;
  32. this.forward();
  33. }
  34. }
  35. return this.currentToken;
  36. }
  37. public peek(): string {
  38. return this._toParse[this._pos];
  39. }
  40. public read(): string {
  41. return this._toParse[this._pos++];
  42. }
  43. public forward(): void {
  44. this._pos++;
  45. }
  46. public isEnd(): boolean {
  47. return this._pos >= this._maxPos;
  48. }
  49. }
  50. /**
  51. * Values
  52. */
  53. var glTFTransforms = ["MODEL", "VIEW", "PROJECTION", "MODELVIEW", "MODELVIEWPROJECTION", "JOINTMATRIX"];
  54. var babylonTransforms = ["world", "view", "projection", "worldView", "worldViewProjection", "mBones"];
  55. var glTFAnimationPaths = ["translation", "rotation", "scale"];
  56. var babylonAnimationPaths = ["position", "rotationQuaternion", "scaling"];
  57. /**
  58. * Parse
  59. */
  60. var parseBuffers = (parsedBuffers: any, gltfRuntime: IGLTFRuntime) => {
  61. for (var buf in parsedBuffers) {
  62. var parsedBuffer = parsedBuffers[buf];
  63. gltfRuntime.buffers[buf] = parsedBuffer;
  64. gltfRuntime.buffersCount++;
  65. }
  66. };
  67. var parseShaders = (parsedShaders: any, gltfRuntime: IGLTFRuntime) => {
  68. for (var sha in parsedShaders) {
  69. var parsedShader = parsedShaders[sha];
  70. gltfRuntime.shaders[sha] = parsedShader;
  71. gltfRuntime.shaderscount++;
  72. }
  73. };
  74. var parseObject = (parsedObjects: any, runtimeProperty: string, gltfRuntime: IGLTFRuntime) => {
  75. for (var object in parsedObjects) {
  76. var parsedObject = parsedObjects[object];
  77. gltfRuntime[runtimeProperty][object] = parsedObject;
  78. }
  79. };
  80. /**
  81. * Utils
  82. */
  83. var normalizeUVs = (buffer: any) => {
  84. if (!buffer) {
  85. return;
  86. }
  87. for (var i = 0; i < buffer.length / 2; i++) {
  88. buffer[i * 2 + 1] = 1.0 - buffer[i * 2 + 1];
  89. }
  90. };
  91. var replaceInString = (str: string, searchValue: string, replaceValue: string) => {
  92. while (str.indexOf(searchValue) !== -1) {
  93. str = str.replace(searchValue, replaceValue);
  94. }
  95. return str;
  96. };
  97. var getAttribute = (attributeParameter: IGLTFTechniqueParameter) => {
  98. if (attributeParameter.semantic === "NORMAL") {
  99. return "normal";
  100. } else if (attributeParameter.semantic === "POSITION") {
  101. return "position";
  102. } else if (attributeParameter.semantic === "JOINT") {
  103. return "matricesIndices";
  104. } else if (attributeParameter.semantic === "WEIGHT") {
  105. return "matricesWeights";
  106. } else if (attributeParameter.semantic === "COLOR") {
  107. return "color";
  108. } else if (attributeParameter.semantic.indexOf("TEXCOORD_") !== -1) {
  109. var channel = Number(attributeParameter.semantic.split("_")[1]);
  110. return "uv" + (channel === 0 ? "" : channel + 1);
  111. }
  112. };
  113. /**
  114. * Returns the animation path (glTF -> Babylon)
  115. */
  116. var getAnimationPath = (path: string): string => {
  117. var index = glTFAnimationPaths.indexOf(path);
  118. if (index !== -1) {
  119. return babylonAnimationPaths[index];
  120. }
  121. return path;
  122. };
  123. /**
  124. * Loads and creates animations
  125. */
  126. var loadAnimations = (gltfRuntime: IGLTFRuntime) => {
  127. for (var anim in gltfRuntime.animations) {
  128. var animation: IGLTFAnimation = gltfRuntime.animations[anim];
  129. var lastAnimation: Animation = null;
  130. for (var i = 0; i < animation.channels.length; i++) {
  131. // Get parameters and load buffers
  132. var channel = animation.channels[i];
  133. var sampler: IGLTFAnimationSampler = animation.samplers[channel.sampler];
  134. if (!sampler) {
  135. continue;
  136. }
  137. var inputData = animation.parameters[sampler.input];
  138. var outputData = animation.parameters[sampler.output];
  139. var bufferInput = GLTFUtils.GetBufferFromAccessor(gltfRuntime, gltfRuntime.accessors[inputData]);
  140. var bufferOutput = GLTFUtils.GetBufferFromAccessor(gltfRuntime, gltfRuntime.accessors[outputData]);
  141. var targetID = channel.target.id;
  142. var targetNode: any = gltfRuntime.scene.getNodeByID(targetID);
  143. if (targetNode === null) {
  144. Tools.Warn("Creating animation named " + anim + ". But cannot find node named " + targetID + " to attach to");
  145. continue;
  146. }
  147. var isBone = targetNode instanceof Bone;
  148. // Get target path (position, rotation or scaling)
  149. var targetPath = channel.target.path;
  150. var targetPathIndex = glTFAnimationPaths.indexOf(targetPath);
  151. if (targetPathIndex !== -1) {
  152. targetPath = babylonAnimationPaths[targetPathIndex];
  153. }
  154. // Determine animation type
  155. var animationType = Animation.ANIMATIONTYPE_MATRIX;
  156. if (!isBone) {
  157. if (targetPath === "rotationQuaternion") {
  158. animationType = Animation.ANIMATIONTYPE_QUATERNION;
  159. targetNode.rotationQuaternion = new Quaternion();
  160. }
  161. else {
  162. animationType = Animation.ANIMATIONTYPE_VECTOR3;
  163. }
  164. }
  165. // Create animation and key frames
  166. var babylonAnimation: Animation = null;
  167. var keys = [];
  168. var arrayOffset = 0;
  169. var modifyKey = false;
  170. if (isBone && lastAnimation && lastAnimation.getKeys().length === bufferInput.length) {
  171. babylonAnimation = lastAnimation;
  172. modifyKey = true;
  173. }
  174. if (!modifyKey) {
  175. babylonAnimation = new Animation(anim, isBone ? "_matrix" : targetPath, 1, animationType, Animation.ANIMATIONLOOPMODE_CYCLE);
  176. }
  177. // For each frame
  178. for (var j = 0; j < bufferInput.length; j++) {
  179. var value: any = null;
  180. if (targetPath === "rotationQuaternion") { // VEC4
  181. value = Quaternion.FromArray([bufferOutput[arrayOffset], bufferOutput[arrayOffset + 1], bufferOutput[arrayOffset + 2], bufferOutput[arrayOffset + 3]]);
  182. arrayOffset += 4;
  183. }
  184. else { // Position and scaling are VEC3
  185. value = Vector3.FromArray([bufferOutput[arrayOffset], bufferOutput[arrayOffset + 1], bufferOutput[arrayOffset + 2]]);
  186. arrayOffset += 3;
  187. }
  188. if (isBone) {
  189. var bone = <Bone>targetNode;
  190. var translation = Vector3.Zero();
  191. var rotationQuaternion = new Quaternion();
  192. var scaling = Vector3.Zero();
  193. // Warning on decompose
  194. var mat = bone.getBaseMatrix();
  195. if (modifyKey) {
  196. mat = lastAnimation.getKeys()[j].value;
  197. }
  198. mat.decompose(scaling, rotationQuaternion, translation);
  199. if (targetPath === "position") {
  200. translation = value;
  201. }
  202. else if (targetPath === "rotationQuaternion") {
  203. rotationQuaternion = value;
  204. // Y is Up
  205. if (GLTFFileLoader.MakeYUP) {
  206. rotationQuaternion = rotationQuaternion.multiply(new Quaternion(-0.707107, 0, 0, 0.707107));
  207. }
  208. }
  209. else {
  210. scaling = value;
  211. }
  212. value = Matrix.Compose(scaling, rotationQuaternion, translation);
  213. }
  214. if (!modifyKey) {
  215. keys.push({
  216. frame: bufferInput[j],
  217. value: value
  218. });
  219. }
  220. else {
  221. lastAnimation.getKeys()[j].value = value;
  222. }
  223. }
  224. // Finish
  225. if (!modifyKey) {
  226. babylonAnimation.setKeys(keys);
  227. targetNode.animations.push(babylonAnimation);
  228. }
  229. lastAnimation = babylonAnimation;
  230. gltfRuntime.scene.stopAnimation(targetNode);
  231. gltfRuntime.scene.beginAnimation(targetNode, 0, bufferInput[bufferInput.length - 1], true, 1.0);
  232. }
  233. }
  234. };
  235. /**
  236. * Returns the bones transformation matrix
  237. */
  238. var configureBoneTransformation = (node: IGLTFNode): Matrix => {
  239. var mat: Matrix = null;
  240. if (node.translation && node.rotation && node.scale) {
  241. var scale = Vector3.FromArray(node.scale);
  242. var rotation = Quaternion.FromArray(node.rotation);
  243. var position = Vector3.FromArray(node.translation);
  244. // Y is Up
  245. if (GLTFFileLoader.MakeYUP) {
  246. rotation = rotation.multiply(new Quaternion(-0.707107, 0, 0, 0.707107));
  247. }
  248. mat = Matrix.Compose(scale, rotation, position);
  249. }
  250. else {
  251. mat = Matrix.FromArray(node.matrix);
  252. }
  253. return mat;
  254. };
  255. /**
  256. * Returns the parent bone
  257. */
  258. var getParentBone = (gltfRuntime: IGLTFRuntime, skins: IGLTFSkins, jointName: string, newSkeleton: Skeleton): Bone => {
  259. // Try to find
  260. for (var i = 0; i < newSkeleton.bones.length; i++) {
  261. if (newSkeleton.bones[i].id === jointName) {
  262. return newSkeleton.bones[i];
  263. }
  264. }
  265. // Not found, search in gltf nodes
  266. var nodes = gltfRuntime.nodes;
  267. for (var nde in nodes) {
  268. var node: IGLTFNode = nodes[nde];
  269. if (!node.jointName) {
  270. continue;
  271. }
  272. var children = node.children;
  273. for (var i = 0; i < children.length; i++) {
  274. var child: IGLTFNode = gltfRuntime.nodes[children[i]];
  275. if (!child.jointName) {
  276. continue;
  277. }
  278. if (child.jointName === jointName) {
  279. var mat = configureBoneTransformation(node);
  280. var bone = new Bone(node.name, newSkeleton, getParentBone(gltfRuntime, skins, node.jointName, newSkeleton), mat);
  281. bone.id = nde;
  282. return bone;
  283. }
  284. }
  285. }
  286. return null;
  287. }
  288. /**
  289. * Returns the appropriate root node
  290. */
  291. var getNodeToRoot = (nodesToRoot: INodeToRoot[], id: string): Bone => {
  292. for (var i = 0; i < nodesToRoot.length; i++) {
  293. var nodeToRoot = nodesToRoot[i];
  294. for (var j = 0; j < nodeToRoot.node.children.length; j++) {
  295. var child = nodeToRoot.node.children[j];
  296. if (child === id) {
  297. return nodeToRoot.bone;
  298. }
  299. }
  300. }
  301. return null;
  302. };
  303. /**
  304. * Returns the node with the joint name
  305. */
  306. var getJointNode = (gltfRuntime: IGLTFRuntime, jointName: string): IJointNode => {
  307. var nodes = gltfRuntime.nodes;
  308. var node: IGLTFNode = nodes[jointName];
  309. if (node) {
  310. return {
  311. node: node,
  312. id: jointName
  313. };
  314. }
  315. for (var nde in nodes) {
  316. node = nodes[nde];
  317. if (node.jointName === jointName) {
  318. return {
  319. node: node,
  320. id: nde
  321. };
  322. }
  323. }
  324. return null;
  325. }
  326. /**
  327. * Checks if a nodes is in joints
  328. */
  329. var nodeIsInJoints = (skins: IGLTFSkins, id: string): boolean => {
  330. for (var i = 0; i < skins.jointNames.length; i++) {
  331. if (skins.jointNames[i] === id) {
  332. return true;
  333. }
  334. }
  335. return false;
  336. }
  337. /**
  338. * Fills the nodes to root for bones and builds hierarchy
  339. */
  340. var getNodesToRoot = (gltfRuntime: IGLTFRuntime, newSkeleton: Skeleton, skins: IGLTFSkins, nodesToRoot: INodeToRoot[]) => {
  341. // Creates nodes for root
  342. for (var nde in gltfRuntime.nodes) {
  343. var node: IGLTFNode = gltfRuntime.nodes[nde];
  344. var id = nde;
  345. if (!node.jointName || nodeIsInJoints(skins, node.jointName)) {
  346. continue;
  347. }
  348. // Create node to root bone
  349. var mat = configureBoneTransformation(node);
  350. var bone = new Bone(node.name, newSkeleton, null, mat);
  351. bone.id = id;
  352. nodesToRoot.push({ bone: bone, node: node, id: id });
  353. }
  354. // Parenting
  355. for (var i = 0; i < nodesToRoot.length; i++) {
  356. var nodeToRoot = nodesToRoot[i];
  357. var children = nodeToRoot.node.children;
  358. for (var j = 0; j < children.length; j++) {
  359. var child: INodeToRoot = null;
  360. for (var k = 0; k < nodesToRoot.length; k++) {
  361. if (nodesToRoot[k].id === children[j]) {
  362. child = nodesToRoot[k];
  363. break;
  364. }
  365. }
  366. if (child) {
  367. (<any>child.bone)._parent = nodeToRoot.bone;
  368. nodeToRoot.bone.children.push(child.bone);
  369. }
  370. }
  371. }
  372. };
  373. var printMat = (m: Float32Array) => {
  374. console.log(
  375. m[0] + "\t" + m[1] + "\t" + m[2] + "\t" + m[3] + "\n" +
  376. m[4] + "\t" + m[5] + "\t" + m[6] + "\t" + m[7] + "\n" +
  377. m[8] + "\t" + m[9] + "\t" + m[10] + "\t" + m[11] + "\n" +
  378. m[12] + "\t" + m[13] + "\t" + m[14] + "\t" + m[15] + "\n"
  379. );
  380. }
  381. /**
  382. * Imports a skeleton
  383. */
  384. var importSkeleton = (gltfRuntime: IGLTFRuntime, skins: IGLTFSkins, mesh: Mesh, newSkeleton: Skeleton, id: string): Skeleton => {
  385. if (!newSkeleton) {
  386. newSkeleton = new Skeleton(skins.name, "", gltfRuntime.scene);
  387. }
  388. if (!skins.babylonSkeleton) {
  389. return newSkeleton;
  390. }
  391. // Matrices
  392. var accessor = gltfRuntime.accessors[skins.inverseBindMatrices];
  393. var buffer = GLTFUtils.GetBufferFromAccessor(gltfRuntime, accessor);
  394. var bindShapeMatrix = Matrix.FromArray(skins.bindShapeMatrix);
  395. // Find the root bones
  396. var nodesToRoot: INodeToRoot[] = [];
  397. var nodesToRootToAdd: Bone[] = [];
  398. getNodesToRoot(gltfRuntime, newSkeleton, skins, nodesToRoot);
  399. newSkeleton.bones = [];
  400. if (nodesToRoot.length === 0) {
  401. newSkeleton.needInitialSkinMatrix = true;
  402. }
  403. // Joints
  404. for (var i = 0; i < skins.jointNames.length; i++) {
  405. var jointNode = getJointNode(gltfRuntime, skins.jointNames[i]);
  406. var node = jointNode.node;
  407. if (!node) {
  408. Tools.Warn("Joint named " + skins.jointNames[i] + " does not exist");
  409. continue;
  410. }
  411. var id = jointNode.id;
  412. // Optimize, if the bone already exists...
  413. var existingBone = gltfRuntime.scene.getBoneByID(id);
  414. if (existingBone) {
  415. newSkeleton.bones.push(existingBone);
  416. continue;
  417. }
  418. // Check if node already exists
  419. var foundBone = false;
  420. for (var j = 0; j < newSkeleton.bones.length; j++) {
  421. if (newSkeleton.bones[j].id === id) {
  422. foundBone = true;
  423. break;
  424. }
  425. }
  426. if (foundBone) {
  427. continue;
  428. }
  429. // Search for parent bone
  430. var parentBone: Bone = null;
  431. for (var j = 0; j < i; j++) {
  432. var joint: IGLTFNode = getJointNode(gltfRuntime, skins.jointNames[j]).node;
  433. if (!joint) {
  434. Tools.Warn("Joint named " + skins.jointNames[j] + " does not exist when looking for parent");
  435. continue;
  436. }
  437. var children = joint.children;
  438. foundBone = false;
  439. for (var k = 0; k < children.length; k++) {
  440. if (children[k] === id) {
  441. parentBone = getParentBone(gltfRuntime, skins, skins.jointNames[j], newSkeleton);
  442. foundBone = true;
  443. break;
  444. }
  445. }
  446. if (foundBone) {
  447. break;
  448. }
  449. }
  450. // Create bone
  451. var mat = configureBoneTransformation(node);
  452. if (!parentBone && nodesToRoot.length > 0) {
  453. parentBone = getNodeToRoot(nodesToRoot, id);
  454. if (parentBone) {
  455. if (nodesToRootToAdd.indexOf(parentBone) === -1) {
  456. nodesToRootToAdd.push(parentBone);
  457. }
  458. }
  459. }
  460. if (!parentBone && nodesToRoot.length === 0) {
  461. var inverseBindMatrix = Matrix.FromArray(buffer, i * 16);
  462. var invertMesh = Matrix.Invert(mesh.getWorldMatrix());
  463. mat = mat.multiply(mesh.getWorldMatrix());
  464. }
  465. var bone = new Bone(node.name, newSkeleton, parentBone, mat);
  466. bone.id = id;
  467. }
  468. // Polish
  469. var bones = newSkeleton.bones;
  470. newSkeleton.bones = [];
  471. for (var i = 0; i < skins.jointNames.length; i++) {
  472. var jointNode: IJointNode = getJointNode(gltfRuntime, skins.jointNames[i]);
  473. if (!jointNode) {
  474. continue;
  475. }
  476. for (var j = 0; j < bones.length; j++) {
  477. if (bones[j].id === jointNode.id) {
  478. newSkeleton.bones.push(bones[j]);
  479. break;
  480. }
  481. }
  482. }
  483. // Finish
  484. newSkeleton.prepare();
  485. for (var i = 0; i < nodesToRootToAdd.length; i++) {
  486. newSkeleton.bones.push(nodesToRootToAdd[i]);
  487. }
  488. return newSkeleton;
  489. };
  490. /**
  491. * Imports a mesh and its geometries
  492. */
  493. var importMesh = (gltfRuntime: IGLTFRuntime, node: IGLTFNode, meshes: string[], id: string, newMesh: Mesh): Mesh => {
  494. if (!newMesh) {
  495. newMesh = new Mesh(node.name, gltfRuntime.scene);
  496. newMesh.id = id;
  497. }
  498. if (!node.babylonNode) {
  499. return newMesh;
  500. }
  501. var multiMat = new MultiMaterial("multimat" + id, gltfRuntime.scene);
  502. newMesh.material = multiMat;
  503. var vertexData = new VertexData();
  504. var geometry = new Geometry(id, gltfRuntime.scene, vertexData, false, newMesh);
  505. var verticesStarts = [];
  506. var verticesCounts = [];
  507. var indexStarts = [];
  508. var indexCounts = [];
  509. for (var meshIndex = 0; meshIndex < meshes.length; meshIndex++) {
  510. var meshID = meshes[meshIndex];
  511. var mesh: IGLTFMesh = gltfRuntime.meshes[meshID];
  512. if (!mesh) {
  513. continue;
  514. }
  515. // Positions, normals and UVs
  516. for (var i = 0; i < mesh.primitives.length; i++) {
  517. // Temporary vertex data
  518. var tempVertexData = new VertexData();
  519. var primitive = mesh.primitives[i];
  520. if (primitive.mode !== 4) {
  521. //continue;
  522. }
  523. var attributes = primitive.attributes;
  524. var accessor: IGLTFAccessor = null;
  525. var buffer: any = null;
  526. // Set positions, normal and uvs
  527. for (var semantic in attributes) {
  528. // Link accessor and buffer view
  529. accessor = gltfRuntime.accessors[attributes[semantic]];
  530. buffer = GLTFUtils.GetBufferFromAccessor(gltfRuntime, accessor);
  531. if (semantic === "NORMAL") {
  532. tempVertexData.normals = new Float32Array(buffer.length);
  533. (<Float32Array>tempVertexData.normals).set(buffer);
  534. }
  535. else if (semantic === "POSITION") {
  536. if (GLTFFileLoader.HomogeneousCoordinates) {
  537. tempVertexData.positions = new Float32Array(buffer.length - buffer.length / 4);
  538. for (var j = 0; j < buffer.length; j += 4) {
  539. tempVertexData.positions[j] = buffer[j];
  540. tempVertexData.positions[j + 1] = buffer[j + 1];
  541. tempVertexData.positions[j + 2] = buffer[j + 2];
  542. }
  543. }
  544. else {
  545. tempVertexData.positions = new Float32Array(buffer.length);
  546. (<Float32Array>tempVertexData.positions).set(buffer);
  547. }
  548. verticesCounts.push(tempVertexData.positions.length);
  549. }
  550. else if (semantic.indexOf("TEXCOORD_") !== -1) {
  551. var channel = Number(semantic.split("_")[1]);
  552. var uvKind = VertexBuffer.UVKind + (channel === 0 ? "" : (channel + 1));
  553. var uvs = new Float32Array(buffer.length);
  554. (<Float32Array>uvs).set(buffer);
  555. normalizeUVs(uvs);
  556. tempVertexData.set(uvs, uvKind);
  557. }
  558. else if (semantic === "JOINT") {
  559. tempVertexData.matricesIndices = new Float32Array(buffer.length);
  560. (<Float32Array>tempVertexData.matricesIndices).set(buffer);
  561. }
  562. else if (semantic === "WEIGHT") {
  563. tempVertexData.matricesWeights = new Float32Array(buffer.length);
  564. (<Float32Array>tempVertexData.matricesWeights).set(buffer);
  565. }
  566. else if (semantic === "COLOR") {
  567. tempVertexData.colors = new Float32Array(buffer.length);
  568. (<Float32Array>tempVertexData.colors).set(buffer);
  569. }
  570. }
  571. // Indices
  572. accessor = gltfRuntime.accessors[primitive.indices];
  573. buffer = GLTFUtils.GetBufferFromAccessor(gltfRuntime, accessor);
  574. tempVertexData.indices = new Int32Array(buffer.length);
  575. (<Float32Array>tempVertexData.indices).set(buffer);
  576. indexCounts.push(tempVertexData.indices.length);
  577. vertexData.merge(tempVertexData);
  578. tempVertexData = undefined;
  579. // Sub material
  580. var material = gltfRuntime.scene.getMaterialByID(primitive.material);
  581. multiMat.subMaterials.push(material === null ? gltfRuntime.scene.defaultMaterial : material);
  582. // Update vertices start and index start
  583. verticesStarts.push(verticesStarts.length === 0 ? 0 : verticesStarts[verticesStarts.length - 1] + verticesCounts[verticesCounts.length - 2]);
  584. indexStarts.push(indexStarts.length === 0 ? 0 : indexStarts[indexStarts.length - 1] + indexCounts[indexCounts.length - 2]);
  585. }
  586. }
  587. // Apply geometry
  588. geometry.setAllVerticesData(vertexData, false);
  589. newMesh.computeWorldMatrix(true);
  590. // Apply submeshes
  591. newMesh.subMeshes = [];
  592. var index = 0;
  593. for (var meshIndex = 0; meshIndex < meshes.length; meshIndex++) {
  594. var meshID = meshes[meshIndex];
  595. var mesh: IGLTFMesh = gltfRuntime.meshes[meshID];
  596. if (!mesh) {
  597. continue;
  598. }
  599. for (var i = 0; i < mesh.primitives.length; i++) {
  600. if (mesh.primitives[i].mode !== 4) {
  601. //continue;
  602. }
  603. var subMesh = new SubMesh(index, verticesStarts[index], verticesCounts[index], indexStarts[index], indexCounts[index], newMesh, newMesh, true);
  604. index++;
  605. }
  606. }
  607. // Finish
  608. return newMesh;
  609. };
  610. /**
  611. * Configure node transformation from position, rotation and scaling
  612. */
  613. var configureNode = (newNode: any, position: Vector3, rotation: Quaternion, scaling: Vector3) => {
  614. if (newNode.position) {
  615. newNode.position = position;
  616. }
  617. if (newNode.rotationQuaternion || newNode.rotation) {
  618. newNode.rotationQuaternion = rotation;
  619. }
  620. if (newNode.scaling) {
  621. newNode.scaling = scaling;
  622. }
  623. };
  624. /**
  625. * Configures node from transformation matrix
  626. */
  627. var configureNodeFromMatrix = (newNode: any, node: IGLTFNode) => {
  628. if (node.matrix) {
  629. var position = new Vector3(0, 0, 0);
  630. var rotation = new Quaternion();
  631. var scaling = new Vector3(0, 0, 0);
  632. var mat = Matrix.FromArray(node.matrix);
  633. mat.decompose(scaling, rotation, position);
  634. // Y is Up
  635. if (GLTFFileLoader.MakeYUP) {
  636. rotation = rotation.multiply(new Quaternion(-0.707107, 0, 0, 0.707107));
  637. }
  638. configureNode(newNode, position, rotation, scaling);
  639. if (newNode instanceof TargetCamera) {
  640. (<TargetCamera>newNode).setTarget(Vector3.Zero());
  641. }
  642. }
  643. else {
  644. configureNode(newNode, Vector3.FromArray(node.translation), Quaternion.FromArray(node.rotation), Vector3.FromArray(node.scale));
  645. }
  646. };
  647. /**
  648. * Imports a node
  649. */
  650. var importNode = (gltfRuntime: IGLTFRuntime, node: IGLTFNode, id: string): Node => {
  651. var lastNode: Node = null;
  652. if (gltfRuntime.importOnlyMeshes && (node.skin || node.meshes)) {
  653. if (gltfRuntime.importMeshesNames.length > 0 && gltfRuntime.importMeshesNames.indexOf(node.name) === -1) {
  654. return null;
  655. }
  656. }
  657. // Meshes
  658. if (node.skin) {
  659. if (node.meshes) {
  660. var skin: IGLTFSkins = gltfRuntime.skins[node.skin];
  661. var newMesh = importMesh(gltfRuntime, node, node.meshes, id, <Mesh>node.babylonNode);
  662. newMesh.skeleton = gltfRuntime.scene.getLastSkeletonByID(node.skin);
  663. if (newMesh.skeleton === null) {
  664. newMesh.skeleton = importSkeleton(gltfRuntime, skin, newMesh, skin.babylonSkeleton, node.skin);
  665. if (!skin.babylonSkeleton) {
  666. skin.babylonSkeleton = newMesh.skeleton;
  667. }
  668. }
  669. if (newMesh.skeleton !== null) {
  670. newMesh.useBones = true;
  671. }
  672. lastNode = newMesh;
  673. }
  674. }
  675. else if (node.meshes) {
  676. /**
  677. * Improve meshes property
  678. */
  679. var newMesh = importMesh(gltfRuntime, node, node.mesh ? [node.mesh] : node.meshes, id, <Mesh>node.babylonNode);
  680. lastNode = newMesh;
  681. }
  682. // Lights
  683. else if (node.light && !node.babylonNode && !gltfRuntime.importOnlyMeshes) {
  684. var light: IGLTFLight = gltfRuntime.lights[node.light];
  685. if (light) {
  686. if (light.type === "ambient") {
  687. var ambienLight: IGLTFAmbienLight = light[light.type];
  688. var hemiLight = new HemisphericLight(node.light, Vector3.Zero(), gltfRuntime.scene);
  689. hemiLight.name = node.name;
  690. if (ambienLight.color) {
  691. hemiLight.diffuse = Color3.FromArray(ambienLight.color);
  692. }
  693. lastNode = hemiLight;
  694. }
  695. else if (light.type === "directional") {
  696. var directionalLight: IGLTFDirectionalLight = light[light.type];
  697. var dirLight = new DirectionalLight(node.light, Vector3.Zero(), gltfRuntime.scene);
  698. dirLight.name = node.name;
  699. if (directionalLight.color) {
  700. dirLight.diffuse = Color3.FromArray(directionalLight.color);
  701. }
  702. lastNode = dirLight;
  703. }
  704. else if (light.type === "point") {
  705. var pointLight: IGLTFPointLight = light[light.type];
  706. var ptLight = new PointLight(node.light, Vector3.Zero(), gltfRuntime.scene);
  707. ptLight.name = node.name;
  708. if (pointLight.color) {
  709. ptLight.diffuse = Color3.FromArray(pointLight.color);
  710. }
  711. lastNode = ptLight;
  712. }
  713. else if (light.type === "spot") {
  714. var spotLight: IGLTFSpotLight = light[light.type];
  715. var spLight = new SpotLight(node.light, Vector3.Zero(), Vector3.Zero(), 0, 0, gltfRuntime.scene);
  716. spLight.name = node.name;
  717. if (spotLight.color) {
  718. spLight.diffuse = Color3.FromArray(spotLight.color);
  719. }
  720. if (spotLight.fallOfAngle) {
  721. spLight.angle = spotLight.fallOfAngle;
  722. }
  723. if (spotLight.fallOffExponent) {
  724. spLight.exponent = spotLight.fallOffExponent;
  725. }
  726. lastNode = spLight;
  727. }
  728. }
  729. }
  730. // Cameras
  731. else if (node.camera && !node.babylonNode && !gltfRuntime.importOnlyMeshes) {
  732. var camera: IGLTFCamera = gltfRuntime.cameras[node.camera];
  733. if (camera) {
  734. if (camera.type === "orthographic") {
  735. var orthographicCamera: IGLTFCameraOrthographic = camera[camera.type];
  736. var orthoCamera = new FreeCamera(node.camera, Vector3.Zero(), gltfRuntime.scene);
  737. orthoCamera.name = node.name;
  738. orthoCamera.mode = Camera.ORTHOGRAPHIC_CAMERA;
  739. orthoCamera.attachControl(gltfRuntime.scene.getEngine().getRenderingCanvas());
  740. lastNode = orthoCamera;
  741. }
  742. else if (camera.type === "perspective") {
  743. var perspectiveCamera: IGLTFCameraPerspective = camera[camera.type];
  744. var persCamera = new FreeCamera(node.camera, Vector3.Zero(), gltfRuntime.scene);
  745. persCamera.name = node.name;
  746. persCamera.attachControl(gltfRuntime.scene.getEngine().getRenderingCanvas());
  747. if (!perspectiveCamera.aspectRatio) {
  748. perspectiveCamera.aspectRatio = gltfRuntime.scene.getEngine().getRenderWidth() / gltfRuntime.scene.getEngine().getRenderHeight();
  749. }
  750. if (perspectiveCamera.znear && perspectiveCamera.zfar) {
  751. persCamera.maxZ = perspectiveCamera.zfar;
  752. persCamera.minZ = perspectiveCamera.znear;
  753. }
  754. lastNode = persCamera;
  755. }
  756. }
  757. }
  758. // Empty node
  759. if (!node.jointName) {
  760. if (node.babylonNode) {
  761. return node.babylonNode;
  762. }
  763. else if (lastNode === null) {
  764. var dummy = new Mesh(node.name, gltfRuntime.scene);
  765. node.babylonNode = dummy;
  766. lastNode = dummy;
  767. }
  768. }
  769. if (lastNode !== null) {
  770. if (node.matrix) {
  771. configureNodeFromMatrix(lastNode, node);
  772. }
  773. else {
  774. configureNode(lastNode, Vector3.FromArray(node.translation), Quaternion.RotationAxis(Vector3.FromArray(node.rotation).normalize(), node.rotation[3]), Vector3.FromArray(node.scale));
  775. }
  776. lastNode.updateCache(true);
  777. node.babylonNode = lastNode;
  778. }
  779. return lastNode;
  780. };
  781. /**
  782. * Traverses nodes and creates them
  783. */
  784. var traverseNodes = (gltfRuntime: IGLTFRuntime, id: string, parent: Node, meshIncluded?: boolean) => {
  785. var node: IGLTFNode = gltfRuntime.nodes[id];
  786. var newNode: Node = null;
  787. if (gltfRuntime.importOnlyMeshes && !meshIncluded) {
  788. if (gltfRuntime.importMeshesNames.indexOf(node.name) !== -1 || gltfRuntime.importMeshesNames.length === 0) {
  789. meshIncluded = true;
  790. }
  791. else {
  792. meshIncluded = false;
  793. }
  794. }
  795. else {
  796. meshIncluded = true;
  797. }
  798. if (!node.jointName && meshIncluded) {
  799. newNode = importNode(gltfRuntime, node, id);
  800. if (newNode !== null) {
  801. newNode.id = id;
  802. newNode.parent = parent;
  803. }
  804. }
  805. for (var i = 0; i < node.children.length; i++) {
  806. traverseNodes(gltfRuntime, node.children[i], newNode, meshIncluded);
  807. }
  808. };
  809. /**
  810. * do stuff after buffers, shaders are loaded (e.g. hook up materials, load animations, etc.)
  811. */
  812. var postLoad = (gltfRuntime: IGLTFRuntime) => {
  813. // Nodes
  814. var currentScene: IGLTFScene = <IGLTFScene>gltfRuntime.currentScene;
  815. for (var i = 0; i < currentScene.nodes.length; i++) {
  816. traverseNodes(gltfRuntime, currentScene.nodes[i], null);
  817. }
  818. // Set animations
  819. loadAnimations(gltfRuntime);
  820. for (var i = 0; i < gltfRuntime.scene.skeletons.length; i++) {
  821. var skeleton = gltfRuntime.scene.skeletons[i];
  822. gltfRuntime.scene.beginAnimation(skeleton, 0, Number.MAX_VALUE, true, 1.0);
  823. }
  824. };
  825. /**
  826. * onBind shaderrs callback to set uniforms and matrices
  827. */
  828. var onBindShaderMaterial = (mesh: Mesh, gltfRuntime: IGLTFRuntime, unTreatedUniforms: Object, shaderMaterial: ShaderMaterial, technique: IGLTFTechnique, material: IGLTFMaterial, onSuccess: (shaderMaterial: ShaderMaterial) => void) => {
  829. for (var unif in unTreatedUniforms) {
  830. var uniform: IGLTFTechniqueParameter = unTreatedUniforms[unif];
  831. var type = uniform.type;
  832. if (type === EParameterType.FLOAT_MAT2 || type === EParameterType.FLOAT_MAT3 || type === EParameterType.FLOAT_MAT4) {
  833. if (uniform.semantic && !uniform.source && !uniform.node) {
  834. GLTFUtils.SetMatrix(gltfRuntime.scene, mesh, uniform, unif, shaderMaterial.getEffect());
  835. }
  836. else if (uniform.semantic && (uniform.source || uniform.node)) {
  837. var source = gltfRuntime.scene.getNodeByName(uniform.source || uniform.node);
  838. if (source === null) {
  839. source = gltfRuntime.scene.getNodeByID(uniform.source || uniform.node);
  840. }
  841. if (source === null) {
  842. continue;
  843. }
  844. GLTFUtils.SetMatrix(gltfRuntime.scene, source, uniform, unif, shaderMaterial.getEffect());
  845. }
  846. }
  847. else {
  848. var value = material.values[technique.uniforms[unif]];
  849. if (!value) {
  850. continue;
  851. }
  852. if (type === EParameterType.SAMPLER_2D) {
  853. var texture: Texture = gltfRuntime.textures[value].babylonTexture;
  854. if (texture === null) {
  855. continue;
  856. }
  857. shaderMaterial.getEffect().setTexture(unif, texture);
  858. }
  859. else {
  860. GLTFUtils.SetUniform(shaderMaterial.getEffect(), unif, value, type);
  861. }
  862. }
  863. }
  864. onSuccess(shaderMaterial);
  865. };
  866. /**
  867. * Prepare uniforms to send the only one time
  868. * Loads the appropriate textures
  869. */
  870. var prepareShaderMaterialUniforms = (gltfRuntime: IGLTFRuntime, shaderMaterial: ShaderMaterial, technique: IGLTFTechnique, material: IGLTFMaterial, unTreatedUniforms: Object) => {
  871. var materialValues = material.values;
  872. var techniqueUniforms = technique.uniforms;
  873. /**
  874. * Prepare values here (not matrices)
  875. */
  876. for (var unif in unTreatedUniforms) {
  877. var uniform: IGLTFTechniqueParameter = unTreatedUniforms[unif];
  878. var type = uniform.type;
  879. var value = materialValues[techniqueUniforms[unif]] || uniform.value;
  880. if (!value) {
  881. continue;
  882. }
  883. var onLoadTexture = (texture: Texture) => {
  884. if (uniform.value) {
  885. // Static uniform
  886. shaderMaterial.setTexture(unif, texture);
  887. delete unTreatedUniforms[unif];
  888. }
  889. };
  890. // Texture (sampler2D)
  891. if (type === EParameterType.SAMPLER_2D) {
  892. GLTFFileLoaderExtension.LoadTextureAsync(gltfRuntime, <string>value, onLoadTexture, () => onLoadTexture(null));
  893. }
  894. // Others
  895. else {
  896. if (uniform.value && GLTFUtils.SetUniform(shaderMaterial, unif, value, type)) {
  897. // Static uniform
  898. delete unTreatedUniforms[unif];
  899. }
  900. }
  901. }
  902. };
  903. /**
  904. * Shader compilation failed
  905. */
  906. var onShaderCompileError = (program: IGLTFProgram, shaderMaterial: ShaderMaterial, onError: () => void) => {
  907. return (effect: Effect, error: string) => {
  908. Tools.Error("Cannot compile program named " + program.name + ". Error: " + error + ". Default material will be applied");
  909. shaderMaterial.dispose(true);
  910. onError();
  911. };
  912. };
  913. /**
  914. * Shader compilation success
  915. */
  916. var onShaderCompileSuccess = (gltfRuntime: IGLTFRuntime, shaderMaterial: ShaderMaterial, technique: IGLTFTechnique, material: IGLTFMaterial, unTreatedUniforms: Object, onSuccess: (shaderMaterial: ShaderMaterial) => void) => {
  917. return (_: Effect) => {
  918. prepareShaderMaterialUniforms(gltfRuntime, shaderMaterial, technique, material, unTreatedUniforms);
  919. shaderMaterial.onBind = (mesh: Mesh) => {
  920. onBindShaderMaterial(mesh, gltfRuntime, unTreatedUniforms, shaderMaterial, technique, material, onSuccess);
  921. };
  922. };
  923. };
  924. /**
  925. * Returns the appropriate uniform if already handled by babylon
  926. */
  927. var parseShaderUniforms = (tokenizer: Tokenizer, technique: IGLTFTechnique, unTreatedUniforms: Object): string => {
  928. for (var unif in technique.uniforms) {
  929. var uniform = technique.uniforms[unif];
  930. var uniformParameter: IGLTFTechniqueParameter = technique.parameters[uniform];
  931. if (tokenizer.currentIdentifier === unif) {
  932. if (uniformParameter.semantic && !uniformParameter.source && !uniformParameter.node) {
  933. var transformIndex = glTFTransforms.indexOf(uniformParameter.semantic);
  934. if (transformIndex !== -1) {
  935. delete unTreatedUniforms[unif];
  936. return babylonTransforms[transformIndex];
  937. }
  938. }
  939. }
  940. }
  941. return tokenizer.currentIdentifier;
  942. };
  943. /**
  944. * All shaders loaded. Create materials one by one
  945. */
  946. var importMaterials = (gltfRuntime: IGLTFRuntime) => {
  947. // Create materials
  948. for (var mat in gltfRuntime.materials) {
  949. GLTFFileLoaderExtension.LoadMaterialAsync(gltfRuntime, mat, (material: Material) => { }, () => { });
  950. }
  951. };
  952. /**
  953. * Implementation of the base glTF spec
  954. */
  955. export class GLTFFileLoaderBase {
  956. public static CreateRuntime(parsedData: any, scene: Scene, rootUrl: string): IGLTFRuntime {
  957. var gltfRuntime: IGLTFRuntime = {
  958. accessors: {},
  959. buffers: {},
  960. bufferViews: {},
  961. meshes: {},
  962. lights: {},
  963. cameras: {},
  964. nodes: {},
  965. images: {},
  966. textures: {},
  967. shaders: {},
  968. programs: {},
  969. samplers: {},
  970. techniques: {},
  971. materials: {},
  972. animations: {},
  973. skins: {},
  974. currentScene: {},
  975. extensionsUsed: [],
  976. buffersCount: 0,
  977. shaderscount: 0,
  978. scene: scene,
  979. rootUrl: rootUrl,
  980. loadedBufferCount: 0,
  981. loadedBufferViews: {},
  982. loadedShaderCount: 0,
  983. importOnlyMeshes: false,
  984. dummyNodes: []
  985. }
  986. // Parse
  987. if (parsedData.extensionsUsed) {
  988. parseObject(parsedData.extensionsUsed, "extensionsUsed", gltfRuntime);
  989. }
  990. if (parsedData.buffers) {
  991. parseBuffers(parsedData.buffers, gltfRuntime);
  992. }
  993. if (parsedData.bufferViews) {
  994. parseObject(parsedData.bufferViews, "bufferViews", gltfRuntime);
  995. }
  996. if (parsedData.accessors) {
  997. parseObject(parsedData.accessors, "accessors", gltfRuntime);
  998. }
  999. if (parsedData.meshes) {
  1000. parseObject(parsedData.meshes, "meshes", gltfRuntime);
  1001. }
  1002. if (parsedData.lights) {
  1003. parseObject(parsedData.lights, "lights", gltfRuntime);
  1004. }
  1005. if (parsedData.cameras) {
  1006. parseObject(parsedData.cameras, "cameras", gltfRuntime);
  1007. }
  1008. if (parsedData.nodes) {
  1009. parseObject(parsedData.nodes, "nodes", gltfRuntime);
  1010. }
  1011. if (parsedData.images) {
  1012. parseObject(parsedData.images, "images", gltfRuntime);
  1013. }
  1014. if (parsedData.textures) {
  1015. parseObject(parsedData.textures, "textures", gltfRuntime);
  1016. }
  1017. if (parsedData.shaders) {
  1018. parseShaders(parsedData.shaders, gltfRuntime);
  1019. }
  1020. if (parsedData.programs) {
  1021. parseObject(parsedData.programs, "programs", gltfRuntime);
  1022. }
  1023. if (parsedData.samplers) {
  1024. parseObject(parsedData.samplers, "samplers", gltfRuntime);
  1025. }
  1026. if (parsedData.techniques) {
  1027. parseObject(parsedData.techniques, "techniques", gltfRuntime);
  1028. }
  1029. if (parsedData.materials) {
  1030. parseObject(parsedData.materials, "materials", gltfRuntime);
  1031. }
  1032. if (parsedData.animations) {
  1033. parseObject(parsedData.animations, "animations", gltfRuntime);
  1034. }
  1035. if (parsedData.skins) {
  1036. parseObject(parsedData.skins, "skins", gltfRuntime);
  1037. }
  1038. if (parsedData.scene && parsedData.scenes) {
  1039. gltfRuntime.currentScene = parsedData.scenes[parsedData.scene];
  1040. }
  1041. return gltfRuntime;
  1042. }
  1043. public static LoadBufferAsync(gltfRuntime: IGLTFRuntime, id: string, onSuccess: (buffer: ArrayBufferView) => void, onError: () => void): void {
  1044. var buffer: IGLTFBuffer = gltfRuntime.buffers[id];
  1045. if (GLTFUtils.IsBase64(buffer.uri)) {
  1046. setTimeout(() => onSuccess(new Uint8Array(GLTFUtils.DecodeBase64(buffer.uri))));
  1047. }
  1048. else {
  1049. Tools.LoadFile(gltfRuntime.rootUrl + buffer.uri, data => onSuccess(new Uint8Array(data)), null, null, true, onError);
  1050. }
  1051. }
  1052. public static LoadTextureBufferAsync(gltfRuntime: IGLTFRuntime, id: string, onSuccess: (buffer: ArrayBufferView) => void, onError: () => void): void {
  1053. var texture: IGLTFTexture = gltfRuntime.textures[id];
  1054. if (!texture || !texture.source) {
  1055. onError();
  1056. return;
  1057. }
  1058. if (texture.babylonTexture) {
  1059. onSuccess(null);
  1060. return;
  1061. }
  1062. var source: IGLTFImage = gltfRuntime.images[texture.source];
  1063. if (GLTFUtils.IsBase64(source.uri)) {
  1064. setTimeout(() => onSuccess(new Uint8Array(GLTFUtils.DecodeBase64(source.uri))));
  1065. }
  1066. else {
  1067. Tools.LoadFile(gltfRuntime.rootUrl + source.uri, data => onSuccess(new Uint8Array(data)), null, null, true, onError);
  1068. }
  1069. }
  1070. public static CreateTextureAsync(gltfRuntime: IGLTFRuntime, id: string, buffer: ArrayBufferView, onSuccess: (texture: Texture) => void, onError: () => void): void {
  1071. var texture: IGLTFTexture = gltfRuntime.textures[id];
  1072. if (texture.babylonTexture) {
  1073. onSuccess(texture.babylonTexture);
  1074. return;
  1075. }
  1076. var sampler: IGLTFSampler = gltfRuntime.samplers[texture.sampler];
  1077. var createMipMaps =
  1078. (sampler.minFilter === ETextureFilterType.NEAREST_MIPMAP_NEAREST) ||
  1079. (sampler.minFilter === ETextureFilterType.NEAREST_MIPMAP_LINEAR) ||
  1080. (sampler.minFilter === ETextureFilterType.LINEAR_MIPMAP_NEAREST) ||
  1081. (sampler.minFilter === ETextureFilterType.LINEAR_MIPMAP_LINEAR);
  1082. var samplingMode = Texture.BILINEAR_SAMPLINGMODE;
  1083. var blob = new Blob([buffer]);
  1084. var blobURL = URL.createObjectURL(blob);
  1085. var revokeBlobURL = () => URL.revokeObjectURL(blobURL);
  1086. var newTexture = new Texture(blobURL, gltfRuntime.scene, !createMipMaps, true, samplingMode, revokeBlobURL, revokeBlobURL);
  1087. newTexture.wrapU = GLTFUtils.GetWrapMode(sampler.wrapS);
  1088. newTexture.wrapV = GLTFUtils.GetWrapMode(sampler.wrapT);
  1089. newTexture.name = id;
  1090. texture.babylonTexture = newTexture;
  1091. onSuccess(newTexture);
  1092. }
  1093. public static LoadShaderStringAsync(gltfRuntime: IGLTFRuntime, id: string, onSuccess: (shaderString: string) => void, onError: () => void): void {
  1094. var shader: IGLTFShader = gltfRuntime.shaders[id];
  1095. if (GLTFUtils.IsBase64(shader.uri)) {
  1096. var shaderString = atob(shader.uri.split(",")[1]);
  1097. onSuccess(shaderString);
  1098. }
  1099. else {
  1100. Tools.LoadFile(gltfRuntime.rootUrl + shader.uri, onSuccess, null, null, false, onError);
  1101. }
  1102. }
  1103. public static LoadMaterialAsync(gltfRuntime: IGLTFRuntime, id: string, onSuccess: (material: Material) => void, onError: () => void): void {
  1104. var material: IGLTFMaterial = gltfRuntime.materials[id];
  1105. var technique: IGLTFTechnique = gltfRuntime.techniques[material.technique];
  1106. if (!technique) {
  1107. var defaultMaterial = new StandardMaterial(id, gltfRuntime.scene);
  1108. defaultMaterial.diffuseColor = new Color3(0.5, 0.5, 0.5);
  1109. defaultMaterial.sideOrientation = Material.CounterClockWiseSideOrientation;
  1110. onSuccess(defaultMaterial);
  1111. return;
  1112. }
  1113. var program: IGLTFProgram = gltfRuntime.programs[technique.program];
  1114. var states: IGLTFTechniqueStates = technique.states;
  1115. var vertexShader: string = Effect.ShadersStore[program.vertexShader + "VertexShader"];
  1116. var pixelShader: string = Effect.ShadersStore[program.fragmentShader + "PixelShader"];
  1117. var newVertexShader = "";
  1118. var newPixelShader = "";
  1119. var vertexTokenizer = new Tokenizer(vertexShader);
  1120. var pixelTokenizer = new Tokenizer(pixelShader);
  1121. var unTreatedUniforms: Object = {};
  1122. var uniforms = [];
  1123. var attributes = [];
  1124. var samplers = [];
  1125. // Fill uniform, sampler2D and attributes
  1126. for (var unif in technique.uniforms) {
  1127. var uniform = technique.uniforms[unif];
  1128. var uniformParameter: IGLTFTechniqueParameter = technique.parameters[uniform];
  1129. unTreatedUniforms[unif] = uniformParameter;
  1130. if (uniformParameter.semantic && !uniformParameter.node && !uniformParameter.source) {
  1131. var transformIndex = glTFTransforms.indexOf(uniformParameter.semantic);
  1132. if (transformIndex !== -1) {
  1133. uniforms.push(babylonTransforms[transformIndex]);
  1134. delete unTreatedUniforms[unif];
  1135. }
  1136. else {
  1137. uniforms.push(unif);
  1138. }
  1139. }
  1140. else if (uniformParameter.type === EParameterType.SAMPLER_2D) {
  1141. samplers.push(unif);
  1142. }
  1143. else {
  1144. uniforms.push(unif);
  1145. }
  1146. }
  1147. for (var attr in technique.attributes) {
  1148. var attribute = technique.attributes[attr];
  1149. var attributeParameter: IGLTFTechniqueParameter = technique.parameters[attribute];
  1150. if (attributeParameter.semantic) {
  1151. attributes.push(getAttribute(attributeParameter));
  1152. }
  1153. }
  1154. // Configure vertex shader
  1155. while (!vertexTokenizer.isEnd() && vertexTokenizer.getNextToken()) {
  1156. var tokenType = vertexTokenizer.currentToken;
  1157. if (tokenType !== ETokenType.IDENTIFIER) {
  1158. newVertexShader += vertexTokenizer.currentString;
  1159. continue;
  1160. }
  1161. var foundAttribute = false;
  1162. for (var attr in technique.attributes) {
  1163. var attribute = technique.attributes[attr];
  1164. var attributeParameter: IGLTFTechniqueParameter = technique.parameters[attribute];
  1165. if (vertexTokenizer.currentIdentifier === attr && attributeParameter.semantic) {
  1166. newVertexShader += getAttribute(attributeParameter);
  1167. foundAttribute = true;
  1168. break;
  1169. }
  1170. }
  1171. if (foundAttribute) {
  1172. continue;
  1173. }
  1174. newVertexShader += parseShaderUniforms(vertexTokenizer, technique, unTreatedUniforms);
  1175. }
  1176. // Configure pixel shader
  1177. while (!pixelTokenizer.isEnd() && pixelTokenizer.getNextToken()) {
  1178. var tokenType = pixelTokenizer.currentToken;
  1179. if (tokenType !== ETokenType.IDENTIFIER) {
  1180. newPixelShader += pixelTokenizer.currentString;
  1181. continue;
  1182. }
  1183. newPixelShader += parseShaderUniforms(pixelTokenizer, technique, unTreatedUniforms);
  1184. }
  1185. // Create shader material
  1186. var shaderPath = {
  1187. vertex: program.vertexShader + id,
  1188. fragment: program.fragmentShader + id
  1189. };
  1190. var options = {
  1191. attributes: attributes,
  1192. uniforms: uniforms,
  1193. samplers: samplers,
  1194. needAlphaBlending: states.functions && states.functions.blendEquationSeparate
  1195. };
  1196. Effect.ShadersStore[program.vertexShader + id + "VertexShader"] = newVertexShader;
  1197. Effect.ShadersStore[program.fragmentShader + id + "PixelShader"] = newPixelShader;
  1198. var shaderMaterial = new ShaderMaterial(id, gltfRuntime.scene, shaderPath, options);
  1199. shaderMaterial.onError = onShaderCompileError(program, shaderMaterial, onError);
  1200. shaderMaterial.onCompiled = onShaderCompileSuccess(gltfRuntime, shaderMaterial, technique, material, unTreatedUniforms, onSuccess);
  1201. shaderMaterial.sideOrientation = Material.CounterClockWiseSideOrientation;
  1202. if (states.functions) {
  1203. var functions = states.functions;
  1204. if (functions.cullFace && functions.cullFace[0] !== ECullingType.BACK) {
  1205. shaderMaterial.backFaceCulling = false;
  1206. }
  1207. var blendFunc = functions.blendFuncSeparate;
  1208. if (blendFunc) {
  1209. if (blendFunc[0] === EBlendingFunction.SRC_ALPHA && blendFunc[1] === EBlendingFunction.ONE_MINUS_SRC_ALPHA && blendFunc[2] === EBlendingFunction.ONE && blendFunc[3] === EBlendingFunction.ONE) {
  1210. shaderMaterial.alphaMode = Engine.ALPHA_COMBINE;
  1211. }
  1212. else if (blendFunc[0] === EBlendingFunction.ONE && blendFunc[1] === EBlendingFunction.ONE && blendFunc[2] === EBlendingFunction.ZERO && blendFunc[3] === EBlendingFunction.ONE) {
  1213. shaderMaterial.alphaMode = Engine.ALPHA_ONEONE;
  1214. }
  1215. else if (blendFunc[0] === EBlendingFunction.SRC_ALPHA && blendFunc[1] === EBlendingFunction.ONE && blendFunc[2] === EBlendingFunction.ZERO && blendFunc[3] === EBlendingFunction.ONE) {
  1216. shaderMaterial.alphaMode = Engine.ALPHA_ADD;
  1217. }
  1218. else if (blendFunc[0] === EBlendingFunction.ZERO && blendFunc[1] === EBlendingFunction.ONE_MINUS_SRC_COLOR && blendFunc[2] === EBlendingFunction.ONE && blendFunc[3] === EBlendingFunction.ONE) {
  1219. shaderMaterial.alphaMode = Engine.ALPHA_SUBTRACT;
  1220. }
  1221. else if (blendFunc[0] === EBlendingFunction.DST_COLOR && blendFunc[1] === EBlendingFunction.ZERO && blendFunc[2] === EBlendingFunction.ONE && blendFunc[3] === EBlendingFunction.ONE) {
  1222. shaderMaterial.alphaMode = Engine.ALPHA_MULTIPLY;
  1223. }
  1224. else if (blendFunc[0] === EBlendingFunction.SRC_ALPHA && blendFunc[1] === EBlendingFunction.ONE_MINUS_SRC_COLOR && blendFunc[2] === EBlendingFunction.ONE && blendFunc[3] === EBlendingFunction.ONE) {
  1225. shaderMaterial.alphaMode = Engine.ALPHA_MAXIMIZED;
  1226. }
  1227. }
  1228. }
  1229. }
  1230. }
  1231. /**
  1232. * glTF File Loader Plugin
  1233. */
  1234. export class GLTFFileLoader implements ISceneLoaderPluginAsync {
  1235. /**
  1236. * Public members
  1237. */
  1238. public extensions: ISceneLoaderPluginExtensions = {
  1239. ".gltf": { isBinary: false },
  1240. ".glb": { isBinary: true }
  1241. };
  1242. /**
  1243. * Private members
  1244. */
  1245. // None
  1246. /**
  1247. * Static members
  1248. */
  1249. public static MakeYUP: boolean = false;
  1250. public static HomogeneousCoordinates: boolean = false;
  1251. public static Extensions: { [name: string]: GLTFFileLoaderExtension } = {};
  1252. public static RegisterExtension(extension: GLTFFileLoaderExtension): void {
  1253. if (GLTFFileLoader.Extensions[extension.name]) {
  1254. Tools.Error("Tool with the same name \"" + extension.name + "\" already exists");
  1255. return;
  1256. }
  1257. GLTFFileLoader.Extensions[extension.name] = extension;
  1258. }
  1259. /**
  1260. * Import meshes
  1261. */
  1262. public importMeshAsync(meshesNames: any, scene: Scene, data: any, rootUrl: string, onSuccess?: (meshes: AbstractMesh[], particleSystems: ParticleSystem[], skeletons: Skeleton[]) => void, onError?: () => void): boolean {
  1263. scene.useRightHandedSystem = true;
  1264. var gltfRuntime = GLTFFileLoaderExtension.LoadRuntimeAsync(scene, data, rootUrl, gltfRuntime => {
  1265. gltfRuntime.importOnlyMeshes = true;
  1266. if (meshesNames === "") {
  1267. gltfRuntime.importMeshesNames = [];
  1268. }
  1269. else if (typeof meshesNames === "string") {
  1270. gltfRuntime.importMeshesNames = [meshesNames];
  1271. }
  1272. else if (meshesNames && !(meshesNames instanceof Array)) {
  1273. gltfRuntime.importMeshesNames = [meshesNames];
  1274. }
  1275. else {
  1276. gltfRuntime.importMeshesNames = [];
  1277. Tools.Warn("Argument meshesNames must be of type string or string[]");
  1278. }
  1279. // Create nodes
  1280. this._createNodes(gltfRuntime);
  1281. var meshes = [];
  1282. var skeletons = [];
  1283. // Fill arrays of meshes and skeletons
  1284. for (var nde in gltfRuntime.nodes) {
  1285. var node: IGLTFNode = gltfRuntime.nodes[nde];
  1286. if (node.babylonNode instanceof AbstractMesh) {
  1287. meshes.push(<AbstractMesh>node.babylonNode);
  1288. }
  1289. }
  1290. for (var skl in gltfRuntime.skins) {
  1291. var skin: IGLTFSkins = gltfRuntime.skins[skl];
  1292. if (skin.babylonSkeleton instanceof Skeleton) {
  1293. skeletons.push(skin.babylonSkeleton);
  1294. }
  1295. }
  1296. // Load buffers, shaders, materials, etc.
  1297. this._loadBuffersAsync(gltfRuntime, () => {
  1298. this._loadShadersAsync(gltfRuntime, () => {
  1299. importMaterials(gltfRuntime);
  1300. postLoad(gltfRuntime);
  1301. });
  1302. });
  1303. if (onSuccess) {
  1304. onSuccess(meshes, null, skeletons);
  1305. }
  1306. }, onError);
  1307. return true;
  1308. }
  1309. /**
  1310. * Load scene
  1311. */
  1312. public loadAsync(scene: Scene, data: string | ArrayBuffer, rootUrl: string, onSuccess: () => void, onError: () => void): boolean {
  1313. scene.useRightHandedSystem = true;
  1314. GLTFFileLoaderExtension.LoadRuntimeAsync(scene, data, rootUrl, gltfRuntime => {
  1315. // Create nodes
  1316. this._createNodes(gltfRuntime);
  1317. // Load buffers, shaders, materials, etc.
  1318. this._loadBuffersAsync(gltfRuntime, () => {
  1319. this._loadShadersAsync(gltfRuntime, () => {
  1320. importMaterials(gltfRuntime);
  1321. postLoad(gltfRuntime);
  1322. });
  1323. });
  1324. onSuccess();
  1325. }, onError);
  1326. return true;
  1327. }
  1328. private _loadShadersAsync(gltfRuntime: IGLTFRuntime, onload: () => void): void {
  1329. var hasShaders = false;
  1330. var processShader = (sha: string, shader: IGLTFShader) => {
  1331. GLTFFileLoaderExtension.LoadShaderStringAsync(gltfRuntime, sha, shaderString => {
  1332. gltfRuntime.loadedShaderCount++;
  1333. if (shaderString) {
  1334. Effect.ShadersStore[sha + (shader.type === EShaderType.VERTEX ? "VertexShader" : "PixelShader")] = shaderString;
  1335. }
  1336. if (gltfRuntime.loadedShaderCount === gltfRuntime.shaderscount) {
  1337. onload();
  1338. }
  1339. }, () => {
  1340. Tools.Error("Error when loading shader program named " + sha + " located at " + shader.uri);
  1341. });
  1342. };
  1343. for (var sha in gltfRuntime.shaders) {
  1344. hasShaders = true;
  1345. var shader: IGLTFShader = gltfRuntime.shaders[sha];
  1346. if (shader) {
  1347. processShader.bind(this, sha, shader)();
  1348. }
  1349. else {
  1350. Tools.Error("No shader named: " + sha);
  1351. }
  1352. }
  1353. if (!hasShaders) {
  1354. onload();
  1355. }
  1356. };
  1357. private _loadBuffersAsync(gltfRuntime: IGLTFRuntime, onload: () => void): void {
  1358. var hasBuffers = false;
  1359. var processBuffer = (buf: string, buffer: IGLTFBuffer) => {
  1360. GLTFFileLoaderExtension.LoadBufferAsync(gltfRuntime, buf, bufferView => {
  1361. gltfRuntime.loadedBufferCount++;
  1362. if (bufferView) {
  1363. if (bufferView.byteLength != gltfRuntime.buffers[buf].byteLength) {
  1364. Tools.Error("Buffer named " + buf + " is length " + bufferView.byteLength + ". Expected: " + buffer.byteLength); // Improve error message
  1365. }
  1366. gltfRuntime.loadedBufferViews[buf] = bufferView;
  1367. }
  1368. if (gltfRuntime.loadedBufferCount === gltfRuntime.buffersCount) {
  1369. onload();
  1370. }
  1371. }, () => {
  1372. Tools.Error("Error when loading buffer named " + buf + " located at " + buffer.uri);
  1373. });
  1374. };
  1375. for (var buf in gltfRuntime.buffers) {
  1376. hasBuffers = true;
  1377. var buffer: IGLTFBuffer = gltfRuntime.buffers[buf];
  1378. if (buffer) {
  1379. processBuffer.bind(this, buf, buffer)();
  1380. }
  1381. else {
  1382. Tools.Error("No buffer named: " + buf);
  1383. }
  1384. }
  1385. if (!hasBuffers) {
  1386. onload();
  1387. }
  1388. }
  1389. // Creates nodes before loading buffers and shaders
  1390. private _createNodes(gltfRuntime: IGLTFRuntime): void {
  1391. var currentScene = <IGLTFScene>gltfRuntime.currentScene;
  1392. for (var i = 0; i < currentScene.nodes.length; i++) {
  1393. traverseNodes(gltfRuntime, currentScene.nodes[i], null);
  1394. }
  1395. }
  1396. };
  1397. BABYLON.SceneLoader.RegisterPlugin(new GLTFFileLoader());
  1398. }