END_TEST;
}
+int UtcDaliActorCalculateWorldTransform08(void)
+{
+ TestApplication application;
+
+ tet_infoline("Test that actor inheritance of scale produces right transform matrix");
+
+ Vector3 solutions[] = {Vector3(250, 0, 0), Vector3(0, 250, 0), Vector3(650, 0, 0), Vector3(0, 250, 0), Vector3(650, 0, 0), Vector3(400, 250, 0), Vector3(200, -50, 0), Vector3(500, 200, 0)};
+
+ struct TestCase
+ {
+ bool translation;
+ bool rotation;
+ bool scaling;
+ };
+ TestCase testCases[] = {
+ {false, false, true},
+ {false, true, false},
+ {true, false, false},
+ {false, true, true},
+ {true, false, true},
+ {true, true, false},
+ {false, false, false},
+ {true, true, true},
+ };
+
+ Actor rootActor = Actor::New();
+ Actor leafActor = Actor::New();
+
+ rootActor[Actor::Property::POSITION] = Vector3(0.0f, 0.0f, 0.0f);
+ rootActor[Actor::Property::SCALE] = Vector3(1.0f, 2.0f, 1.0f);
+ rootActor[Actor::Property::ORIENTATION] = AngleAxis(Degree(90.0f), Vector3::ZAXIS);
+ rootActor[Actor::Property::SIZE] = Vector2(200, 400);
+ rootActor[Actor::Property::ANCHOR_POINT] = AnchorPoint::CENTER;
+ rootActor[Actor::Property::PARENT_ORIGIN] = ParentOrigin::CENTER;
+
+ leafActor[Actor::Property::POSITION] = Vector3(0.0f, -50.0f, 0.0f);
+ leafActor[Actor::Property::SCALE] = Vector3(1.0f, 1.0f, 1.0f);
+ leafActor[Actor::Property::ORIENTATION] = AngleAxis(Degree(90.0f), Vector3::ZAXIS);
+ leafActor[Actor::Property::SIZE] = Vector2(200, 400);
+ leafActor[Actor::Property::ANCHOR_POINT] = AnchorPoint::BOTTOM_CENTER;
+ leafActor[Actor::Property::PARENT_ORIGIN] = ParentOrigin::TOP_CENTER;
+ leafActor[Actor::Property::POSITION_USES_ANCHOR_POINT] = true;
+
+ application.GetScene().Add(rootActor);
+ rootActor.Add(leafActor);
+
+ for(uint32_t i = 0; i< 8; ++i)
+ {
+ leafActor[Actor::Property::INHERIT_POSITION] = testCases[i].translation;
+ leafActor[Actor::Property::INHERIT_ORIENTATION] = testCases[i].rotation;
+ leafActor[Actor::Property::INHERIT_SCALE] = testCases[i].scaling;
+
+ application.SendNotification();
+ application.Render(0);
+ application.SendNotification();
+ application.Render(0);
+
+ Matrix m = DevelActor::GetWorldTransform(leafActor);
+ Matrix actualMatrix = leafActor.GetCurrentProperty<Matrix>(Actor::Property::WORLD_MATRIX);
+
+ Vector3 worldPosition1 = Vector3(m.GetTranslation());
+ Vector3 worldPosition2 = Vector3(actualMatrix.GetTranslation());
+
+ DALI_TEST_EQUALS(solutions[i], worldPosition1, 0.001f, TEST_LOCATION);
+ DALI_TEST_EQUALS(solutions[i], worldPosition2, 0.001f, TEST_LOCATION);
+ }
+
+ END_TEST;
+}
+
int UtcDaliActorCalculateWorldColor01(void)
{
TestApplication application;
}
else
{
- Vector3 parentPosition, parentScale;
- Quaternion parentOrientation;
- worldMatrix.GetTransformComponents(parentPosition, parentOrientation, parentScale);
-
+ // Get Parent information.
+ Vector3 parentPosition, parentScale;
+ Quaternion parentOrientation;
+ const Matrix& parentMatrix = worldMatrix;
+ parentMatrix.GetTransformComponents(parentPosition, parentOrientation, parentScale);
+
+ // Compute intermediate Local information
+ centerPosition = CalculateCenterPosition(anchorPoint, positionUsesAnchorPoint, size, localScale, localOrientation);
+ Vector3 intermediateLocalPosition = actorPosition + centerPosition + (parentOrigin - Vector3(0.5f, 0.5f, 0.5f)) * parentSize;
+ Matrix intermediateLocalMatrix;
+ intermediateLocalMatrix.SetTransformComponents(localScale, localOrientation, intermediateLocalPosition);
+
+ // Compute intermediate world information
+ Matrix intermediateWorldMatrix;
+ MatrixUtils::Multiply(intermediateWorldMatrix, intermediateLocalMatrix, parentMatrix);
+
+ Vector3 intermediateWorldPosition, intermediateWorldScale;
+ Quaternion intermediateWorldOrientation;
+ intermediateWorldMatrix.GetTransformComponents(intermediateWorldPosition, intermediateWorldOrientation, intermediateWorldScale);
+
+ // Compute final world information
+ Vector3 finalWorldPosition = intermediateWorldPosition;
+ Vector3 finalWorldScale = intermediateWorldScale;
+ Quaternion finalWorldOrientation = intermediateWorldOrientation;
+ // worldScale includes the influence of local scale, local rotation, and parent scale.
+ // So, for the final world matrix, if this node inherits its parent scale, use worldScale.
+ // If not, use local scale for the final world matrix.
if((inheritanceModeList[i] & INHERIT_SCALE) == 0)
{
- //Don't inherit scale
- localScale /= parentScale;
+ finalWorldScale = localScale;
}
+ // For the final world matrix, if this node inherits its parent orientation, use worldOrientation.
+ // If not, use local orientation for the final world matrix.
if((inheritanceModeList[i] & INHERIT_ORIENTATION) == 0)
{
- //Don't inherit orientation
- parentOrientation.Invert();
- localOrientation = parentOrientation * localOrientation;
+ finalWorldOrientation = localOrientation;
}
- if((inheritanceModeList[i] & INHERIT_POSITION) == 0)
- {
- localMatrix.SetTransformComponents(localScale, localOrientation, Vector3::ZERO);
- Matrix tempMatrix;
- MatrixUtils::Multiply(tempMatrix, localMatrix, worldMatrix);
- worldMatrix = tempMatrix;
- worldMatrix.SetTranslation(actorPosition + centerPosition);
- }
- else
+ // The final world position of this node is computed as a sum of
+ // parent origin position in world space and relative position of center from parent origin.
+ // If this node doesn't inherit its parent position, simply use the relative position as a final world position.
+ Vector3 localCenterPosition = CalculateCenterPosition(anchorPoint, positionUsesAnchorPoint, size, finalWorldScale, finalWorldOrientation);
+ finalWorldPosition = actorPosition * finalWorldScale;
+ finalWorldPosition *= finalWorldOrientation;
+ finalWorldPosition += localCenterPosition;
+ if((inheritanceModeList[i] & INHERIT_POSITION) != 0)
{
- localPosition = actorPosition + centerPosition + (parentOrigin - Vector3(0.5f, 0.5f, 0.5f)) * parentSize;
- localMatrix.SetTransformComponents(localScale, localOrientation, localPosition);
- Matrix tempMatrix;
- MatrixUtils::Multiply(tempMatrix, localMatrix, worldMatrix);
- worldMatrix = tempMatrix;
+ Vector4 parentOriginPosition((parentOrigin - Vector3(0.5f, 0.5f, 0.5f)) * parentSize);
+ parentOriginPosition.w = 1.0f;
+ finalWorldPosition += Vector3(parentMatrix * parentOriginPosition);
}
+
+ worldMatrix.SetTransformComponents(finalWorldScale, finalWorldOrientation, finalWorldPosition);
}
}
else
#include <dali/internal/common/matrix-utils.h>
#include <dali/public-api/common/constants.h>
+#include <dali/integration-api/debug.h>
+
namespace Dali
{
namespace Internal
* @brief Calculates the center position for the transform component
* @param[out] centerPosition The calculated center-position of the transform component
* @param[in] transformComponentStatic A const reference to the static component transform struct
- * @param[in] transformComponentAnimatable A const reference to the animatable component transform struct
+ * @param[in] scale scale factor to be applied to the center position.
+ * @param[in] orientation orientation factor to be applied to the center position.
* @param[in] size The size of the current transform component
* @param[in] half Halfway point of the transform
* @param[in] topLeft The top-left coords of the transform
*/
inline void CalculateCenterPosition(
- Vector3& centerPosition,
- const TransformComponentStatic& transformComponentStatic,
- const TransformComponentAnimatable& transformComponentAnimatable,
- const Vector3& size,
- const Vector3& half,
- const Vector3& topLeft)
+ Vector3& centerPosition,
+ const TransformComponentStatic& transformComponentStatic,
+ const Vector3& scale,
+ const Quaternion& orientation,
+ const Vector3& size,
+ const Vector3& half,
+ const Vector3& topLeft)
{
// Calculate the center-point by applying the scale and rotation on the anchor point.
- centerPosition = (half - transformComponentStatic.mAnchorPoint) * size * transformComponentAnimatable.mScale;
- centerPosition *= transformComponentAnimatable.mOrientation;
+ centerPosition = (half - transformComponentStatic.mAnchorPoint) * size * scale;
+ centerPosition *= orientation;
// If the position is ignoring the anchor-point, then remove the anchor-point shift from the position.
if(!transformComponentStatic.mPositionUsesAnchorPoint)
{
//Full transform inherited
mLocalMatrixDirty[i] = true;
- CalculateCenterPosition(centerPosition, mTxComponentStatic[i], mTxComponentAnimatable[i], mSize[i], half, topLeft);
+ CalculateCenterPosition(centerPosition, mTxComponentStatic[i], mTxComponentAnimatable[i].mScale, mTxComponentAnimatable[i].mOrientation, mSize[i], half, topLeft);
localPosition = mTxComponentAnimatable[i].mPosition + centerPosition + (mTxComponentStatic[i].mParentOrigin - half) * mSize[parentIndex];
mLocal[i].SetTransformComponents(mTxComponentAnimatable[i].mScale, mTxComponentAnimatable[i].mOrientation, localPosition);
}
}
else
{
- //Some components are not inherited
+ // Keep previous localMatrix for comparison.
+ Matrix previousLocalMatrix = mLocal[i];
+
+ // Get Parent information.
Vector3 parentPosition, parentScale;
Quaternion parentOrientation;
const Matrix& parentMatrix = mWorld[parentIndex];
parentMatrix.GetTransformComponents(parentPosition, parentOrientation, parentScale);
- Vector3 localScale = mTxComponentAnimatable[i].mScale;
+ // Compute intermediate Local information
+ CalculateCenterPosition(centerPosition, mTxComponentStatic[i], mTxComponentAnimatable[i].mScale, mTxComponentAnimatable[i].mOrientation, mSize[i], half, topLeft);
+ Vector3 intermediateLocalPosition = mTxComponentAnimatable[i].mPosition + centerPosition + (mTxComponentStatic[i].mParentOrigin - half) * mSize[parentIndex];
+ Matrix intermediateLocalMatrix;
+ intermediateLocalMatrix.SetTransformComponents(mTxComponentAnimatable[i].mScale, mTxComponentAnimatable[i].mOrientation, intermediateLocalPosition);
+
+ // Compute intermediate world information
+ Matrix intermediateWorldMatrix;
+ MatrixUtils::Multiply(intermediateWorldMatrix, intermediateLocalMatrix, mWorld[parentIndex]);
+
+ Vector3 intermediateWorldPosition, intermediateWorldScale;
+ Quaternion intermediateWorldOrientation;
+ intermediateWorldMatrix.GetTransformComponents(intermediateWorldPosition, intermediateWorldOrientation, intermediateWorldScale);
+
+ // Compute final world information
+ Vector3 finalWorldPosition = intermediateWorldPosition;
+ Vector3 finalWorldScale = intermediateWorldScale;
+ Quaternion finalWorldOrientation = intermediateWorldOrientation;
+ // worldScale includes the influence of local scale, local rotation, and parent scale.
+ // So, for the final world matrix, if this node inherits its parent scale, use worldScale.
+ // If not, use local scale for the final world matrix.
if((mInheritanceMode[i] & INHERIT_SCALE) == 0)
{
- //Don't inherit scale
- localScale /= parentScale;
+ finalWorldScale = mTxComponentAnimatable[i].mScale;
}
- Quaternion localOrientation(mTxComponentAnimatable[i].mOrientation);
+ // For the final world matrix, if this node inherits its parent orientation, use worldOrientation.
+ // If not, use local orientation for the final world matrix.
if((mInheritanceMode[i] & INHERIT_ORIENTATION) == 0)
{
- //Don't inherit orientation
- parentOrientation.Invert();
- localOrientation = parentOrientation * mTxComponentAnimatable[i].mOrientation;
+ finalWorldOrientation = mTxComponentAnimatable[i].mOrientation;
}
- Matrix localMatrix = mLocal[i];
-
- if((mInheritanceMode[i] & INHERIT_POSITION) == 0)
- {
- //Don't inherit position
- CalculateCenterPosition(centerPosition, mTxComponentStatic[i], mTxComponentAnimatable[i], mSize[i], half, topLeft);
- mLocal[i].SetTransformComponents(localScale, localOrientation, Vector3::ZERO);
- MatrixUtils::Multiply(mWorld[i], mLocal[i], parentMatrix);
- mWorld[i].SetTranslation(mTxComponentAnimatable[i].mPosition + centerPosition);
- }
- else
+ // The final world position of this node is computed as a sum of
+ // parent origin position in world space and relative position of center from parent origin.
+ // If this node doesn't inherit its parent position, simply use the relative position as a final world position.
+ Vector3 localCenterPosition;
+ CalculateCenterPosition(localCenterPosition, mTxComponentStatic[i], finalWorldScale, finalWorldOrientation, mSize[i], half, topLeft);
+ finalWorldPosition = mTxComponentAnimatable[i].mPosition * finalWorldScale;
+ finalWorldPosition *= finalWorldOrientation;
+ finalWorldPosition += localCenterPosition;
+ if((mInheritanceMode[i] & INHERIT_POSITION) != 0)
{
- CalculateCenterPosition(centerPosition, mTxComponentStatic[i], mTxComponentAnimatable[i], mSize[i], half, topLeft);
- localPosition = mTxComponentAnimatable[i].mPosition + centerPosition + (mTxComponentStatic[i].mParentOrigin - half) * mSize[parentIndex];
- mLocal[i].SetTransformComponents(localScale, localOrientation, localPosition);
- MatrixUtils::Multiply(mWorld[i], mLocal[i], parentMatrix);
+ Vector4 parentOriginPosition((mTxComponentStatic[i].mParentOrigin - half) * mSize[parentIndex]);
+ parentOriginPosition.w = 1.0f;
+ finalWorldPosition += Vector3(parentMatrix * parentOriginPosition);
}
- mLocalMatrixDirty[i] = mComponentDirty[i] || (localMatrix != mLocal[i]);
+ mWorld[i].SetTransformComponents(finalWorldScale, finalWorldOrientation, finalWorldPosition);
+
+ Matrix inverseParentMatrix;
+ inverseParentMatrix.SetInverseTransformComponents(parentScale, parentOrientation, parentPosition);
+ mLocal[i] = inverseParentMatrix * mWorld[i];
+
+ mLocalMatrixDirty[i] = mComponentDirty[i] || (previousLocalMatrix != mLocal[i]);
}
}
else //Component has no parent or doesn't inherit transform
{
Matrix localMatrix = mLocal[i];
- CalculateCenterPosition(centerPosition, mTxComponentStatic[i], mTxComponentAnimatable[i], mSize[i], half, topLeft);
+ CalculateCenterPosition(centerPosition, mTxComponentStatic[i], mTxComponentAnimatable[i].mScale, mTxComponentAnimatable[i].mOrientation, mSize[i], half, topLeft);
localPosition = mTxComponentAnimatable[i].mPosition + centerPosition;
mLocal[i].SetTransformComponents(mTxComponentAnimatable[i].mScale, mTxComponentAnimatable[i].mOrientation, localPosition);
mWorld[i] = mLocal[i];