javascriptreactjsaugmented-realityaframemindar

Set individual sound for each aframe entity


I wanna realize next functionality: user are scanning one image (it is a target, all ones are 5 item), and after than as the picture will be scan - will start playing sound (related to this image).I am using Arame library (creating scene and sound objects) and mindAR (detect of scaned photos); All are based on React function components. For test I`ve created mock:

<a-scene ref={sceneRef} mindar-image={`imageTargetSrc: http://localhost:5000/wild%20nature/wild_nature.mind; autoStart: false; uiLoading: true; uiError: true; uiScanning: true; maxTrack: 3`} color-space="sRGB" embedded renderer="colorManagement: true, physicallyCorrectLights" vr-mode-ui="enabled: false" device-orientation-permission-ui="enabled: false">
              <a-assets>
  
                   <audio id="lion" src="http://localhost:5000/wild%20nature/lion/lion.mp3" preload='auto'></audio>
                   <audio id="owl" src="http://localhost:5000/wild%20nature/owl/owl.mp3" preload='auto'></audio>


              </a-assets>
              

              <a-camera position="0 0 0" look-controls="enabled: true"></a-camera>

             
                <a-entity 
                  mindar-image-target="targetIndex: 4"
                  geometry="primitive: plane" 
                  position=" 0 0 0" 
                  sound="src:#lion;" 
                />
                <a-entity 
                  mindar-image-target="targetIndex: 3"
                  geometry="primitive: plane" 
                  position=" 0 0 0" 
                  sound="src:#owl;" 
                />
            </a-scene>

At this moment: When I scan a lion photo - all works correctly, but when I change scaned photo to owl - sound doesn`t play.

import React, { useCallback, useEffect, useRef, useState } from 'react';
import 'aframe';
import 'mind-ar/dist/mindar-image-aframe.prod.js';
import { getChildrenByGroup } from './../utils/helpers'; 

const MindARViewer = ({children_AR_list}) => {
  
  const sceneRef = useRef(null);
  const sceneRefering= useRef([]);
  const [targetFound, setTargetFound] = useState("");

  let [targetFoundCounter,setTargetFoundCounter] = useState(0);
  const [groupedChildren, setGroupedChildren] = useState([]);

  useEffect(() => {
    setGroupedChildren(getChildrenByGroup(children_AR_list))
    
  }, []);

  useEffect(() => {
    const sceneEl = sceneRef.current;
    const arSystem = sceneEl.systems?.["mindar-image-system"];
    
    const entity = document.querySelector('a-entity[sound]');

    // Start AR system when scene starts rendering
    sceneEl.addEventListener('loaded', () => {
      arSystem.start();
    });

    // Handle target detection events
    
    sceneEl.addEventListener('targetFound', () => {
      setTargetFound(entity?.components.sound.parsingAttrValue)
      console.log(`Target found:`, entity?.components.sound.parsingAttrValue);
      
      // setTargetFoundCounter(targetFoundCounter++)

      entity?.components.sound?.playSound();
    });



    sceneEl.addEventListener('targetLost', () => {
      entity?.components.sound?.pause();
    });

    return () => {
      arSystem.stop();
      entity?.components.sound.pause();
    }
  }, []);

   



  return (
    <>
    
    {
      
      
          <>
           <a-scene ref={sceneRef} mindar-image={`imageTargetSrc: http://localhost:5000/wild%20nature/wild_nature.mind; autoStart: false; uiLoading: true; uiError: true; uiScanning: true; maxTrack: 3`} color-space="sRGB" embedded renderer="colorManagement: true, physicallyCorrectLights" vr-mode-ui="enabled: false" device-orientation-permission-ui="enabled: false">
              <a-assets>
  
                   <audio id="lion" src="http://localhost:5000/wild%20nature/lion/lion.mp3" preload='auto'></audio>
                   <audio id="owl" src="http://localhost:5000/wild%20nature/owl/owl.mp3" preload='auto'></audio>


              </a-assets>
              

              <a-camera position="0 0 0" look-controls="enabled: true"></a-camera>

             
                <a-entity 
                  mindar-image-target="targetIndex: 4"
                  geometry="primitive: plane" 
                  position=" 0 0 0" 
                  sound="src:#lion;" 
                />
                <a-entity 
                  mindar-image-target="targetIndex: 3"
                  geometry="primitive: plane" 
                  position=" 0 0 0" 
                  sound="src:#owl;" 
                />
            </a-scene>
          </>
     
    }
   
    
    </>
  )
}

export default MindARViewer;


Solution

  • You're only selecting one entity with a sound component using

    const entity = document.querySelector('a-entity[sound]');

    So even when you detect the owl target, you're still referencing the lion entity (the first one found in the DOM).

    Modify this -

    useEffect(() => {
      const sceneEl = sceneRef.current;
      const arSystem = sceneEl.systems?.["mindar-image-system"];
    
      sceneEl.addEventListener("loaded", () => {
        arSystem.start();
    
        // Attach to each entity with a mindar target
        const entities = sceneEl.querySelectorAll('a-entity[mindar-image-target]');
    
        entities.forEach((entity) => {
          entity.addEventListener("targetFound", () => {
            entity.components.sound?.playSound();
          });
    
          entity.addEventListener("targetLost", () => {
            entity.components.sound?.pause();
          });
        });
      });
    
      return () => {
        arSystem.stop();
      };
    }, []);