Search code examples
javascriptaugmented-realityspark-ar-studio

How to monitor object position in SparkAR?


I'm scripting in SparkAR and just trying to constantly check the world (not local) position of some objects.

So far, I've tried:

Promise.all([

    Scene.root.findFirst('plane4'),

]).then(function (results) {

    const plane4 = results[0];

    // Get the timer ready
    reset();
    start();

    function reset() {

        Patches.inputs.setPulse('SendReset', Reactive.once());
    }

    function start() {


    plane4.monitor({ fireOnInitialValue: true }).subscribe(function (p) {
        Diagnostics.log(p.position.x.newValue);
    })

Also tried taking off the newValue, taking off the x, etc. How can I check for an object's position over time?


Solution

    1. To access the World transform position, you must use the path plane4.worldTransform.
    2. You can subscribe for changes any signal in Spark ar. For example: you can subscribe for changes to plane4.worldTransform.x since this is ScalarSignal. But you cannot subscribe to plane4 or plane4.worldTransform as they are not signals, but simply considered objects of the scene.

    You can find out more about each type of Spark ar here https://sparkar.facebook.com/ar-studio/learn/developer/reference/scripting/summary

    Below is a working example code for subscribing to the world X coordinate for plane4

    plane4.worldTransform.x.monitor().subscribe(function (posX) {
        Diagnostics.log(posX.newValue);
    });
    

    UPD: added an example of checking the positions of many objects

    The developers of the Spark AR engine recommend using as few signal subscriptions as possible, since subscriptions greatly affect performance, so you need to skillfully use the Reactive module and subscribe to complex composite signals. In the example, I used 2 objects, not 9. Also, I did not use pure 0, but with some small deviations.

    Pay attention to the comments in the code.

    const Scene = require('Scene');
    const Reactive = require('Reactive');
    const Diagnostics = require('Diagnostics');
    
    const planes = [];
    const objectsCount = 2;
    
    Promise.all([
        Scene.root.findFirst('plane0'),
        Scene.root.findFirst('plane1'),
    ]).then(function(result)
    {
        for(let i = 0; i < objectsCount; ++i)
        {
            planes.push(result[i]);
        }
    
        /*
        The case when it is important to you which of the objects is in the position {0,0}
        can be dispensed with using N subscriptions. Where N is the number of objects.
    
        For example, a game where a character collects coins when he touches them and
         you need to know which coin you need to hide from the screen.
        */
        // Case 1 begin
        for(let i = 0; i < objectsCount; ++i)
        {
            Reactive.and(
                Reactive.and(
                    planes[i].worldTransform.x.le(0.01),
                    planes[i].worldTransform.x.ge(-0.01)
                ),
                Reactive.and(
                    planes[i].worldTransform.y.le(0.01),
                    planes[i].worldTransform.y.ge(-0.01)
                )
            )
            .monitor().subscribe(function(isPosZero)
            {
                if(isPosZero.newValue)
                {
                    Diagnostics.log("plane" + i.toString() + " pos is zero");
                }
            });
        }
        // Case 1 end
        
        
        /*
        The case when it does not matter to you which particular object is in the position {0,0}.
        Here you can get by with just one subscription.
        
        For example, a game where a player dies when he touches the spikes, 
        no matter which spike he touches, it is important that you kill the character.
        */
        // Case 2 begin
        let myOrList = [];
        
        for (let i = 0; i < objectsCount; ++i)
        {
            myOrList.push(
                Reactive.and(
                    Reactive.and(
                        planes[i].worldTransform.x.le(0.01),
                        planes[i].worldTransform.x.ge(-0.01)
                    ),
                    Reactive.and(
                        planes[i].worldTransform.y.le(0.01),
                        planes[i].worldTransform.y.ge(-0.01)
                    )
                )
            );
        }
    
        Reactive.orList(
            myOrList
        ).monitor().subscribe(function(isPosZero)
        {
            Diagnostics.log('the position of one of the objects is {0,0}');
        });
        // Case 2 end
    });