Zimbofly Posted July 23, 2014 Share Posted July 23, 2014 I've been using tween.js with three.js with good results for auto animating camera with hotkeys. is there something simmilar that will work with babylon? what I'm trying to achieve for example - press key '1' and camera tweens to a certain location along a pathpress key '2' and camera goes to a different location. any ideas to set me on the right path would be much appreciated. ta. Quote Link to comment Share on other sites More sharing options...
Dad72 Posted July 23, 2014 Share Posted July 23, 2014 It is very simple with the animation of camera and events or Action soon with the support keyUp, keyDown Quote Link to comment Share on other sites More sharing options...
Temechon Posted July 23, 2014 Share Posted July 23, 2014 I do agree with Zimbofly, predefined tweens would be great. Like this one, but in 3D Quote Link to comment Share on other sites More sharing options...
GameMonetize Posted July 24, 2014 Share Posted July 24, 2014 We can almost do that right now.You can at anytime create an animation from the current position to a specific position and launch it: var keys = [ { frame: 0, value: this.position }, { frame: 100, value: newPosition } ]; var dataType = Animation.ANIMATIONTYPE_VECTOR3; var animation = new BABYLON.Animation("myTweenedAnimation", this.position, 100, dataType, Animation.ANIMATIONLOOPMODE_CONSTANT); animation.setKeys(keys); scene.beginDirectAnimation(this, [animation], 0, 100); Zimbofly 1 Quote Link to comment Share on other sites More sharing options...
Zimbofly Posted July 29, 2014 Author Share Posted July 29, 2014 thanks DeltaKosh - using that code in conjunction with window.addEventListener("keydown", function (event) -and reading this great tutorial http://blogs.msdn.com/b/davrous/archive/2014/02/19/coding4fun-tutorial-creating-a-3d-webgl-procedural-qrcode-maze-with-babylon-js.aspx window.addEventListener("keydown", function (event) { //left wall //hotkey no. 1 if (event.keyCode === 49 || event.keyCode === 97) { animateCameraPositionAndRotation(camera, camera.position, new BABYLON.Vector3(LWallXCamera, cameraHeight, startPos), camera.rotation, new BABYLON.Vector3(0, faceLeft, camera.rotation.z)); } now to see if I can chain animations to make camera move around objects great forum - thanks! Quote Link to comment Share on other sites More sharing options...
JackFalcon Posted May 1, 2017 Share Posted May 1, 2017 Hello, Here is a brief on Tween.js. 3 Examples Applying Tween.js with Babylon.js: http://anymscape.com/BJSDEMOS/tweendemo4/ Tween concept was innovated at Pixar at some point (I think), Catmull, etc. This integration is pretty straight-forward. Maybe even harmonious. It has good modular packaging for myriad-interpolation-variations. Kind of like a pocket-sized power tool. Most interesting, it gives a cross-context "hybrid-interface" of rich 2D And 3D visual animations.... in the last example. Example 1: Hybrid UI - interface-level, just like jquery, d3, etc... moving stuff around. Example 2: Complex UI - chain html into rich-components like this (font-awesome) starbar. Example 3: 3D world mix - this one is really interesting. RequestAnimation Meld with BeforeRender Loop. Because of the nature of the examples, I'll drop the code here. I can do a github. Example 1: Moving a simple txtBox horizontally with a nice Cubic Interpolation Curve: - setup - easy: <!--TWEENJS--> <script src="../lib/tweenjs/stats.min.js"></script><!--optional bonus points--> <script src="../lib/tweenjs/Tween.js"></script> <script src="../lib/tweenjs/RequestAnimationFrame.js"></script> - minor tricky part next. This master loop needs to go at the bottom of the code. Just like render loops, always have to go last. Infinite loops are so self-centered. /*****************************MASTER-TWEENJS-LOOP****************************\ - Loop for all TWEENJS interpolation updates. Without '.update()' call no TWEENS run. \****************************************************************************/ requestAnimationFrame(TWEEN_LOOP); function TWEEN_LOOP(time) { TWEEN.update(time); //trigger all tween interpolation updates. requestAnimationFrame(TWEEN_LOOP); //recursion, TWEEN_LOOP. } /**************************-END-TWEEN_LOOP-*********************************/ - So put at bottom, and now you can tween 'all the things'... Weird on brain? Yes, it will improve and make sense L8r... Now add initTweens() method like this: <!--TWEENJS-EXAMPLE-1--> <div id="txtBox1" class="csstrick" style="position:absolute; top:100px; left:10px; width:150px; height:20px; background:#a0dde9; padding:15px; border:3px solid #ccc; border-radius:8px; z-index:102; text-align:center;"> tweenjs&babylonjs </div> <script> //init tween by object handle var dynamicState = { x:50, w:150, h:20}, targetState = { x:400}, txtBoxDiv = document.getElementById('txtBox1'); //tween in object format. var txtboxTweenRight = new TWEEN.Tween(dynamicState).to(targetState, 2000 ); txtboxTweenRight.onUpdate(function(){ txtBoxDiv.style.left = dynamicState.x+'px';/*console.log('txtbox: '+this.x)*/}); //interpolation steps txtboxTweenRight.onComplete(function(){/*console.log('right: done')*/}) //end of tween callback. txtboxTweenRight.easing(TWEEN.Easing.Cubic.Out); txtboxTweenRight.delay( 44 ); //init tween with chaining... var txtboxTweenLeft = new TWEEN.Tween(dynamicState).to({x: 10}, 2000 ).easing(TWEEN.Easing.Cubic.Out).delay( 44 ) .onUpdate(function(){ txtBoxDiv.style.left = dynamicState.x+'px'}) .onComplete(function(){/*console.log('left: done')*/}) //end of tween callback. //animate in succession var txtBoxAnimation = function(){ txtboxTweenRight.chain(txtboxTweenLeft); // txtboxTweenLeft.chain(txtboxTweenRight); txtboxTweenRight.start(); } var txtboxtweenWidth = new TWEEN.Tween(dynamicState).to({w: 600}, 2000 ).easing(TWEEN.Easing.Cubic.Out).delay( 44 ) .onUpdate(function(){ txtBoxDiv.style.width = dynamicState.w+'px'}) .onComplete(function(){/*console.log('left: done')*/}) //end of tween callback. var txtboxtweenHeight = new TWEEN.Tween(dynamicState).to({h: 500}, 2000 ).easing(TWEEN.Easing.Cubic.Out).delay( 44 ) .onUpdate(function(){ txtBoxDiv.style.height = dynamicState.h+'px'}) .onComplete(function(){/*console.log('left: done')*/}) //end of tween callback. var txtBoxSizeAnimation = function(){ txtboxtweenWidth.chain(txtboxtweenHeight); txtboxtweenWidth.start(); } </script> <!--END-TWEENJS-EXAMPLE-1--> - That is all the code. You'll get a <div> that goes right then left. And if you un-comment a line, it will go right then left forever. With nice cubic-out interpolation curves and a hybrid-interface html-overlay via AnimationFrame. Next, tweening a complex component (star-bar). Quote Link to comment Share on other sites More sharing options...
hunts Posted May 1, 2017 Share Posted May 1, 2017 @Zimbofly do you mean something like this? https://www.babylonjs-playground.com/#2Q8VL4#6 JackFalcon 1 Quote Link to comment Share on other sites More sharing options...
JackFalcon Posted May 1, 2017 Share Posted May 1, 2017 Example 2. A StarBar: http://anymscape.com/BJSDEMOS/tweendemo4/ Description: It accordions in and out, incrementally highlighting stars in ':blue' and then when 10 are completed, increments totalcount and total star in ':yellow'. Which gives the UX to make you feel like a winner. Here is the code: <!--**********************STAR-BAR-TWEEN-EXAMPLE*****************************************--> <div id="starbar"> <div class='icotrophy'><i id="icotrophy" title="stars" class="fa fa-star" style='color:#444;'></i> </div> <div id="starCount">0</div> <span id="starDivider">|</span> <div class='icostar' id="icostarz1"><i title="stars" class="fa fa-star"></i></div> <div class='icostar' id="icostarz2"><i title="stars" class="fa fa-star"></i></div> <div class='icostar' id="icostarz3"><i title="stars" class="fa fa-star"></i></div> <div class='icostar' id="icostarz4"><i title="stars" class="fa fa-star"></i></div> <div class='icostar' id="icostarz5"><i title="stars" class="fa fa-star"></i></div> <div class='icostar' id="icostarz6"><i title="stars" class="fa fa-star"></i></div> <div class='icostar' id="icostarz7"><i title="stars" class="fa fa-star"></i></div> <div class='icostar' id="icostarz8"><i title="stars" class="fa fa-star"></i></div> <div class='icostar' id="icostarz9"><i title="stars" class="fa fa-star"></i></div> <div class='icostar' id="icostarz10"><i title="stars" class="fa fa-star"></i></div> </div> <style> #starbar{ height:20px; width:65px; top:5px; left:5px; position:fixed; padding:6px; border-radius: 20px; background-color: blue; border: 1px solid #666; overflow:hidden; display:inline-block; text-align:center; overflow:hidden; z-index:100; /*line-height: 1.4;*/ /*white-space: nowrap;*/ } .icostar, .icotrophy{ float:left; width:30px; } #starCount{ float:left; font-style:impact; } #starDivider{ float:left; margin-left:10px; /*text-shadow: 0 -1px 1px black;*/ } #icostarz1, #icostarz2, #icostarz3, #icostarz4, #icostarz5, #icostarz6, #icostarz7, #icostarz8, #icostarz9, #icostarz10{ /*display:none;*/ opacity:0; } </style> <script> /******************************TWEEN-STARBAR-EXAMPLE-CODE********************************************************/ var starBarExpand, starBarCollapse, starBarAnimation, starBarFull=false, starBarEmpty=false; //composite-memebers-design-pattern. // txtBoxAnimation; function tweenInit_Starbar() { var icostarz = document.getElementsByClassName('icostar'); var icotrophy = document.getElementById('icotrophy'); var countDiv = document.getElementById('starCount'); var starbar = document.getElementById('starbar'); var tweenState_Starbar = {width: 75 }; var starCount = 0, visCount = 0; starBarAnimation = function(){ starBarCollapse.chain(starBarExpand); starBarCollapse.start(); } starBarExpand = new TWEEN.Tween(tweenState_Starbar).to({width:360}, 2000).delay(44).easing(TWEEN.Easing.Cubic.Out) .onUpdate(function(){ starbar.style.width = tweenState_Starbar.width+'px'; //show stars at position. if(visCount<1&&parseInt(tweenState_Starbar.width)>=100){icostarz[0].style.opacity=1; icostarz[0].children[0].style.color='#000'; visCount++;} if(visCount<2&&parseInt(tweenState_Starbar.width)>=130){icostarz[1].style.opacity=1; icostarz[1].children[0].style.color='#000'; visCount++;} if(visCount<3&&parseInt(tweenState_Starbar.width)>=160){icostarz[2].style.opacity=1; icostarz[2].children[0].style.color='#000'; visCount++;} if(visCount<4&&parseInt(tweenState_Starbar.width)>=190){icostarz[3].style.opacity=1; icostarz[3].children[0].style.color='#000'; visCount++;} if(visCount<5&&parseInt(tweenState_Starbar.width)>=220){icostarz[4].style.opacity=1; icostarz[4].children[0].style.color='#000'; visCount++;} if(visCount<6&&parseInt(tweenState_Starbar.width)>=250){icostarz[5].style.opacity=1; icostarz[5].children[0].style.color='#000'; visCount++;} if(visCount<7&&parseInt(tweenState_Starbar.width)>=280){icostarz[6].style.opacity=1; icostarz[6].children[0].style.color='#000'; visCount++;} if(visCount<8&&parseInt(tweenState_Starbar.width)>=310){icostarz[7].style.opacity=1; icostarz[7].children[0].style.color='#000'; visCount++;} if(visCount<9&&parseInt(tweenState_Starbar.width)>=340){icostarz[8].style.opacity=1; icostarz[8].children[0].style.color='#000'; visCount++;} if(visCount<10&&parseInt(tweenState_Starbar.width)>=355){icostarz[9].style.opacity=1; icostarz[9].children[0].style.color='#000'; visCount++;} }) .onComplete(function(){ icotrophy.style.color = '#8facd5'; //lightblue starBarFull=true; }); starBarCollapse = new TWEEN.Tween(tweenState_Starbar).to({width: 75 }, 2000).easing(TWEEN.Easing.Cubic.Out).delay( 44 ) .onUpdate(function(){ starbar.style.width = tweenState_Starbar.width+'px'; //hide stars at position if(visCount===1&&parseInt(tweenState_Starbar.width)<=100){icostarz[0].style.opacity=0; visCount--;} if(visCount===2&&parseInt(tweenState_Starbar.width)<=130){icostarz[1].style.opacity=0; visCount--;} if(visCount===3&&parseInt(tweenState_Starbar.width)<=160){icostarz[2].style.opacity=0; visCount--;} if(visCount===4&&parseInt(tweenState_Starbar.width)<=190){icostarz[3].style.opacity=0; visCount--;} if(visCount===5&&parseInt(tweenState_Starbar.width)<=220){icostarz[4].style.opacity=0; visCount--;} if(visCount===6&&parseInt(tweenState_Starbar.width)<=250){icostarz[5].style.opacity=0; visCount--;} if(visCount===7&&parseInt(tweenState_Starbar.width)<=280){icostarz[6].style.opacity=0; visCount--;} if(visCount===8&&parseInt(tweenState_Starbar.width)<=310){icostarz[7].style.opacity=0; visCount--;} if(visCount===9&&parseInt(tweenState_Starbar.width)<=340){icostarz[8].style.opacity=0; visCount--;} if(visCount===10&&parseInt(tweenState_Starbar.width)<=370){icostarz[9].style.opacity=0; visCount--;} }) .onComplete(function() { countDiv.innerHTML = ++starCount; //increment txt number. icotrophy.style.color = 'yellow'; //goldstar for reading this far starBarEmpty=true; }); //chaining example, enstead fit into gameplay via requestAnimationFrame. // starBarExpand.chain(starBarCollapse); // starBarCollapse.chain(starBarExpand); starBarExpand.start(); } tweenInit_Starbar(); /*******************************-END-EXAMPLE-2-*******************************/ //updated master loop.... /*****************************MASTER-TWEENJS-LOOP****************************\ - Loop for all TWEENJS interpolation updates. Without this call no TWEENS run.hybrid. \****************************************************************************/ requestAnimationFrame(TWEEN_LOOP); function TWEEN_LOOP(time) { TWEEN.update(time); //trigger all tween interpolation updates. //(optional)flag runtime animations within TWEEN_LOOP if(starBarFull){ starBarFull=false; starBarCollapse.start(); }else if(starBarEmpty){ starBarEmpty=false; starBarExpand.start(); } requestAnimationFrame(TWEEN_LOOP); //recursion, TWEEN_LOOP. } /**************************-END-TWEEN_LOOP-*********************************/ - Results, this starbar is ok. It has some needs (fontawesome icon wrapping - not hiding always, and needs dynamic width count ). <link rel="stylesheet" href="../lib/font-awesome/font-awesome-4.7.0/css/font-awesome.min.css"> Why use with Babylon? Because adds a hybrid-2D-ui-overlay-interface? I agree it may even give you double-loops - which - I hope experts chime in. It seems to me this is mixing cpu loops and gpu loops... on deeper research, seems AnimationFrame can hit GPU depending on context, so, performance hit undetermined. Or maybe it is good to keep lower importance stuff like 2d ui layer interpolation out of gpu optimized code. Curious... Anyway, that is 2 cents on tween.js used as an overlay to babylon canvas. Next, it is possible to combine the loops. Quote Link to comment Share on other sites More sharing options...
JackFalcon Posted May 1, 2017 Share Posted May 1, 2017 Example 3: A Big Sphere Eats a Little Sphere - or you just imagined that: http://anymscape.com/BJSDEMOS/tweendemo4/ This is only a TEST: /*****************************MASTER-TWEENJS-LOOP-IN-BJS****************************\ - Loop for all TWEENJS interpolation updates. Without this call no TWEENS run. - use this loop to signal calculation updates from BJS to Tween.js. Idk. Risky?!! \****************************************************************************/ scene.registerBeforeRender(function() { //tweenjs integration with babylonjs. vcool. this runs all TWEEN interpolations. TWEEN.update( window.performance.now() ); }); /**************************-END-TWEEN_LOOP-*********************************/ Here is the tween of circles that intersect (similar to a tween.js example, but in 3D, because it is operating on BabylonJS components. /*********************-TWEEN-EXAMPLE-3-*************************/ /*---------------Mixing-TWEENJS && BabylonJS-------------------*/ var targetOrb, targetOrbState, targetTween; //Member-composite-pattern. var trackingOrb, trackingOrbState, trackingTween; //Member-composite-pattern. var initOrbTween = function(){ targetOrb = new BABYLON.Mesh.CreateSphere("sphere", 14, 1, scene); targetOrb.position= new BABYLON.Vector3(0,10,40); targetOrbState = { x:targetOrb.position.x, y: targetOrb.position.y, z:targetOrb.position.z }; targetTween = new TWEEN.Tween( targetOrbState ).to( { x: 10, y: 20, z:-70 }, 4000 ).onUpdate( function() { targetOrb.position.x=this.x; targetOrb.position.z=this.z; }).onComplete(function() { }); // } ).start(); trackingOrb = new BABYLON.Mesh.CreateSphere("sphere", 14, 2, scene); trackingOrb.position= new BABYLON.Vector3(-20,10,10); trackingOrbState = { x:trackingOrb.position.x, y: trackingOrb.position.y, z:trackingOrb.position.z }; // new TWEEN.Tween( trackingOrbState ).to( { x: -10, y: 20, z:10 }, 3000 ).onUpdate( function() { trackingTween = new TWEEN.Tween( trackingOrbState ).to(targetOrbState, 4000 ).onUpdate( function() { trackingOrb.position.x=this.x; trackingOrb.position.z=this.z; }).onComplete(function() { // forwardBackward = !forwardBackward; //toggle to go forward. }); }; babylonSphereAnimation = function(){ initOrbTween(); targetTween.start(); trackingTween.start(); } /*****************************MASTER-TWEENJS-LOOP-IN-BJS****************************\ - Loop for all TWEENJS interpolation updates. Without this call no TWEENS run. - use this loop if you want to signal calculation updates from BJS to \****************************************************************************/ scene.registerBeforeRender(function() { //tweenjs integration with babylonjs. vcool. this runs all TWEEN interpolations. TWEEN.update( window.performance.now() ); }); /**************************-END-TWEEN_LOOP-*********************************/ /*********************-END-TWEEN-EXAMPLE-3-*************************/ return scene; } One more thing, button handlers in a testing apparatus, for animation method onclick testing: document.getElementById('btn1').onclick = function(e){ starBarAnimation(); }; document.getElementById('btn2').onclick = function(e){ txtBoxAnimation(); }; var babylonSphereAnimation; document.getElementById('btn3').onclick = function(e){ babylonSphereAnimation(); }; document.getElementById('btn4').onclick = function(e){ txtBoxSizeAnimation(); }; document.getElementById('btn5').onclick = function(e){ txtBoxAnimation(); }; document.getElementById('btn6').onclick = function(e){ txtBoxAnimation(); }; All in all - 2D overlay animations, not so bad. Free is cheaper than Greensock. And mixing TweenLoop with 3D beforeRender is possible, but needs performance review. The ending code is confusing to understand the tween-clumps. But stepping through the three steps really helps to comprehend the strange tween syntax. Ok, hope this is useful, bye. : ) Wingnut 1 Quote Link to comment Share on other sites More sharing options...
GameMonetize Posted May 1, 2017 Share Posted May 1, 2017 This is really cool and helpful. Thank you for having taking time to share it JackFalcon 1 Quote Link to comment Share on other sites More sharing options...
JackFalcon Posted May 1, 2017 Share Posted May 1, 2017 Thanks DK, I'll githubit.... and thank you for making it possible. GameMonetize 1 Quote Link to comment Share on other sites More sharing options...
JackFalcon Posted May 1, 2017 Share Posted May 1, 2017 Thanks @hunts, I see how that link injects GreenSock into Babylon Playground: var s = document.createElement('script') s.src = "https://cdnjs.cloudflare.com/ajax/libs/gsap/1.8.4/TweenMax.min.js" document.body.appendChild(s) vcool... Quote Link to comment Share on other sites More sharing options...
adam Posted May 1, 2017 Share Posted May 1, 2017 On 7/23/2014 at 3:40 PM, Temechon said: I do agree with Zimbofly, predefined tweens would be great. Like this one, but in 3D You can use TweenMax: https://www.babylonjs-playground.com/#5UZNC#3 https://www.babylonjs-playground.com/#5UZNC#2 Quote Link to comment Share on other sites More sharing options...
JackFalcon Posted May 7, 2017 Share Posted May 7, 2017 As far as I understand, license for Tween.js is free (gpl i think) and greensock tweenmax, I think, is $99 a year to use commercially. Quote Link to comment Share on other sites More sharing options...
Recommended Posts
Join the conversation
You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.