Pivot point and scaling: what's happening here?

Please view this playground: https://playground.babylonjs.com/#BZ134Y#3.

Originally, I wanted to make this object (box) rotatable around its center. However, I’ve encountered massive problems with scaling after setting the pivot point, which are reproduced in the PG link above. Commenting line 41 out (node.setPivotPoint(centerPoint)) will make the scene look as intended, but with that line, the box moves on the Y-axis while scaling. The documentation I’ve read on this topic is very extensive, but also very confusing and overwhelming.

Please note: I could of course move the origin in the GLTF to the center, however the GLTF I’m using is more or less an example. Real productive GLTFs will most probably come from users with different backgrounds, so I’m trying to accommodate arbitrary origins.

What am I doing wrong here and how do I do this correctly?

Hey!

can you try to make sure you are in world space with
node.setPivotPoint(centerPoint, BABYLON.Space.WORLD);

It changes something. Still does not look logical, I’m afraid:

Oh, and by the way: is there a reason boundingInfo.boundingBox.centerWorld does not return world space coordinates?

nope it should return world coordinates. This is not what you are seeing?

Nope. Compare two code snippets, which I consider to be equivalent, semantics-wise:

        const centerPoint = boundingInfo.boundingBox.centerWorld;
        node.setPivotPoint(centerPoint);

        const centerPoint = boundingInfo.boundingBox.center;
        node.setPivotPoint(centerPoint, BABYLON.Space.WORLD);

So help me understand what you need then :slight_smile: What is your goal? If the scene works without the node.setPivotPoint, why do you need it?

I want to rotate models with the mouse :slight_smile: However, I want to rotate them in place around their center point, but they are not guaranteed to have their origins in their center (more probable at the bottom). That’s why I need to set the pivot point, which even works properly apart from the movement on the Y-axis you can see in the PG.

I hope that cleared up my intention. Thanks!

So ultimately you expect your mesh to be centered on 0,0,0 right? like half below and half above the ground?

Actually, that’s an interesting question :slight_smile: In the context of this PG you are probably right, I’m expecting the pivot point to be in the center of the model, which combined with the zero-position should put the box right through the ground. This is different in my actual project (the box would be standing on the ground), so I actually had to ponder a bit.

What I’m not understanding for now:

  • even with the world space coordinates, the box is not halved by the ground, but instead is positioned a good part above the ground
  • how and why to calculate center points in either local or world space
  • why setting a pivot point makes scaling move the object on the axis instead of just scaling it in place (around the said pivot point)

The most important point is probably the last one, since rotating around the pivot actually works for the most part, but the model is repositioned, somehow based on scaling, so I’m confused quite a bit.

(I might extend the PG with the actual rotation part, but that’ll have to wait until tomorrow)

Ok I understand. In your case you have your vertices stored in a complete off centered way
So I recommend not using pivot but moving the vertices

Something like that:
https://playground.babylonjs.com/#BZ134Y#4

Thanks, that sounds really interesting! Could you elaborate on the “vertices stored in off-centered way”? For the moment, I have no clue what that means (apart from it’s being bad news), but would like to grasp the details, since that might become really important when third parties start to create models for us.

Your vertices (stored in your file) are not centered on origin. You could fix it in your DCC tool (like Blender or maya) but as you mentioned you will not control the assets in the future so the best idea is to move the vertices inside the mesh to be centered (which is what I did)

Thanks! Would you bear with me for just a little longer?

Do I understand this correctly: it’s possible to fix the problem in the model file with Blender without moving the origin to e.g. center of the geometry? If so, can you give me a pointer to how this is done?

Does this also mean that pivoting is dependent on the mesh and cannot be implemented generally for all meshes? Or are these just edge cases that are not covered just yet but are possible in theory?

Yup you could in Blender choose where the pivot is for a particular mesh. @PirateJC is way more versed than me in blender and can help with this task.

Yes pivoting totally depends on the geometry and nothing forces the pivot to be in the center of the bounding boxes by default, you should actually chose what works best for each cases. lets say you want to place smthg on the ground, having the pivot at the bottom would be handy, now, reversly attaching to the ceiling might be simplified by having at the top.

From what I’ve understood so far, I’m using two origins:

  1. the origin in the GLTF, which I’m using for positioning (mostly at the center (0,0,0)) and for scaling.
  2. the center of the model which I’d like to use for rotation.

Do I have a chance to juggle these origins safely?

I sometimes add an extra transform for this basically all at the mesh center and when I load I parent it to an extra node to have the mental model easier. I know some people would prefer the pivot way but extra transform works great for me :slight_smile:

So the best possible way I can think of to do this would be as @Deltakosh and @sebavan have suggested.

In Blender take your asset and make sure that your geometry is positioned according to how you’d like it in the final scene relative to your pivot point. There are a TON of different methods on how to do this, but here’s a quick one:

Start with a plane to represent your ground with a position of (0,0,0) and then add your mesh to the scene…for this example I’ll use a cube as our “mesh”.

Note that the pivot point of the cube is perfectly in the center of the geometry.

Ok now let’s move the pivot point to be at the bottom of the cube…we can do this by entering edit mode by hitting ‘tab’ on the keyboard. Also enter wireframe mode in Blender by hitting Shift+z.

How select the all 4 of the bottom vertices:

Now hit Shift + S and select “Cursor to Selected.” This will move the 3D cursor to the center of the selected vertices.

Now go back to object mode by hitting ‘tab’ again. Under the ‘Object’ Menu find ‘Set Origin’ and ‘Origin to 3D Cursor.’ This will move the pivot point to the location of the 3D cursor which is at the bottom of our cube mesh.

image

When you do this, note that Blender automatically adds in an offset for the mesh’s position so that the mesh has now basically “moved” without you realizing it. I know that’s a tricky concept, but because your pivot point (or origin as Blender calls it) has moved, essentially the entire model has moved…then Blender “moves” all of the vertices of the geometry back to where they were before…essentially moving the entire mesh to line up with your new pivot point.

image

So if you zero out the Z value the cube will now pop up to be even with the ground plane.

Now when you export that model it will have a position of (0,0,0), with a pivot point even with the ground plane.

Then in Babylon all you need to do is map the mouse movement to the Y rotation of the mesh and I think that should accomplish everything you need?

I hope this helps!

Hey guys, thank you very much for all of your input! I had to apply Pareto principle to implement something that works for me for now, which is probably not something you could apply generally, but then again, neither is a pivot point :slight_smile:.

Since I’ve moved the origin point to the bottom of the mesh, I needed to adjust for the position on the Y-axis, especially when scaling. So my hack goes something like this:

  • After loading a mesh and before applying scaling, set the pivot point to the center point of the mesh (calculated via bounding box).
  • Next, apply the scaling.
  • After scaling, move the Y position to (1 - mesh.scaling.y) / 2 and save this position to the metadata. This position is used to reposition the object when its rotation is reset (which is a feature we use).

I realize this is a hack and will probably break soon (as always), but it will hopefully buy me some time to find a more general solution before our users actually start to produce their own models.