Is it possible to tween decompose instead of having to tween 3x vector3 for Pos, Rot, Scale? Or if not a way to tween between decompose is there a way to tween Pos, Rot, Scale at the same time? Ive tried but no success. Im running three tweens currently for the job. 1 per vector.
Are you using tween.js? Not clear what youāre asking.
Do you mean is it possible to tween a matrix? If so, then yes. You can tween the values in the matrix.elements array.
Thanks for the reply @looeee and @trusktr . I currently have an instancedMesh of elements that I tween. I tween their pos, rot, scale. But I do it with three different tweens. I would like to tween all three Vectors with one tween.
Something like:
new Tween( object.position, obj.rotation, obj.scale ).to( target.object.position, target.object.rotation, target.obj.scale )
Inside my tween I then convert the positions to a matrix and compose them and use the new composed matrix to update the matrix of the instances. So I know its obv possible to tween the matrices. I just want all three vectors in one tween.
@D13
Use .onUpdate()
and lerp values for position, rotation and scale all at once there: Edit fiddle - JSFiddle - Code Playground
@prisoner849 Boom! Thank you!
So, qq: I implemented this and indeed it works like a champ. A big tween performance enhancement. However, with this approach its similar to slerp. We turn 0 into 1 over series of steps. However, I need to preserve the current position of existing objects āpanelCurrent.positionā. It seems this solution starts at āval:0ā every time. Is there a way it could start at the current objects position?
So the big diff here is going from a starting vector assumed at ācurrent.object.positionā vs a starting vector assumed from ā0ā.
var obLen = targets.radial.length;
for( let i = 0; i < obLen; i++ ) {
const panelCurrent = meshCache[ i ];
const panelTarget = targets.radial[ i ];
const panelMatrix = panelTarget.matrix;
const orientation = panelCurrent.quaternion();
const offset = new THREE.Vector3();
const newRot = new THREE.Euler();
let valsCount = { val: 0 }
let vals = {
pos: new THREE.Vector3(),
rot: new THREE.Vector3(),
sca: new THREE.Vector3()
}
new TWEEN.Tween( valsCount ).to({ val: 1 }, Math.random() * duration * 2 ).onUpdate( function(){
vals.pos.lerpVectors( panelCurrent.position, panelTarget.position, valsCount.val );
vals.rot.lerpVectors( panelCurrent.rotation, panelTarget.rotation, valsCount.val );
vals.sca.lerpVectors( panelCurrent.scale, panelCurrent.scale, valsCount.val );
newRot.set( vals.rot.x, vals.rot.y, vals.rot.z );
offset.set( vals.pos.x, vals.pos.y, vals.pos.z ).multiplyScalar( 0.075 );
orientation.setFromEuler( newRot );
panelMatrix.compose( offset, orientation, vals.sca );
currentMesh.setMatrix( i, panelMatrix );
currentMesh.instanceMatrix.needsUpdate = true;
}).start();
}
What I miss? I need my positions to start from āpanelCurrent.positionā. Thank you!
@D13
Use .onComplete()
and save current values into initVals
Edit fiddle - JSFiddle - Code Playground
PS Reading āUserās guideā time to time is helpful tween.js/user_guide.md at 8db070d25a82c19772352bbcbc33a326e6882b4e Ā· tweenjs/tween.js Ā· GitHub
Thank You!
@D13 Youāre welcome
@D13 Besides lerping like @prisoner849 suggested, you can also animate any number if properties of an object. The following is closer to what you were thinking:
new Tween({
position: object.position,
rotation: obj.rotation,
scale: obj.scale
}).to({
position: target.object.position,
rotation: target.object.rotation,
scale: target.obj.scale
})
then in onUpdate
you can read the values and use them on each update:
onUpdate(theValues => {
console.log(theValues.position, theValues.rotation, theValues.scale)
})
where theValues
is the same object you passed to new Tween
, which gets modified on each update.
Iāve seen that, that you can change nested objects, but seems I did something wrong so it didināt work
Ah! Made it working with nested objects: Edit fiddle - JSFiddle - Code Playground
Just had to care about box.rotation.order
as itās not a number, but a string, and it becomes NaN
whilst tweening.
Very Nice, yes, I was able to use the onComplete solution just fine. I think as far as performance goes this is the best without going to a TWEEN Manager, which could be tuned to squeeze the last inth of performance when getting into those 10k+ instances. For now, Iām happy with performance as it is. When I get into the big data Iāll revisit this.
Solution for now:
new TWEEN.Tween({ val:0 }).to({ val: 1 }, Math.random() * duration * 2 )
.easing( TWEEN.Easing.Exponential.InOut )
.onUpdate( value => {
// lerp new positions
vals.pos.lerpVectors( panelCurrent.position, targets.radial[ i ].position, value.val );
vals.rot.lerpVectors( panelCurrent.rotation, targets.radial[ i ].rotation, value.val );
vals.sca.lerpVectors( panelCurrent.scale, targets.radial[ i ].scale, value.val );
// compose new matrix
newRot.set( vals.rot.x, vals.rot.y, vals.rot.z );
offset.set( vals.pos.x, vals.pos.y, vals.pos.z );
offset.multiplyScalar( 0.025 );
orientation.setFromEuler( newRot );
panelMatrix.compose( offset, orientation, vals.sca );
// update positions
currentMesh.setMatrixAt( i, panelMatrix );
// apply updates
currentMesh.instanceMatrix.needsUpdate = true;
}).onComplete(() => {
// reset positions
panelCurrent.position.set( vals.pos.x, vals.pos.y, vals.pos.z );
panelCurrent.rotation.set( vals.rot.x, vals.rot.y, vals.rot.z );
panelCurrent.scale.set( vals.sca.x, vals.sca.y, vals.sca.z );
offset.set( panelCurrent.position.x, panelCurrent.position.y, panelCurrent.position.z );
offset.multiplyScalar( 0.025 );
newRot.set( panelCurrent.rotation.x, panelCurrent.rotation.y, panelCurrent.rotation.z );
orientation.setFromEuler( newRot );
panelMatrix.compose( offset, orientation, panelCurrent.scale );
}).start();
Of course, there is the caveat that the āonCompleteā has to finish its animation cycle to save the new position values. So, if a user clicks a new transition before the current one is finished then you get a snapping effect as the new positions are not saved and instead pull from the previous positions in the matrix. I can handle that thoughā¦
For now, this was plenty good enough. A million thanks!
Oh I see. Ok, yes, this is nice too. Not having to use onComplete to save the new positions. I was going to play with a version of this soon.