Vous ne pouvez pas sélectionner plus de 25 sujets Les noms de sujets doivent commencer par une lettre ou un nombre, peuvent contenir des tirets ('-') et peuvent comporter jusqu'à 35 caractères.

demo.js 7.3KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273
  1. /**
  2. * Augmented Reality demo using the babylon.js plugin for encantar.js
  3. * @author Alexandre Martins <alemartf(at)gmail.com> (https://github.com/alemart/encantar-js)
  4. */
  5. (function() {
  6. /**
  7. * Augmented Reality Demo
  8. */
  9. class EnchantedDemo extends ARDemo
  10. {
  11. /**
  12. * Constructor
  13. */
  14. constructor()
  15. {
  16. super();
  17. this._objects = { };
  18. }
  19. /**
  20. * Start the AR session
  21. * @returns {Promise<Session>}
  22. */
  23. async startSession()
  24. {
  25. if(!AR.isSupported()) {
  26. throw new Error(
  27. 'This device is not compatible with this AR experience.\n\n' +
  28. 'User agent: ' + navigator.userAgent
  29. );
  30. }
  31. const tracker = AR.Tracker.ImageTracker();
  32. await tracker.database.add([
  33. {
  34. name: 'mage',
  35. image: document.getElementById('mage')
  36. },
  37. {
  38. name: 'cat',
  39. image: document.getElementById('cat')
  40. }
  41. ]);
  42. const viewport = AR.Viewport({
  43. container: document.getElementById('ar-viewport'),
  44. hudContainer: document.getElementById('ar-hud')
  45. });
  46. const video = document.getElementById('my-video');
  47. const useWebcam = (video === null);
  48. const source = useWebcam ? AR.Source.Camera() : AR.Source.Video(video);
  49. const session = await AR.startSession({
  50. mode: 'immersive',
  51. viewport: viewport,
  52. trackers: [ tracker ],
  53. sources: [ source ],
  54. stats: true,
  55. gizmos: true,
  56. });
  57. const scan = document.getElementById('scan');
  58. tracker.addEventListener('targetfound', event => {
  59. session.gizmos.visible = false;
  60. if(scan)
  61. scan.hidden = true;
  62. this._onTargetFound(event.referenceImage);
  63. });
  64. tracker.addEventListener('targetlost', event => {
  65. session.gizmos.visible = true;
  66. if(scan)
  67. scan.hidden = false;
  68. this._onTargetLost(event.referenceImage);
  69. });
  70. return session;
  71. }
  72. /**
  73. * Initialization
  74. * @param {ARSystem} ar
  75. * @returns {Promise<void>}
  76. */
  77. async init(ar)
  78. {
  79. // Do not automatically play an animation when loading GLTF models
  80. BABYLON.SceneLoader.OnPluginActivatedObservable.add(loader => {
  81. if(loader.name == 'gltf') {
  82. loader.animationStartMode = BABYLON.GLTFLoaderAnimationStartMode.NONE;
  83. }
  84. });
  85. // Change the point of view - slightly
  86. ar.root.position.y = -0.5;
  87. // Initialize objects
  88. this._initLight(ar);
  89. this._initText(ar);
  90. this._initMagicCircle(ar);
  91. await Promise.all([
  92. this._initMage(ar),
  93. this._initCat(ar),
  94. ]);
  95. }
  96. /**
  97. * Animation loop
  98. * @param {ARSystem} ar
  99. * @returns {void}
  100. */
  101. update(ar)
  102. {
  103. const delta = ar.session.time.delta; // given in seconds
  104. this._animateMagicCircle(delta);
  105. }
  106. // ------------------------------------------------------------------------
  107. _initLight(ar)
  108. {
  109. const light = new BABYLON.HemisphericLight('light', BABYLON.Vector3.Down());
  110. light.intensity = 1.0;
  111. light.diffuse.set(1, 1, 0.9);
  112. light.specular.set(0, 0, 0);
  113. }
  114. _initMagicCircle(ar)
  115. {
  116. // create a magic circle
  117. const magicCircle = BABYLON.MeshBuilder.CreatePlane('magic-circle', {
  118. width: 1,
  119. height: 1,
  120. sideOrientation: BABYLON.Mesh.DOUBLESIDE
  121. });
  122. magicCircle.material = new BABYLON.StandardMaterial('magic-circle-material');
  123. magicCircle.material.diffuseTexture = new BABYLON.Texture('../assets/magic-circle.png');
  124. magicCircle.material.diffuseTexture.hasAlpha = true;
  125. magicCircle.material.useAlphaFromDiffuseTexture = true;
  126. magicCircle.material.diffuseColor.set(0, 0, 0);
  127. magicCircle.material.emissiveColor.set(1, 1, 1);
  128. magicCircle.material.unlit = true;
  129. magicCircle.rotation.set(-Math.PI / 2, 0, 0);
  130. magicCircle.scaling.set(4, 4, 1);
  131. // make it a child of ar.root
  132. magicCircle.parent = ar.root;
  133. // save a reference
  134. this._objects.magicCircle = magicCircle;
  135. }
  136. _initText(ar)
  137. {
  138. const text = BABYLON.MeshBuilder.CreatePlane('text', {
  139. width: 1,
  140. height: 1,
  141. sideOrientation: BABYLON.Mesh.DOUBLESIDE
  142. });
  143. text.material = new BABYLON.StandardMaterial('text-material');
  144. text.material.diffuseTexture = new BABYLON.Texture('../assets/it-works.png');
  145. text.material.diffuseTexture.hasAlpha = true;
  146. text.material.useAlphaFromDiffuseTexture = true;
  147. text.material.diffuseColor.set(0, 0, 0);
  148. text.material.emissiveColor.set(1, 1, 1);
  149. text.material.unlit = true;
  150. text.position.set(0, 2, 0.5);
  151. text.scaling.set(3, 1.5, 1);
  152. text.parent = ar.root;
  153. this._objects.text = text;
  154. }
  155. async _initMage(ar)
  156. {
  157. // load the mage
  158. const gltf = await BABYLON.SceneLoader.ImportMeshAsync('', '../assets/', 'mage.glb');
  159. const mage = gltf.meshes[0];
  160. mage.scaling.set(0.7, 0.7, 0.7);
  161. // play an animation
  162. const anim = gltf.animationGroups.find(anim => anim.name == 'Idle');
  163. if(anim)
  164. anim.play(true);
  165. // make the mage a child of ar.root
  166. mage.parent = ar.root;
  167. // save a reference
  168. this._objects.mage = mage;
  169. }
  170. async _initCat(ar)
  171. {
  172. const gltf = await BABYLON.SceneLoader.ImportMeshAsync('', '../assets/', 'cat.glb');
  173. const cat = gltf.meshes[0];
  174. cat.scaling.set(0.7, 0.7, 0.7);
  175. const anim = gltf.animationGroups.find(anim => anim.name == 'Cheer');
  176. if(anim)
  177. anim.play(true);
  178. cat.parent = ar.root;
  179. this._objects.cat = cat;
  180. }
  181. _animateMagicCircle(delta)
  182. {
  183. const TWO_PI = 2.0 * Math.PI;
  184. const ROTATIONS_PER_SECOND = 1.0 / 8.0;
  185. this._objects.magicCircle.rotate(BABYLON.Axis.Z, -TWO_PI * ROTATIONS_PER_SECOND * delta);
  186. }
  187. _onTargetFound(referenceImage)
  188. {
  189. // change the scene based on the tracked image
  190. switch(referenceImage.name) {
  191. case 'mage':
  192. this._objects.mage.setEnabled(true);
  193. this._objects.cat.setEnabled(false);
  194. this._objects.text.setEnabled(false);
  195. this._objects.magicCircle.material.emissiveColor.fromHexString('#beefff');
  196. break;
  197. case 'cat':
  198. this._objects.mage.setEnabled(false);
  199. this._objects.cat.setEnabled(true);
  200. this._objects.text.setEnabled(true);
  201. this._objects.magicCircle.material.emissiveColor.fromHexString('#ffffaa');
  202. break;
  203. }
  204. }
  205. _onTargetLost(referenceImage)
  206. {
  207. }
  208. }
  209. /**
  210. * Start the Demo
  211. * @returns {void}
  212. */
  213. function main()
  214. {
  215. const demo = new EnchantedDemo();
  216. if(typeof encantar === 'undefined')
  217. throw new Error(`Can't find the babylon.js plugin for encantar.js`);
  218. encantar(demo).catch(error => {
  219. alert(error.message);
  220. });
  221. }
  222. document.addEventListener('DOMContentLoaded', main);
  223. })();