-
-
Notifications
You must be signed in to change notification settings - Fork 35.5k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
feature request: transform origin (or "pivot point") #15965
Comments
Can you please provide a simple fiddle demonstrating your use case? Also, please explain in the context of your demo why the existing three.js capabilities are not adequate. |
TBH, I always thought that the existing approaches in |
I think it might be worth to consider this issue as a valid feature request. |
I agree with @Mugen87 here. I spent way to long using these hacks to get pivot points from the FBX format working, and I still think that there are edge cases that are not covered since the format has the concept of geometric pivot (i.e. transformed geometry relative to the mesh) and also object level pivot points (what @trusktr means here). Both currently are shoe-horned into the geometric pivot, but it would have been a lot easier and less error prone if threejs had native pivot points. Since most other 3D apps seem to have this concept, the only reason I can think of for NOT adding them is if there are major caveats for doing so, such as reduced performance. |
There are some ramifications here. The new matrix will have to be recursively updated and
Any non-DCC examples? I know all modeling tools have this, but they have a lot of concepts that aren't reasonable to include in a realtime rendering library. I think Unity's editor allows you to set pivot points, but they're baked when you build the project and a pivot point cannot be changed at runtime without using parent nodes. From the authors of the Godot Engine:
|
Perhaps the new matrix can be calculated only if pivot point is specified, as it is optional. |
Yes, this seems like the obvious next step. If this can only be achieved by reduced performance, then it's a non-starter and we'll have to continue with the hacks. In Babylon.js it looks like the pivot is a simple pre-transform matrix. If we implement it in a similar way, such that the pivot matrix is undefined by default, then On the other hand, Babylon.js is the only non-DCC tool I can find that implements pivot points in real time (with 5 minutes of research, anyway). This would be useful for the FBX loader, and I can imagine other situations such as manually building objects with hinges where since this would be useful. But on the other hand, we've got this far using just the hacks and I don't personally have a strong need for this. @truskr if you want to champion this idea, could you do some more research and see whether other tools beside Babylon offer real time pivots? Also, if you can identify some use cases and see if other people besides you are requesting this feature then that would help strengthen the case.
My preference would be to call this |
@looeee Please stop referring to the existing code as hacks. |
I would like the OP to answer my questions above before considering adding such a feature. Note, a user can do the following at the application level. I would not expect it to have a measurable performance impact. THREE.Object3D.prototype.updateMatrix = function () {
this.matrix.compose( this.position, this.quaternion, this.scale );
if ( this.pivot && this.pivot.isVector3 ) {
var px = this.pivot.x;
var py = this.pivot.y;
var pz = this.pivot.z;
var te = this.matrix.elements;
te[ 12 ] += px - te[ 0 ] * px - te[ 4 ] * py - te[ 8 ] * pz;
te[ 13 ] += py - te[ 1 ] * px - te[ 5 ] * py - te[ 9 ] * pz;
te[ 14 ] += pz - te[ 2 ] * px - te[ 6 ] * py - te[ 10 ] * pz;
}
this.matrixWorldNeedsUpdate = true;
}; and then define the object pivot only when needed: mesh.pivot = new THREE.Vector3( 5, 5, 5 ); With this approach, children of objects having a defined pivot are still located relative to the object's origin. |
Basic example: Using origin/pivot to define the hinge of a door in a game. Here's a fiddle, using CSS transform-origin, but you get the idea. |
Instead of asking the user to monkey-patch library code, I would prefer to include |
This comment has been minimized.
This comment has been minimized.
I think these are fair points. We should measure what's the performance impact of modifying THREE.Object3D.prototype.updateMatrix = function () {
this.matrix.compose( this.position, this.quaternion, this.scale );
var pivot = this.pivot;
if ( pivot !== null ) {
var px = pivot.x, py = pivot.y, pz = pivot.z;
var te = this.matrix.elements;
te[ 12 ] += px - te[ 0 ] * px - te[ 4 ] * py - te[ 8 ] * pz;
te[ 13 ] += py - te[ 1 ] * px - te[ 5 ] * py - te[ 9 ] * pz;
te[ 14 ] += pz - te[ 2 ] * px - te[ 6 ] * py - te[ 10 ] * pz;
}
this.matrixWorldNeedsUpdate = true;
}; |
Perhaps we can do this at the start of the next release cycle? That way we'll have a month to test it, and we can roll it back if it causes performance degradation |
If it goes into the lib, is it better in Object3D than in Matrix4 and Matrix3 (for 2D)? |
@trusktr Did you try the patch I provided for you? Is it implementing the feature you requested? |
@WestLangley Seems like it does. Here's a fiddle rotating/scaling a cube (and its child) around its corner. |
@trusktr Do you want to prepare a PR with the code from #15965 (comment)? |
@Mugen87 You should be asking me that question. |
@looeee Can you please try this patch in the |
@Mugen87 Have you been able to try this? I am finding it very unintuitive when the pivot is changed... |
@WestLangley Sorry about that. I was not aware you want to do this 😅
I'm actually waiting on a PR so I can checkout the respective branch and test it. I know the feature from Babylon.js and I'd like to compare both behaviors. |
If the feature is supported, I will file the PR. I do not support the feature yet, because we haven't decided what the behavior should be. |
This demo requires changing the pivot in real-time, and unfortunately, doing so is not intuitive at all. (One filp is easy; change the pivot and the object jumps to a different location.) A better API may be a method that rotates an object around an axis apart from the object -- such as the method I proposed in this SO answer. |
Here's a fiddle of that rotating plane, using the above I wanted to verify that it works with arbitrary quaternion applied too: this fiddle shows rotating around the front diagonal of a cube as expected. 👍 This shows that with a pivot, and using And this fiddle shows I like the idea of an option to rotate around an axis, but in the SO answer it doesn't work with a transformed parent. Having to figure out a world axis in order to rotate an object may not be convenient. In the door example, it's simple to specify pivot local to the door, as opposed to calculating a world axis (and making it work with rotated parents), and it makes encapsulation easy: the local component doesn't need to worry about the outside world for the animation to work. |
Yeah, that sounds good! I'm still hoping to see support for pivot points in |
+1 |
Description of the problem
As an example, Babylon has this feature built in, called pivot points. CSS has it in the form of the
transform-origin
property.These features enable rotation about a pivot point with a one-liner.
Here's an implementation idea: https://jsfiddle.net/mmalex/hd8ex0ok/ (thanks @nmalex).
I believe ideally this would be implemented inside
Matrix4
, and theMatrix4.compose( position, quaternion, scale )
signature would be changed toMatrix4.compose( position, quaternion, scale[, origin] )
, with theorigin
parameter being optional for backwards compatibility.An
origin
property would be added toObject3D
, so that we can for example writeobject.origin.set(1,2,3)
.updateMatrixWorld
would then callthis.matrix.compose( this.position, this.quaternion, this.scale, this.origin )
.Just bike shedding, but
pivot
could also be another name in place oforigin
, but I likeorigin
better because "pivot" doesn't seem to align with "scale" (I'm thinking thatscale
would also happen about theorigin
).Three.js version
Browser
OS
Hardware Requirements (graphics card, VR Device, ...)
N/A
The text was updated successfully, but these errors were encountered: