elation-engine 0.9.109 → 0.9.113

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/LICENSE CHANGED
@@ -1,6 +1,6 @@
1
1
  The MIT License (MIT)
2
2
 
3
- Copyright (c) 2013-2015 James Baicoianu
3
+ Copyright (c) 2013-2021 James Baicoianu
4
4
 
5
5
  Permission is hereby granted, free of charge, to any person obtaining a copy
6
6
  of this software and associated documentation files (the "Software"), to deal
package/css/engine.css CHANGED
@@ -1,4 +1,5 @@
1
- .engine_view {
1
+ engine-systems-render-view {
2
+ display: block;
2
3
  position: relative;
3
4
  }
4
5
  .engine_view_fullsize {
@@ -80,12 +81,15 @@
80
81
  width: 10em;
81
82
  display: inline-block;
82
83
  }
83
- .engine_view.cursor_default {
84
+ .engine_view.cursor_default,
85
+ engine-systems-render-view.cursor_default {
84
86
  cursor: default;
85
87
  }
86
- .engine_view.cursor_pointer {
88
+ .engine_view.cursor_pointer,
89
+ engine-systems-render-view.cursor_pointer {
87
90
  cursor: pointer;
88
91
  }
89
- .engine_view.cursor_crosshair {
92
+ .engine_view.cursor_crosshair,
93
+ engine-systems-render-view.cursor_crosshair {
90
94
  cursor: crosshair;
91
95
  }
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "elation-engine",
3
3
  "description": "WebGL/WebVR engine written in Javascript",
4
- "version": "0.9.109",
4
+ "version": "0.9.113",
5
5
  "main": "",
6
6
  "author": "James Baicoianu",
7
7
  "license": "MIT",
package/scripts/assets.js CHANGED
@@ -1,4 +1,4 @@
1
- elation.require(['utils.workerpool', 'engine.external.three.three', 'engine.external.libgif', 'engine.external.textdecoder-polyfill'], function() {
1
+ elation.require(['utils.workerpool', 'engine.external.three.three', 'engine.external.libgif', 'engine.external.textdecoder-polyfill', 'engine.external.three.three-loaders', 'engine.external.three.three-vrm'], function() {
2
2
 
3
3
  THREE.Cache.enabled = true;
4
4
 
@@ -67,7 +67,9 @@ elation.require(['utils.workerpool', 'engine.external.three.three', 'engine.exte
67
67
  assets: {},
68
68
  types: {},
69
69
  corsproxy: '',
70
+ dracopath: false,
70
71
  placeholders: {},
72
+ scriptOverrides: {},
71
73
 
72
74
  init: function(dummy) {
73
75
  var corsproxy = elation.config.get('engine.assets.corsproxy', '');
@@ -79,10 +81,15 @@ elation.require(['utils.workerpool', 'engine.external.three.three', 'engine.exte
79
81
  },
80
82
  initTextureLoaders: function(rendersystem, libpath) {
81
83
  let renderer = rendersystem.renderer;
82
- let loader = new THREE.BasisTextureLoader();
83
- loader.setTranscoderPath(libpath);
84
- loader.detectSupport(renderer);
85
- this.basisloader = loader;
84
+ let basisloader = new THREE.BasisTextureLoader();
85
+ basisloader.setTranscoderPath(libpath);
86
+ basisloader.detectSupport(renderer);
87
+ this.basisloader = basisloader;
88
+
89
+ let pmremGenerator = new THREE.PMREMGenerator( renderer );
90
+ pmremGenerator.compileEquirectangularShader();
91
+ this.pmremGenerator = pmremGenerator;
92
+
86
93
  this.rendersystem = rendersystem;
87
94
  },
88
95
  loadAssetPack: function(url, baseurl) {
@@ -132,6 +139,67 @@ if (!ENV_IS_BROWSER) return;
132
139
  setPlaceholder: function(type, name) {
133
140
  this.placeholders[type] = this.find(type, name);
134
141
  },
142
+ setDracoPath: function(dracopath) {
143
+ this.dracopath = dracopath;
144
+ },
145
+ getOrigin(baseurl=null) {
146
+ if (baseurl) {
147
+ let m = baseurl.match(/(https?:\/\/[^\/]+)/i);
148
+ if (m) {
149
+ return m[1];
150
+ }
151
+ }
152
+ return self.location.origin;
153
+ },
154
+ isURLRelative: function(src) {
155
+ if (src && src.match(/^([\S]+:)?\/\//) || src[0] == '/') {
156
+ return false;
157
+ }
158
+ return true;
159
+ },
160
+ isURLAbsolute: function(src) {
161
+ return (src[0] == '/' && src[1] != '/');
162
+ },
163
+ isURLLocal: function(src) {
164
+ if (this.isURLBlob(src) || this.isURLData(src)) {
165
+ return true;
166
+ }
167
+ if (src.match(/^(https?:)?\/\//i)) {
168
+ return (src.indexOf(self.location.origin) == 0);
169
+ }
170
+ return (
171
+ (src[0] == '/' && src[1] != '/') ||
172
+ (src[0] != '/')
173
+ );
174
+ },
175
+ isURLData: function(url) {
176
+ if (!url) return false;
177
+ return url.indexOf('data:') == 0;
178
+ },
179
+ isURLBlob: function(url) {
180
+ if (!url) return false;
181
+ return url.indexOf('blob:') == 0;
182
+ },
183
+ isURLProxied: function(url) {
184
+ if (!url || !elation.engine.assets.corsproxy) return false;
185
+ return url.indexOf(elation.engine.assets.corsproxy) == 0;
186
+ },
187
+ getFullURL: function(url, baseurl=null) {
188
+ if (!url) url = '';
189
+ if (!baseurl) baseurl = '';
190
+ var fullurl = url;
191
+ if (!this.isURLBlob(fullurl) && !this.isURLData(fullurl)) {
192
+ if (this.isURLRelative(fullurl) && fullurl.substr(0, baseurl.length) != baseurl) {
193
+ fullurl = baseurl + fullurl;
194
+ } else if (this.isURLProxied(fullurl)) {
195
+ fullurl = fullurl.replace(elation.engine.assets.corsproxy, '');
196
+ } else if (this.isURLAbsolute(fullurl)) {
197
+ fullurl = this.getOrigin(baseurl) + fullurl;
198
+ }
199
+ }
200
+
201
+ return fullurl;
202
+ },
135
203
  loaderpool: false
136
204
  });
137
205
  elation.extend('engine.assetdownloader', new function() {
@@ -371,37 +439,22 @@ if (!ENV_IS_BROWSER) return;
371
439
  console.log('engine.assets.base load() should not be called directly', this);
372
440
  },
373
441
  isURLRelative: function(src) {
374
- if (src && src.match(/^(https?:)?\/\//) || src[0] == '/') {
375
- return false;
376
- }
377
- return true;
442
+ return elation.engine.assets.isURLRelative(src);
378
443
  },
379
444
  isURLAbsolute: function(src) {
380
- return (src[0] == '/' && src[1] != '/');
445
+ return elation.engine.assets.isURLAbsolute(src);
381
446
  },
382
447
  isURLLocal: function(src) {
383
- if (this.isURLBlob(src) || this.isURLData(src)) {
384
- return true;
385
- }
386
- if (src.match(/^(https?:)?\/\//i)) {
387
- return (src.indexOf(self.location.origin) == 0);
388
- }
389
- return (
390
- (src[0] == '/' && src[1] != '/') ||
391
- (src[0] != '/')
392
- );
448
+ return elation.engine.assets.isURLLocal(src);
393
449
  },
394
450
  isURLData: function(url) {
395
- if (!url) return false;
396
- return url.indexOf('data:') == 0;
451
+ return elation.engine.assets.isURLData(url);
397
452
  },
398
453
  isURLBlob: function(url) {
399
- if (!url) return false;
400
- return url.indexOf('blob:') == 0;
454
+ return elation.engine.assets.isURLBlob(url);
401
455
  },
402
456
  isURLProxied: function(url) {
403
- if (!url || !elation.engine.assets.corsproxy) return false;
404
- return url.indexOf(elation.engine.assets.corsproxy) == 0;
457
+ return elation.engine.assets.isURLProxied(url);
405
458
  },
406
459
  getFullURL: function(url, baseurl) {
407
460
  if (!url) url = this.src;
@@ -414,12 +467,15 @@ if (!ENV_IS_BROWSER) return;
414
467
  } else if (this.isURLProxied(fullurl)) {
415
468
  fullurl = fullurl.replace(elation.engine.assets.corsproxy, '');
416
469
  } else if (this.isURLAbsolute(fullurl)) {
417
- fullurl = self.location.origin + fullurl;
470
+ fullurl = this.getOrigin() + fullurl;
418
471
  }
419
472
  }
420
473
 
421
474
  return fullurl;
422
475
  },
476
+ getOrigin() {
477
+ return elation.engine.assets.getOrigin(this.baseurl);
478
+ },
423
479
  getProxiedURL: function(url, baseurl) {
424
480
  var proxiedurl = this.getFullURL(url, baseurl);
425
481
  if (this.proxy && this.proxy != 'false' && proxiedurl && elation.engine.assets.corsproxy && !this.isURLLocal(proxiedurl) && proxiedurl.indexOf(elation.engine.assets.corsproxy) == -1) {
@@ -436,6 +492,7 @@ if (!ENV_IS_BROWSER) return;
436
492
  },
437
493
  getBaseURL: function(url) {
438
494
  var url = url || this.getFullURL();
495
+ if (url.indexOf('/') == -1) url = document.location.href;
439
496
  var parts = url.split('/');
440
497
  parts.pop();
441
498
  return parts.join('/') + '/';
@@ -493,6 +550,7 @@ if (!ENV_IS_BROWSER) return;
493
550
  imagetype: '',
494
551
  tex_linear: true,
495
552
  srgb: false,
553
+ equi: false,
496
554
  hasalpha: null,
497
555
  rawimage: null,
498
556
  preload: true,
@@ -516,6 +574,9 @@ if (!ENV_IS_BROWSER) return;
516
574
  //texture.needsUpdate = true;
517
575
  texture.flipY = (this.flipy === true || this.flipy === 'true');
518
576
  texture.encoding = (this.srgb ? THREE.sRGBEncoding : THREE.LinearEncoding);
577
+ if (this.equi) {
578
+ texture.mapping = THREE.EquirectangularReflectionMapping;
579
+ }
519
580
  if (this.isURLData(fullurl)) {
520
581
  this.loadImageByURL();
521
582
  } else {
@@ -533,12 +594,32 @@ if (!ENV_IS_BROWSER) return;
533
594
  blob.arrayBuffer()
534
595
  .then(buffer => loader._createTexture(buffer))
535
596
  .then(texture => this.handleLoadBasis(texture))
597
+ } else if (imagetype == 'exr') {
598
+ // TODO - this should probably done off-thread if possible, it currently locks rendering for a noticable amount of time
599
+ let loader = new THREE.EXRLoader();
600
+ if (loader) {
601
+ loader.setDataType( THREE.UnsignedByteType );
602
+ loader.load(fullurl, (exrtexture) => {
603
+ let exrCubeRenderTarget = elation.engine.assets.pmremGenerator.fromEquirectangular( exrtexture );
604
+ let exrBackground = exrCubeRenderTarget.texture;
605
+
606
+ exrtexture.dispose();
607
+
608
+ this._texture = exrBackground;
609
+ this.loaded = true;
610
+ this.uploaded = false;
611
+
612
+ this.sendLoadEvents();
613
+
614
+ });
615
+ }
536
616
  } else {
617
+ let blob = xhr.response;
537
618
  if (typeof createImageBitmap == 'function' && type != 'image/gif') {
538
- let blob = xhr.response;
539
619
  createImageBitmap(blob).then(elation.bind(this, this.handleLoad), elation.bind(this, this.handleBitmapError));
540
620
  } else {
541
- this.loadImageByURL();
621
+ let imgurl = URL.createObjectURL(blob);
622
+ this.loadImageByURL(imgurl);
542
623
  }
543
624
  }
544
625
 
@@ -560,18 +641,20 @@ if (!ENV_IS_BROWSER) return;
560
641
  texture.needsUpdate = true;
561
642
  texture.flipY = this.flipy;
562
643
 
563
- elation.events.add(this.canvas, 'update', () => texture.needsUpdate = true);
644
+ elation.events.add(this.canvas, 'asset_update', () => { texture.needsUpdate = true; });
564
645
  this.loaded = true;
565
646
  setTimeout(() => this.sendLoadEvents(), 0);
566
647
  }
567
648
  },
568
- loadImageByURL: function() {
569
- var proxiedurl = this.getProxiedURL(this.src);
649
+ loadImageByURL: function(src) {
650
+ if (!src) {
651
+ src = this.getProxiedURL(this.src);
652
+ }
570
653
  var image = document.createElementNS( 'http://www.w3.org/1999/xhtml', 'img' );
571
654
  elation.events.add(image, 'load', elation.bind(this, this.handleLoad, image));
572
655
  elation.events.add(image, 'error', elation.bind(this, this.handleError));
573
656
  image.crossOrigin = 'anonymous';
574
- image.src = proxiedurl;
657
+ image.src = src;
575
658
  return image;
576
659
  },
577
660
  getCanvas: function() {
@@ -673,8 +756,8 @@ if (!ENV_IS_BROWSER) return;
673
756
  canvas.originalSrc = this.src;
674
757
 
675
758
  var imagemax = elation.utils.any(this.maxsize, elation.config.get('engine.assets.image.maxsize', Infinity));
676
- canvas.width = (this.tex_linear ? Math.min(imagemax, this.nextHighestPowerOfTwo(image.width)) : image.width);
677
- canvas.height = (this.tex_linear ? Math.min(imagemax, this.nextHighestPowerOfTwo(image.height)) : image.height);
759
+ canvas.width = Math.min(image.width, imagemax); //(this.tex_linear ? Math.min(imagemax, this.nextHighestPowerOfTwo(image.width)) : image.width);
760
+ canvas.height = Math.min(image.height, imagemax); //(this.tex_linear ? Math.min(imagemax, this.nextHighestPowerOfTwo(image.height)) : image.height);
678
761
  var ctx = canvas.getContext("2d");
679
762
  ctx.drawImage(image, 0, 0, image.width, image.height, 0, 0, canvas.width, canvas.height);
680
763
  if (this.hasalpha === null) {
@@ -889,10 +972,13 @@ if (!ENV_IS_BROWSER) return;
889
972
  if (url.match(/\.webm$/)) {
890
973
  this.hasalpha = true;
891
974
  }
975
+ if ('requestVideoFrameCallback' in video) {
976
+ video.requestVideoFrameCallback((time, metadata) => this.updateVideoFrame(time, metadata));
977
+ }
892
978
  }
893
979
  this._video = video;
894
980
  let textureFormat = (this.format == THREE.RGBFormat && this.hasalpha ? THREE.RGBAFormat : this.format);
895
- if (this.sbs3d) {
981
+ if (false && this.sbs3d) {
896
982
  this._texture = new THREE.SBSVideoTexture(video, THREE.UVMapping, THREE.ClampToEdgeWrapping, THREE.ClampToEdgeWrapping, null, null, textureFormat, this.type);
897
983
  this._texture.reverse = this.reverse3d;
898
984
  } else {
@@ -979,6 +1065,11 @@ if (!ENV_IS_BROWSER) return;
979
1065
  handleAutoplayFail: function(ev) {
980
1066
  elation.events.fire({element: this._texture, type: 'autoplayfail'});
981
1067
  },
1068
+ updateVideoFrame: function(time, metadata) {
1069
+ //elation.events.fire({element: this, type: 'videoframe'});
1070
+ elation.events.fire({element: this._texture, type: 'videoframe'});
1071
+ this._video.requestVideoFrameCallback((time, metadata) => this.updateVideoFrame(time, metadata));
1072
+ },
982
1073
  getInstance: function(args) {
983
1074
  if (!this._texture) {
984
1075
  this.load();
@@ -1019,8 +1110,8 @@ if (!ENV_IS_BROWSER) return;
1019
1110
  hls.destroy();
1020
1111
  break;
1021
1112
  }
1022
- } else if (data.details === 'internalException' && data.type === 'otherError' && isMobile()) {
1023
- this.hlsDropHighestLevel();
1113
+ //} else if (data.details === 'internalException' && data.type === 'otherError' && isMobile()) {
1114
+ // this.hlsDropHighestLevel();
1024
1115
  } else if (data.details == 'bufferStalledError') {
1025
1116
  //hls.recoverMediaError();
1026
1117
  }
@@ -1153,6 +1244,7 @@ if (!ENV_IS_BROWSER) return;
1153
1244
  compression: 'none',
1154
1245
  object: false,
1155
1246
  assetpack: null,
1247
+ animations: false,
1156
1248
 
1157
1249
  loadworkers: [
1158
1250
  ],
@@ -1183,29 +1275,13 @@ if (!ENV_IS_BROWSER) return;
1183
1275
  this.instances.push(group);
1184
1276
  return group;
1185
1277
  },
1186
- fillGroup: function(group, source) {
1278
+ fillGroup: function(group, source, clone=true) {
1187
1279
  if (!source) source = this._model;
1188
1280
  if (source) {
1189
- /*
1190
- group.position.copy(source.position);
1191
- group.quaternion.copy(source.quaternion);
1192
- //group.scale.copy(source.scale);
1193
- if (source.children) {
1194
- source.children.forEach(function(n) {
1195
- group.add(n.clone());
1196
- });
1197
- }
1198
- */
1199
- var newguy = source.clone();
1281
+ var newguy = (clone ? THREE.SkeletonUtils.cloneWithAnimations(source, this.animations) : source);
1200
1282
  group.add(newguy);
1201
1283
  newguy.updateMatrix(true);
1202
1284
  newguy.updateMatrixWorld(true);
1203
-
1204
- newguy.traverse(function(n) {
1205
- if (n instanceof THREE.SkinnedMesh) {
1206
- //n.rebindByName(newguy);
1207
- }
1208
- });
1209
1285
  }
1210
1286
  return group;
1211
1287
  },
@@ -1326,7 +1402,7 @@ if (!ENV_IS_BROWSER) return;
1326
1402
  elation.bind(this, function(events) {
1327
1403
  var files = [];
1328
1404
  events.forEach(function(ev) {
1329
- var url = ev.target.responseURL,
1405
+ var url = ev.target.responseURL.replace(elation.engine.assets.corsproxy, ''),
1330
1406
  data = ev.target.response;
1331
1407
  if (url == jobdata.src) {
1332
1408
  jobdata.srcdata = data;
@@ -1335,7 +1411,11 @@ if (!ENV_IS_BROWSER) return;
1335
1411
  }
1336
1412
  });
1337
1413
  this.state = 'processing';
1338
- this.loadWithWorker(jobdata);
1414
+ if (this.isglTF(jobdata)) {
1415
+ this.loadglTF(jobdata);
1416
+ } else {
1417
+ this.loadWithWorker(jobdata);
1418
+ }
1339
1419
  elation.events.fire({element: this, type: 'asset_load_processing'});
1340
1420
  }),
1341
1421
  elation.bind(this, function(error) {
@@ -1345,6 +1425,41 @@ if (!ENV_IS_BROWSER) return;
1345
1425
  );
1346
1426
  elation.events.fire({element: this, type: 'asset_load_queued'});
1347
1427
  },
1428
+ isglTF: function(jobdata) {
1429
+ let d = new Uint8Array(jobdata.srcdata);
1430
+ let isGLB = String.fromCharCode(d[0]) == 'g' && String.fromCharCode(d[1]) == 'l' && String.fromCharCode(d[2]) == 'T' && String.fromCharCode(d[3]) == 'F';
1431
+ return isGLB;
1432
+ },
1433
+ loadglTF: function(jobdata) {
1434
+ let proxypath = this.getProxiedURL(jobdata.src);
1435
+ var loader = new THREE.GLTFLoader();
1436
+ if (elation.engine.assets.dracopath) {
1437
+ loader.setDRACOLoader(new THREE.DRACOLoader().setDecoderPath(elation.engine.assets.dracopath));
1438
+ }
1439
+ this._model = new THREE.Group();
1440
+ this._model.userData.loaded = false;
1441
+ loader.parse(jobdata.srcdata, proxypath, elation.bind(this, function(modeldata) {
1442
+ if (modeldata.scene) {
1443
+ this.loaded = true;
1444
+ this.animations = modeldata.animations;
1445
+
1446
+ // Cmompute vertex normals, if missing
1447
+ modeldata.scene.traverse(n => {
1448
+ if (n.geometry && !n.geometry.attributes.normal) {
1449
+ n.geometry.computeVertexNormals();
1450
+ }
1451
+ });
1452
+
1453
+ if (modeldata.userData && modeldata.userData.gltfExtensions && modeldata.userData.gltfExtensions.VRM) {
1454
+ THREE.VRM.from(modeldata).then(vrm => {
1455
+ this.vrm = vrm;
1456
+ this.complete(vrm.scene);
1457
+ });
1458
+ }
1459
+ this.complete(modeldata.scene);
1460
+ }
1461
+ }));
1462
+ },
1348
1463
  loadWithWorker: function(jobdata) {
1349
1464
  this._model = new THREE.Group();
1350
1465
  this._model.userData.loaded = false;
@@ -1367,7 +1482,7 @@ if (!ENV_IS_BROWSER) return;
1367
1482
  this.removePlaceholders();
1368
1483
  this._model.userData.loaded = true;
1369
1484
  //this._model.add(scene);
1370
- this.fillGroup(this._model, object);
1485
+ this.fillGroup(this._model, object, false);
1371
1486
 
1372
1487
  this.extractTextures(object);
1373
1488
  //this.assignTextures(scene);
@@ -1867,6 +1982,7 @@ if (!ENV_IS_BROWSER) return;
1867
1982
  elation.define('engine.assets.script', {
1868
1983
  assettype: 'script',
1869
1984
  src: false,
1985
+ override: false,
1870
1986
  code: false,
1871
1987
 
1872
1988
  _construct: function(args) {
@@ -1885,14 +2001,31 @@ if (!ENV_IS_BROWSER) return;
1885
2001
  elation.engine.assetdownloader.fetchURL(url).then(ev => {
1886
2002
  let decoder = new TextDecoder('utf-8');
1887
2003
  this.parse(decoder.decode(ev.target.response));
2004
+ },
2005
+ err => {
2006
+ this.handleError();
1888
2007
  });
1889
2008
  }
1890
2009
  },
1891
2010
  parse: function(data) {
1892
- //var blob = new Blob(['(function(window) {\n' + data + '\n})(self)'], {type: 'application/javascript'});
1893
- var blob = new Blob(['\n' + data + '\n'], {type: 'application/javascript'});
2011
+ // If overrides are specified, we inject them into the script as locally-scoped variables
2012
+ // This lets us bind our scripts to specific instances of objects, rather than relying on globals
2013
+ let overrideScript = '';
2014
+ if (this.override) {
2015
+ let overrides = elation.engine.assets.scriptOverrides[this.src];
2016
+ if (!overrides) {
2017
+ overrides = elation.engine.assets.scriptOverrides[this.src] = {};
2018
+ }
2019
+ for (let k in this.override) {
2020
+ overrides[k] = this.override[k];
2021
+ overrideScript += 'let ' + k + ' = elation.engine.assets.scriptOverrides["' + this.src + '"]["' + k + '"];\n';
2022
+ }
2023
+ }
2024
+ //var blob = new Blob(['\n(function() { ' + overrideScript + '\n' + data + ' })();\n'], {type: 'application/javascript'});
2025
+ var blob = new Blob(['\n{ ' + overrideScript + '\n' + data + ' };\n'], {type: 'application/javascript'});
1894
2026
  var bloburl = URL.createObjectURL(blob);
1895
2027
  this._script.src = bloburl;
2028
+ this.code = data;
1896
2029
  this.loaded = true;
1897
2030
  elation.events.fire({type: 'asset_load', element: this._script});
1898
2031
  elation.events.fire({type: 'asset_load', element: this});
@@ -1902,6 +2035,7 @@ if (!ENV_IS_BROWSER) return;
1902
2035
  },
1903
2036
  handleError: function(ev) {
1904
2037
  this._script = false;
2038
+ elation.events.fire({element: this, type: 'asset_error'});
1905
2039
  },
1906
2040
  getInstance: function(args) {
1907
2041
  if (!this._script) {
@@ -1978,7 +2112,7 @@ if (!ENV_IS_BROWSER) return;
1978
2112
  { name: 'iChannel2', value: new THREE.Texture() },
1979
2113
  { name: 'iChannel3', value: new THREE.Texture() },
1980
2114
  ];
1981
-
2115
+ this.uniformsMap = this.parseUniforms(this.uniforms);
1982
2116
  // FIXME - this hack is used to update the Shadertoy uniforms at 60fps, but it should be abstracted out and driven by the object that's using the shader
1983
2117
  // As a general shader harness, this will give us the means to update uniforms based on custom functions, so we can pass in things like mouse position,
1984
2118
  // multiple textures, audio data, etc.
@@ -1986,15 +2120,19 @@ if (!ENV_IS_BROWSER) return;
1986
2120
  let starttime = new Date().getTime();
1987
2121
  lasttime = starttime;
1988
2122
  setInterval(() => {
1989
- if (this._material && this._material.uniforms.iTime) {
1990
- let d = new Date();
1991
- let now = d.getTime();
2123
+ let d = new Date();
2124
+ let now = d.getTime();
2125
+ this.uniformsMap.iTime.value = (now - starttime) / 1000;
2126
+ this.uniformsMap.iTimeDelta.value = (now - lasttime) / 1000;
2127
+ this.uniformsMap.iFrame.value++;
2128
+ this.uniformsMap.iDate.value.set(d.getFullYear(), d.getMonth() + 1, d.getDate(), (d.getHours() * 60 + d.getMinutes()) * 60 + d.getSeconds() + d.getMilliseconds() / 1000);
1992
2129
 
1993
- this._material.uniforms.iTime.value = (now - starttime) / 1000;
1994
- this._material.uniforms.iTimeDelta.value = (now - lasttime) / 1000;
1995
- this._material.uniforms.iFrame.value++;
2130
+ if (this._material && this._material.uniforms.iTime) {
1996
2131
 
1997
- this._material.uniforms.iDate.value.set(d.getFullYear(), d.getMonth() + 1, d.getDate(), (d.getHours() * 60 + d.getMinutes()) * 60 + d.getSeconds() + d.getMilliseconds() / 1000);
2132
+ this._material.uniforms.iTime.value = this.uniformsMap.iTime.value;
2133
+ this._material.uniforms.iTimeDelta.value = this.uniformsMap.iTimeDelta.value;
2134
+ this._material.uniforms.iFrame.value = this.uniformsMap.iFrame.value;
2135
+ this._material.uniforms.iDate.value = this.uniformsMap.iDate.value;
1998
2136
  lasttime = now;
1999
2137
  }
2000
2138
  }, 16);
@@ -2010,6 +2148,7 @@ if (!ENV_IS_BROWSER) return;
2010
2148
  elation.engine.assetdownloader.fetchURL(this.getProxiedURL(this.fragment_src)).then(ev => {
2011
2149
  let decoder = new TextDecoder('utf-8');
2012
2150
  let shadercode = decoder.decode(ev.target.response);
2151
+ this.loaded = true;
2013
2152
  if (this.shadertype == 'default') {
2014
2153
  this._material.fragmentShader = shadercode;
2015
2154
  } else if (this.shadertype == 'shadertoy') {
@@ -2065,7 +2204,7 @@ if (!ENV_IS_BROWSER) return;
2065
2204
  }
2066
2205
  }
2067
2206
  if (this.uniforms) {
2068
- this._material.uniforms = this.parseUniforms(this.uniforms);
2207
+ this._material.uniforms = this.uniformsMap;
2069
2208
  }
2070
2209
  this.complete();
2071
2210
  },
@@ -2077,7 +2216,7 @@ if (!ENV_IS_BROWSER) return;
2077
2216
  parseUniforms(uniforms) {
2078
2217
  let matuniforms = {};
2079
2218
  uniforms.forEach(u => {
2080
- matuniforms[u.name] = { value: u.value };
2219
+ matuniforms[u.name] = u;
2081
2220
  });
2082
2221
  return matuniforms;
2083
2222
  },
@@ -6,7 +6,7 @@ elation.require([
6
6
  'engine.external.pako',
7
7
  'engine.external.zlib.inflate',
8
8
  'engine.external.xmldom',
9
- 'engine.external.three.three', 'engine.external.three.three-loaders',
9
+ 'engine.external.three.three', 'engine.external.three.three-loaders', 'engine.external.three.fflate',
10
10
  'engine.external.textdecoder-polyfill'
11
11
  ], function() {
12
12
 
@@ -385,13 +385,6 @@ elation.require([
385
385
  convertToJSON: function(scene) {
386
386
  var json;
387
387
  if (scene) {
388
- // Convert Geometries to BufferGeometries
389
- scene.traverse(function(n) {
390
- if (n.geometry && n.geometry instanceof THREE.Geometry) {
391
- var bufgeo = new THREE.BufferGeometry().fromGeometry(n.geometry);
392
- n.geometry = bufgeo;
393
- }
394
- });
395
388
  json = scene.toJSON();
396
389
  }
397
390
  return json;
@@ -411,7 +404,7 @@ elation.require([
411
404
  var loader = new THREE.ColladaLoader();
412
405
  var corsproxy = elation.engine.assets.corsproxy || '';
413
406
  loader.setResourcePath(corsproxy + baseurl);
414
- loader.options.upAxis = 'Y';
407
+ //loader.options.upAxis = 'Y';
415
408
  var xml = this.convertArrayBufferToString(bindata);
416
409
  var parsed = loader.parse(xml);
417
410
  var imageids = Object.keys(parsed.library.images);
@@ -420,28 +413,14 @@ elation.require([
420
413
  //parsed.library.images[imageids[i]].build = this.getProxiedURL(img);
421
414
  }
422
415
  parsed.scene.traverse(function(n) {
423
- if ((n.geometry instanceof THREE.BufferGeometry && !n.geometry.attributes.normals) ||
424
- (n.geometry instanceof THREE.Geometry && !n.geometry.faceVertexNormals)) {
425
- n.geometry.computeFaceNormals();
416
+ if (n.geometry && n.geometry instanceof THREE.BufferGeometry && !n.geometry.attributes.normals) {
417
+ //n.geometry.computeFaceNormals();
426
418
  n.geometry.computeVertexNormals();
427
419
  }
428
- // Convert to BufferGeometry for better loading efficiency
429
- if (n.geometry && n.geometry instanceof THREE.Geometry) {
430
- n.geometry.mergeVertices();
431
- var bufgeo = new THREE.BufferGeometry().fromGeometry(n.geometry);
432
- n.geometry = bufgeo;
433
- } else if (n.geometry && n.geometry instanceof THREE.BufferGeometry) {
434
- /*
435
- var geo = new THREE.Geometry().fromBufferGeometry(n.geometry);
436
- geo.mergeVertices();
437
- geo.computeVertexNormals();
438
- n.geometry = new THREE.BufferGeometry().fromGeometry(geo);
439
- */
440
- }
441
420
  });
442
421
  data = parsed;
443
422
 
444
- data.scene.animations = parsed.animations;
423
+ //data.scene.animations = parsed.animations;
445
424
  data.scene.rotation.x = -Math.PI/2;
446
425
  data.scene.updateMatrix();
447
426
  resolve(data.scene.toJSON());
@@ -460,13 +439,6 @@ elation.require([
460
439
  var data = this.convertArrayBufferToString(bindata);
461
440
  var modeldata = loader.parse(data);
462
441
 
463
- modeldata.traverse(function(n) {
464
- if (n.geometry && n.geometry instanceof THREE.Geometry) {
465
- var bufgeo = new THREE.BufferGeometry().fromGeometry(n.geometry);
466
- n.geometry = bufgeo;
467
- }
468
- });
469
-
470
442
  resolve(modeldata.toJSON());
471
443
  }));
472
444
  }