We use cookies to ensure that we give you the best experience on our website. If you continue to use this site we will assume that you are happy with it.

Wait to execute function in run code till first frame is rendered

Home Forums Programming Wait to execute function in run code till first frame is rendered

Tagged: 

Viewing 14 posts - 1 through 14 (of 14 total)
  • Author
    Posts
  • #32334
    shantiscript
    Customer

    Hi,
    i am triggering a gltf animation by using a modification of the puzzle code for playing animations from within the runCode() section.
    The animations already start playing though before the first render is finished. So half of the animation has already played one the scene actually starts rendering.
    How can i make sure that a function is executed just when the first frame has been rendered?

    #32335
    shantiscript
    Customer

    Just to add when using the play animation puzzle in the puzzle editor the same thing happens.
    The animation starts playing before the first frame is rendered and half of the animation already happened once the first frame renders.
    I can’t use autostart (in Blender export) to trigger the animation as there are some other dependencies in javascript in my project, so i need to start the animation by using javascript/puzzle

    #32336

    Hi,

    you can possibly load the animation stopped initially (disable Auto run in Blender), and then start by the play animation puzzle placed in the Main tab.

    Chief 3D Verger | LinkedIn | Twitter

    #32352
    GLiFTeK
    Customer

    You could do what Yuri said but also hide the animated object at scene start, play the animation, use a time puzzle for a little over its animation time length, stop after one play then show it, then it’s “buffered”? For the user to hit play when they want.

    #32356
    shantiscript
    Customer

    Hi thanks for the replies!!!
    I don’t think you really understand the problem i am running into, so i will try to rephrase.
    I disabled auto run in blender for the animation and used the play animation puzzle placed in the main tab as Yuri described.

    The problem with that is that the animation starts playing the key frames of the animation before the scene is visible to the user (before the first frame of the actual app is rendered to the screen). Means the animation already starts playing in the background while the loading screen is still indicating the loading. So half of the animation has played once the scene is actually visible to the user.

    This is because in my understanding the run() method that is called inside of app.loadScene triggers the render of the app instance after the loadScene callback is fired (once the gltf loader has fetched the gltf into the app instance)
    But code thats executed in the puzzles or in run() doesn’t wait for the render function to finish but its executed asynchronously right after the run() function has been called. It doesn’t wait for the first render to be finished and there is no callback or promise to wait for that to happen.
    So if the render takes longer to execute all animations triggered with the puzzle on start or in run() will already start running in the background

    // loaded GLTF 2.0 asset
    var url = 'template.gltf';
    
    // construct a new application with simple rotating preloader
    var app = new v3d.App('v3d-container', null, new v3d.SimplePreloader({ container: 'v3d-container' }));
    
    // load main scene
    app.loadScene(url, function() {
        app.enableControls();
        app.run();
        runCode();
    });
    
    function runCode() {
        // place your own code here
    }

    So i need a way to wait for the animation to start until the first render is completed.

    #32363

    Hi,

    So i need a way to wait for the animation to start until the first render is completed.

    You can possibly put your function inside a timeout with the 0 seconds period. This will cause it to wait until the next frame is rendered.

    Chief 3D Verger | LinkedIn | Twitter

    #32374
    shantiscript
    Customer

    Awesome that worked!

    #32426
    GLiFTeK
    Customer

    Wow that’s important info.
    Glad it worked, and glad I also know now.
    High fives all around! :good:

    #32462
    GLiFTeK
    Customer

    Hi,

    So i need a way to wait for the animation to start until the first render is completed.

    You can possibly put your function inside a timeout with the 0 seconds period. This will cause it to wait until the next frame is rendered.

    Yuri did you mean that in re to JavaScript or puzzles? Ie: timeout function vs procedures?

    #32465

    You can use either the after or the set timer puzzle or the setTimeout JS function. These are basically the same.

    Chief 3D Verger | LinkedIn | Twitter

    #32467
    GLiFTeK
    Customer

    You can use either the after or the set timer puzzle or the setTimeout JS function. These are basically the same.

    Ok that’s what I thought.
    Thanks :good:

    #36044
    shantiscript
    Customer

    Just an update on this for anyone who might come across this again. There is a better way than using a timeout function to solve this. If the timeout function is too short on a slow device you could still run into running functions before the first frame is actually rendered.
    The app instance has a property called frame

    https://www.soft8soft.com/docs/api/en/extras/App.html#frame

    By checking if the the first app frame has be rendered (for example using an if condition) you can make sure that nothing runs before the first frame has be rendered to the screen

    #36054
    GLiFTeK
    Customer

    Possibly use a timer puzzle for the first puzzle that executes and say “after frame “0” to have the “first” thing in your puzzles network start?

    #36066
    shantiscript
    Customer

    Yeah in the puzzles you would create some function, either a while loop that constantly checks if the first frame has been rendered. Or a interval function that checks if the first frame has been rendered.

    In code i created a function that first checks if the first frame has been rendered already and if not it runs a check function at an interval of 200ms. The function returns a promise in booth cases

    function waitForFirstFrame() {
      return new Promise(resolve => {
        if (appInstance.frame >= 1) {
          resolve()
        } else {
          const waitForFirstFrame = setInterval(() => {
            if (appInstance.frame >= 1) {
              clearInterval(waitForFirstFrame)
              resolve()
            }
          }, 200)
        }
      })
    }

    you can then run or trigger anything that needs to wait till the first frame has ben rendered in the then() block of that function

    waitForFirstFrame().then(runAnimations(animations, { frame: 553, speed: 1 }))

    in the example runAnimations will wait till the first frame has been rendered and then start an animation

Viewing 14 posts - 1 through 14 (of 14 total)
  • You must be logged in to reply to this topic.