Você não pode selecionar mais de 25 tópicos Os tópicos devem começar com uma letra ou um número, podem incluir traços ('-') e podem ter até 35 caracteres.

demo.js 5.4KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187
  1. window.addEventListener('load', () => {
  2. const my = { };
  3. async function initialize(ar)
  4. {
  5. // add lights
  6. const ambientLight = new THREE.AmbientLight(0x808080);
  7. const directionalLight = new THREE.DirectionalLight(0xffffff, 0.75);
  8. directionalLight.position.set(0, 0, -1);
  9. ar.scene.add(ambientLight);
  10. ar.scene.add(directionalLight);
  11. // create cubes
  12. my.cubes = [
  13. createCube(ar, 1.0, -0.5, 0x00ff00),
  14. createCube(ar, -1.0, -0.5, 0xffff00),
  15. createCube(ar, 0.0, -0.5, 0x0077ff),
  16. ];
  17. // create text
  18. my.text = await createText(ar, 'Tap on any cube', 0x88ffee);
  19. my.text.position.set(-1.5, 0.25, 0.5);
  20. // setup interactivity
  21. my.pointer = createPointer(ar);
  22. my.raycaster = new THREE.Raycaster();
  23. }
  24. function createCube(ar, x, y, color, length = 0.7)
  25. {
  26. const geometry = new THREE.BoxGeometry(length, length, length);
  27. const material = new THREE.MeshPhongMaterial({ color });
  28. const cube = new THREE.Mesh(geometry, material);
  29. cube.position.x = x;
  30. cube.position.y = y;
  31. cube.position.z = length / 2;
  32. cube.userData.color = color;
  33. material.opacity = 1.0;
  34. material.transparent = true;
  35. ar.root.add(cube);
  36. return cube;
  37. }
  38. async function createText(ar, text, color = 0xffffff)
  39. {
  40. const loader = new THREE.FontLoader();
  41. const fontURL = '../assets/helvetiker_bold.typeface.json';
  42. const font = await loader.loadAsync(fontURL);
  43. const material = new THREE.MeshPhongMaterial({ color });
  44. const geometry = new THREE.TextGeometry(text, {
  45. font: font,
  46. size: 0.3,
  47. height: 0.05,
  48. });
  49. const mesh = new THREE.Mesh(geometry, material);
  50. ar.root.add(mesh);
  51. return mesh;
  52. }
  53. function createPointer(ar)
  54. {
  55. const pointer = {
  56. position: new THREE.Vector2(),
  57. down: false,
  58. get active()
  59. {
  60. return this.down && Math.max(Math.abs(this.position.x), Math.abs(this.position.y)) <= 1.0;
  61. }
  62. };
  63. function updatePosition(event)
  64. {
  65. const canvas = ar.renderer.domElement;
  66. const rect = canvas.getBoundingClientRect();
  67. const x = event.pageX - (rect.left + window.scrollX);
  68. const y = event.pageY - (rect.top + window.scrollY);
  69. // normalize to [-1,1] x [-1,1]
  70. pointer.position.x = 2.0 * x / rect.width - 1.0;
  71. pointer.position.y = -2.0 * y / rect.height + 1.0;
  72. }
  73. // setup pointer interactivity
  74. window.addEventListener('pointermove', event => {
  75. updatePosition(event);
  76. });
  77. window.addEventListener('pointerdown', event => {
  78. updatePosition(event);
  79. pointer.down = true;
  80. });
  81. window.addEventListener('pointerup', event => {
  82. pointer.down = false;
  83. });
  84. // done!
  85. return pointer;
  86. }
  87. function animate(ar)
  88. {
  89. // reset all cubes
  90. for(let i = 0; i < my.cubes.length; i++) {
  91. my.cubes[i].material.color.setHex(my.cubes[i].userData.color);
  92. my.cubes[i].scale.z = 1.0;
  93. }
  94. // interact with objects via raycasting
  95. if(my.pointer.active) {
  96. my.raycaster.setFromCamera(my.pointer.position, ar.camera);
  97. const intersections = my.raycaster.intersectObjects(my.cubes);
  98. for(let i = 0; i < intersections.length; i++) {
  99. // create the appearance of a pushed button
  100. const object = intersections[i].object;
  101. object.material.color.setHex(0xff3333);
  102. object.scale.z = 0.2;
  103. }
  104. }
  105. }
  106. async function startARSession()
  107. {
  108. if(!AR.isSupported()) {
  109. throw new Error(
  110. 'This device is not compatible with this AR experience.\n\n' +
  111. 'User agent: ' + navigator.userAgent
  112. );
  113. }
  114. //AR.Settings.powerPreference = 'low-power';
  115. const tracker = AR.Tracker.ImageTracker();
  116. await tracker.database.add([{
  117. name: 'my-reference-image',
  118. image: document.getElementById('my-reference-image')
  119. }]);
  120. const viewport = AR.Viewport({
  121. container: document.getElementById('ar-viewport'),
  122. hudContainer: document.getElementById('ar-hud')
  123. });
  124. const video = document.getElementById('my-video');
  125. const useWebcam = (video === null);
  126. const source = useWebcam ?
  127. AR.Source.Camera({ resolution: 'md' }) :
  128. AR.Source.Video(video);
  129. const session = await AR.startSession({
  130. mode: 'immersive',
  131. viewport: viewport,
  132. trackers: [ tracker ],
  133. sources: [ source ],
  134. stats: true,
  135. gizmos: true,
  136. });
  137. const scan = document.getElementById('scan');
  138. tracker.addEventListener('targetfound', event => {
  139. session.gizmos.visible = false;
  140. if(scan)
  141. scan.hidden = true;
  142. });
  143. tracker.addEventListener('targetlost', event => {
  144. session.gizmos.visible = true;
  145. if(scan)
  146. scan.hidden = false;
  147. });
  148. return session;
  149. }
  150. // enchant!
  151. encantar(startARSession, animate, initialize);
  152. });