Scale in local coordinates?
-
- Gnoblar
- Posts: 4
- Joined: Wed Jul 23, 2008 2:48 pm
Scale in local coordinates?
Hi,
I have a Mesh that I load into an Entity, which lives in a SceneNode. This SceneNode has a SceneNode parent, which in turn has another SceneNodeParent (i.e. SceneNode --> SceneNode --> SceneNode --> Entity --> Mesh).
Now, I do several transformations in the SceneNodes, and for rotation and translation everything works fine. But when I try to scale my object non-uniformly (in the x-direction), it always seems to scale relative to the Mesh's original orientation, not relative to the orientation of the SceneNode.
After searching the forum, I found one person saying that SceneNode::scale() is always "global" (which is what I am seeing). But to me it would be more practical (and in my opinion logical) to scale my object "locally". Is there a way of doing this (apart from getting the derived transformation from the SceneNode and doing the inverse transformation on my scale vector)?
I have a Mesh that I load into an Entity, which lives in a SceneNode. This SceneNode has a SceneNode parent, which in turn has another SceneNodeParent (i.e. SceneNode --> SceneNode --> SceneNode --> Entity --> Mesh).
Now, I do several transformations in the SceneNodes, and for rotation and translation everything works fine. But when I try to scale my object non-uniformly (in the x-direction), it always seems to scale relative to the Mesh's original orientation, not relative to the orientation of the SceneNode.
After searching the forum, I found one person saying that SceneNode::scale() is always "global" (which is what I am seeing). But to me it would be more practical (and in my opinion logical) to scale my object "locally". Is there a way of doing this (apart from getting the derived transformation from the SceneNode and doing the inverse transformation on my scale vector)?
-
- Gnoblar
- Posts: 7
- Joined: Sun May 11, 2008 5:14 pm
Re: Scale in local coordinates?
Hey,
I've had a similar problem recently. Looking into the OGRE source code, I realized the problem is OGRE doesn't handle scaling right when composing transformations. It basically treats scale as if it was commutative with rotations, but it is not (unless the scaling is uniform). So, I suppose it's best practice to assume that OGRE does not support non-uniform scales at all (even though in certain special cases it does work).
I was thinking on how to fix this, but it's quite tricky if we also want to use quaternions to represent rotation. I can only think of a solution requiring polar decomposition during every transformation concatenation (which is quite impractical). Anyone knows a better way (apart from abandoning quaternions and going matrices)?
I've had a similar problem recently. Looking into the OGRE source code, I realized the problem is OGRE doesn't handle scaling right when composing transformations. It basically treats scale as if it was commutative with rotations, but it is not (unless the scaling is uniform). So, I suppose it's best practice to assume that OGRE does not support non-uniform scales at all (even though in certain special cases it does work).
I was thinking on how to fix this, but it's quite tricky if we also want to use quaternions to represent rotation. I can only think of a solution requiring polar decomposition during every transformation concatenation (which is quite impractical). Anyone knows a better way (apart from abandoning quaternions and going matrices)?
-
- Gnome
- Posts: 372
- Joined: Thu Dec 20, 2007 1:00 am
- Location: Florida
- x 3
-
- Old One
- Posts: 3245
- Joined: Tue Apr 24, 2007 8:23 pm
- Location: NY, NY, USA
- x 11
That's my confusion, I do rotation/translation/non-uniform scaling all on one node and it works completely as expectednbeato wrote:R * S != S * R.
For a quick solution, make an object node, use it to rotate/translate the object. Attach a scale node as a child, use it only for scaling. Then attach your mesh to the scale node.

-
- OGRE Retired Moderator
- Posts: 4823
- Joined: Fri Jun 18, 2004 1:40 pm
- Location: Berlin, Germany
- x 8
Ogre applies node transforms in SRT order, scale, rotate, translate, thus scale is applied before rotation which is the most useful way for most application.
In the odd exception, there is the possiblity nbeato explained: using a helper node. Another more light-weight approach is to "pre-rotate" the scale vector. Apply node's rotation to the scale vector and that then to the node.
In the odd exception, there is the possiblity nbeato explained: using a helper node. Another more light-weight approach is to "pre-rotate" the scale vector. Apply node's rotation to the scale vector and that then to the node.
-
- Gnoblar
- Posts: 7
- Joined: Sun May 11, 2008 5:14 pm
OK I admit I didn't have time to test it out but based on what I see in the OGRE source code, specifically,
I conclude that OGRE never combines rotation with scale and therefore can only do scaling in world coordinates, no matter how many helper nodes you use. Pre-rotating scaling vector also can't possibly produce scale with respect to rotated coordinate axes (2D example: imagine a square that you want to scale in direction (1,1) but leave alone in direction (-1,1)).
I'd be very happy if you proved me wrong though, and local scale somehow worked in OGRE.
Code: Select all
void Node::updateFromParentImpl(void) const
{
if (mParent)
{
// Update orientation
const Quaternion& parentOrientation = mParent->_getDerivedOrientation();
if (mInheritOrientation)
{
// Combine orientation with that of parent
mDerivedOrientation = parentOrientation * mOrientation;
}
else
{
// No inheritence
mDerivedOrientation = mOrientation;
}
// Update scale
const Vector3& parentScale = mParent->_getDerivedScale();
if (mInheritScale)
{
// Scale own position by parent scale, NB just combine
// as equivalent axes, no shearing
mDerivedScale = parentScale * mScale;
}
else
{
// No inheritence
mDerivedScale = mScale;
}
// Change position vector based on parent's orientation & scale
mDerivedPosition = parentOrientation * (parentScale * mPosition);
// Add altered position vector to parents
mDerivedPosition += mParent->_getDerivedPosition();
}
else
{
// Root node, no parent
mDerivedOrientation = mOrientation;
mDerivedPosition = mPosition;
mDerivedScale = mScale;
}
mCachedTransformOutOfDate = true;
mNeedParentUpdate = false;
}
I'd be very happy if you proved me wrong though, and local scale somehow worked in OGRE.
-
- Gnoblar
- Posts: 4
- Joined: Wed Jul 23, 2008 2:48 pm
Ok, here is a simple example.
I create a node and a childNode, and attach a "robot.mesh"-entity to the childNode. Then I try the following 2 cases:
a) only scale the (parent) node (500,100,100)
b) rotate the childNode 90 degrees around the Z-axis, and scale the (parent) node (500,100,100)
Here is the code for case (a):
And here is the code for case (b):
In case (a), the robot should become fat along the x-axis.
In case (b), the robot should rotate 90 degrees, and then become TALLER along the x-axis (since the robot has rotated). But what happens, is that the robot becomes fat along the y-axis (which is the mesh's x-axis).
I have included pictures below of case (a) and case (b) (the camera is pointing towards negative Z).
Case (a):

Case (b):

Case (a) is of course correct.
Case (b) is wrong; it behaves as if the scaling was done before the rotation.
I create a node and a childNode, and attach a "robot.mesh"-entity to the childNode. Then I try the following 2 cases:
a) only scale the (parent) node (500,100,100)
b) rotate the childNode 90 degrees around the Z-axis, and scale the (parent) node (500,100,100)
Here is the code for case (a):
Code: Select all
Ogre::Entity* entity = sceneMgr->createEntity("robot", "robot.mesh");
Ogre::SceneNode* node = sceneMgr->getRootSceneNode()->createChildSceneNode("LevelNode");
node->scale(500,100,100);
Ogre::SceneNode* childNode = node->createChildSceneNode("childnode");
childNode->attachObject(entity);
Code: Select all
Ogre::Entity* entity = sceneMgr->createEntity("robot", "robot.mesh");
Ogre::SceneNode* node = sceneMgr->getRootSceneNode()->createChildSceneNode("LevelNode");
node->scale(500,100,100);
Ogre::SceneNode* childNode = node->createChildSceneNode("childnode");
childNode->rotate(Ogre::Quaternion(Ogre::Degree(90), Ogre::Vector3::UNIT_Z));
childNode->attachObject(entity);
In case (b), the robot should rotate 90 degrees, and then become TALLER along the x-axis (since the robot has rotated). But what happens, is that the robot becomes fat along the y-axis (which is the mesh's x-axis).
I have included pictures below of case (a) and case (b) (the camera is pointing towards negative Z).
Case (a):

Case (b):

Case (a) is of course correct.
Case (b) is wrong; it behaves as if the scaling was done before the rotation.
-
- Gnoblar
- Posts: 7
- Joined: Sun May 11, 2008 5:14 pm
Thanks for working out an example, Abacus, that's exactly what I meant too. I've a problem with this in skeletal animation where I wanted to non-uniformly scale some bones to make some body parts more fat or thin, but it just wouldn't work correctly.
I wonder if other popular 3D engines have the same issue...
I wonder if other popular 3D engines have the same issue...
-
- Greenskin
- Posts: 118
- Joined: Tue Feb 19, 2008 1:01 pm
-
- OGRE Moderator
- Posts: 7157
- Joined: Sun Jan 25, 2004 7:35 am
- Location: Brisbane, Australia
- x 535
Yep, basically Ogre doesn't treat scales the same way a chain of matrices would work. It multiplies each scale by it's parent's scale, without using the orientation relative to the parent. This means the local axes of a node will always be orthogonal after transforming.
One possibility would be to handle the matrices manually, then pass them to the entity as a shader parameter. Of course then ogre's scene culling isn't going to exactly match.
Most people don't notice since they only scale uniformly or not at all (preferable, so no renormalising of the surface normals is needed).
One possibility would be to handle the matrices manually, then pass them to the entity as a shader parameter. Of course then ogre's scene culling isn't going to exactly match.
Most people don't notice since they only scale uniformly or not at all (preferable, so no renormalising of the surface normals is needed).
-
- Gnome
- Posts: 372
- Joined: Thu Dec 20, 2007 1:00 am
- Location: Florida
- x 3
Considering Ogre is a rendering scene graph, isn't this a bug? The scale axes should be in the local or parent coordinate frame, not global. How much stuff would this break? I can probably code a fix, but I don't want to step on toes.Kojack wrote:Yep, basically Ogre doesn't treat scales the same way a chain of matrices would work. It multiplies each scale by it's parent's scale, without using the orientation relative to the parent. This means the local axes of a node will always be orthogonal after transforming.
-
- Gnome
- Posts: 397
- Joined: Sat Nov 08, 2008 1:59 pm
- x 2
Re: Scale in local coordinates?
[REMOVED - posted in wrong thread]
Last edited by JDX_John on Sat Feb 14, 2009 10:15 am, edited 1 time in total.
-
- OGRE Retired Moderator
- Posts: 4823
- Joined: Fri Jun 18, 2004 1:40 pm
- Location: Berlin, Germany
- x 8
Re: Scale in local coordinates?
Completely different issues. This thread is about non-uniform scaling of nodes.
The other thread is about an export problem, as far as I can see. Morphing is done in a different manner.
JDXSolutions, what is the problem you actually want to have solved?
The other thread is about an export problem, as far as I can see. Morphing is done in a different manner.
JDXSolutions, what is the problem you actually want to have solved?
-
- Gnome
- Posts: 397
- Joined: Sat Nov 08, 2008 1:59 pm
- x 2
Re: Scale in local coordinates?
Sorry I was meaning to post in the other thread... we think the problem may not be the exporter after all but Ogre's scaling - I was going to post this thread to the other one and got mixed uphaffax wrote:Completely different issues. This thread is about non-uniform scaling of nodes.
The other thread is about an export problem, as far as I can see. Morphing is done in a different manner.
JDXSolutions, what is the problem you actually want to have solved?

-
- Gremlin
- Posts: 156
- Joined: Sun Sep 14, 2003 3:54 am
- Location: Beijing China
Re: Scale in local coordinates?
what's about non-uniform scaling now(1.7 trunk) in ogre's bone/node?