Numa Posted November 11, 2016 Share Posted November 11, 2016 Hi there, I'm trying to rotate a mesh around a specific point. I use the setPivotMatrix + translate back and it works great, as long as the mesh isn't already scaled or rotated. If it is, the mesh jumps to a wrong position before it starts rotating. I took care of the scale but can't figure out how to handle the rotation. Here's what I have: var position = new BABYLON.Vector3(10, 10, 10); // Mesh position relative to pivot point var relativePosition = mesh.position.subtract(position); // Set pivot matrix mesh.setPivotMatrix(BABYLON.Matrix.Translation(relativePosition.x * (1 / mesh.scaling.x), relativePosition.y * (1 / mesh.scaling.y), relativePosition.z * (1 / mesh.scaling.z))); // Translate back mesh.position = mesh.position.add(new BABYLON.Vector3(-relativePosition.x, -relativePosition.y, -relativePosition.z)); Thanks guys Quote Link to comment Share on other sites More sharing options...
JohnK Posted November 11, 2016 Share Posted November 11, 2016 Am working on the same problem (well the rotation one) as is @DigiHz Data have an idea why and where it goes wrong but will take a few days to confirm (or not) that I can produce a solution. If I get rotation solved, scaling will probably follow. DigiHz Data and Numa 2 Quote Link to comment Share on other sites More sharing options...
DigiHz Data Posted November 13, 2016 Share Posted November 13, 2016 Look at my updated PG about a possible solution. http://www.babylonjs-playground.com/#M0UJB Quote Link to comment Share on other sites More sharing options...
Numa Posted November 13, 2016 Author Share Posted November 13, 2016 Looking good! Why do we need pick a specific axis? let's say I want my pivot to be (3, 4, 5) instead of 0, 0, 0, could I just pass the (0, 0, 0).subtract(3, 4, 5) vector instead? Would that work? Quote Link to comment Share on other sites More sharing options...
DigiHz Data Posted November 13, 2016 Share Posted November 13, 2016 I can not tell you about that, sorry, you can figure it out from the code in the PG i think. Quote Link to comment Share on other sites More sharing options...
JohnK Posted November 15, 2016 Share Posted November 15, 2016 @Numa and @DigiHz Data after days playing around with setPivotMatrix I suddenly felt very foolish as I realised the approach was wrong and I had in fact produced the basis of a solution back in May 2015 in the post below (back in the days when I was new to BJS and was misinterpreting many things and was working on an un-necessary solution to something dealt with much easier - so nothing changes does it) However as wrong headed as that solution was it was the solution to the pivot problem. Here are two methods one for rotating around a pivot and one for scaling from a pivot both of which allow you to move the pivot and the mesh using just .position. If you would both like to test them out and see if they fail anywhere this would be very useful. (After all I though I had found a solution previously and it failed). Of course anyone else is welcome to test them out as well. The Rotation Method rotateAroundPivot takes three parameters - the position of the pivot (Vector3), an axis (Vector3) to rotate around and the angle (number as radians) to rotate. Rotations are accumulative. BABYLON.Mesh.prototype.rotateAroundPivot = function(pivotPoint, axis, angle) { if(!this._rq) { this._rq = BABYLON.Quaternion.Identity(); } var _p = new BABYLON.Quaternion(this.position.x - pivotPoint.x, this.position.y - pivotPoint.y, this.position.z - pivotPoint.z, 0); axis.normalize(); var _q = BABYLON.Quaternion.RotationAxis(axis,angle); //form quaternion rotation var _qinv = BABYLON.Quaternion.Inverse(_q); var _pdash = _q.multiply(_p).multiply(_qinv); this.position = new BABYLON.Vector3(pivotPoint.x + _pdash.x, pivotPoint.y + _pdash.y, pivotPoint.z + _pdash.z); this.rotationQuaternion = this._rq.multiply(_q); this._rq = this.rotationQuaternion; } Scaling Method scaleFromPivot takes four parameters the position of the pivot (Vector3) and the scale for x, y, z axes as numbers. The numbers used set the current scale of the mesh based on its original size with the pivot as centre of enlargement. BABYLON.Mesh.prototype.scaleFromPivot = function(pivotPoint, sx, sy, sz) { var _sx = sx / this.scaling.x; var _sy = sy / this.scaling.y; var _sz = sz / this.scaling.z; this.scaling = new BABYLON.Vector3(sx, sy, sz); this.position = new BABYLON.Vector3(pivotPoint.x + _sx * (this.position.x - pivotPoint.x), pivotPoint.y + _sy * (this.position.y - pivotPoint.y), pivotPoint.z + _sz * (this.position.z - pivotPoint.z)); } Here is a playground to try it out http://www.babylonjs-playground.com/#1MKHR9 Numa 1 Quote Link to comment Share on other sites More sharing options...
Numa Posted November 17, 2016 Author Share Posted November 17, 2016 Thanks @JohnK !! That worked for me. I had to change that first line though: this._rq = BABYLON.Quaternion.Identity(); with this._rq = this.rotationQuaternion; otherwise if the object was already rotated it would mess things up. Thank you so much! Quote Link to comment Share on other sites More sharing options...
JohnK Posted November 17, 2016 Share Posted November 17, 2016 @Numa thank you for pointing this out. I had assumed that my methods would be applied from the start and all rotations would take place using them. In practice your correction would only work if previous rotations had been done using mesh.rotate. If a rotation was set just using mesh.rotation then this.rotationQuaternion would be undefined. Hopefully between us we now have it working correctly in all cases using the modified code below. BABYLON.Mesh.prototype.rotateAroundPivot = function(pivotPoint, axis, angle) { if(!this._rotationQuaternion) { this._rq = BABYLON.Quaternion.RotationYawPitchRoll(this.rotation.y, this.rotation.x, this.rotation.z); } var _p = new BABYLON.Quaternion(this.position.x - pivotPoint.x, this.position.y - pivotPoint.y, this.position.z - pivotPoint.z, 0); axis.normalize(); var _q = BABYLON.Quaternion.RotationAxis(axis,angle); //form quaternion rotation var _qinv = BABYLON.Quaternion.Inverse(_q); var _pdash = _q.multiply(_p).multiply(_qinv); this.position = new BABYLON.Vector3(pivotPoint.x + _pdash.x, pivotPoint.y + _pdash.y, pivotPoint.z + _pdash.z); this.rotationQuaternion = this._rq.multiply(_q); this._rq = this.rotationQuaternion; } New PG http://www.babylonjs-playground.com/#1MKHR9#1 Please feel free to test again and once more thank you for the feedback. Quote Link to comment Share on other sites More sharing options...
jmb462 Posted September 2, 2018 Share Posted September 2, 2018 Hi here, I'm planning to make a rubik's cube with babylon. I'm new to babylon and javascript. I'm using your function to rotate the face around the cube axis. Here is my playground : http://www.babylonjs-playground.com/#1MKHR9#62 The "u" key rotate the upper face. The "r" key rotate the right face. As long as I rotate only the upper face or only the right face, everything is ok. But, if you press "u" once, then "r" once, some pieces rotate both around the world axis (as i wish) AND around the piece axis. I really don't understand why because I only use your function RotateAroundPivot once . Do someone have an idea why ? Thanks. JMB 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.