cs686's picture
Deploy Kimodo ZeroGPU motion API
a550c4e verified
Raw
History Blame Contribute Delete
16.6 kB
/*
* SPDX-FileCopyrightText: Copyright (c) 2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
* SPDX-License-Identifier: Apache-2.0
*/
#pragma once
#include "Transform.h"
namespace Math
{
inline Transform Transform::FromRotation(const Quaternion& rotation)
{
return Transform(rotation);
}
inline Transform Transform::FromTranslation(const Vector& translation)
{
return Transform(Quaternion::Identity, translation);
}
inline Transform Transform::FromScale(float uniformScale)
{
return Transform(Quaternion::Identity, Vector::Zero, uniformScale);
}
inline Transform Transform::FromTranslationAndScale(const Vector& translation, float uniformScale)
{
return Transform(Quaternion::Identity, translation, uniformScale);
}
inline Transform Transform::FromRotationBetweenVectors(const Vector sourceVector, const Vector targetVector)
{
return Transform(Quaternion::FromRotationBetweenNormalizedVectors(sourceVector, targetVector));
}
inline Transform Transform::Lerp(const Transform& from, const Transform& to, float t)
{
Quaternion const rotation = Quaternion::NLerp(Quaternion(from.m_rotation), Quaternion(to.m_rotation), t);
Vector const translationAndScale = Vector::Lerp(from.m_translationScale, to.m_translationScale, t);
Transform lerped(NoInit);
lerped.m_rotation = rotation;
lerped.m_translationScale = translationAndScale;
return lerped;
}
inline Transform Transform::Slerp(const Transform& from, const Transform& to, float t)
{
Quaternion const rotation = Quaternion::SLerp(Quaternion(from.m_rotation), Quaternion(to.m_rotation), t);
Vector const translationAndScale = Vector::Lerp(Vector(from.m_translationScale), Vector(to.m_translationScale), t);
Transform lerped(NoInit);
lerped.m_rotation = rotation;
lerped.m_translationScale = translationAndScale;
return lerped;
}
inline Transform Transform::FastSlerp(const Transform& from, const Transform& to, float t)
{
Quaternion const rotation = Quaternion::FastSLerp(Quaternion(from.m_rotation), Quaternion(to.m_rotation), t);
Vector const translationAndScale = Vector::Lerp(Vector(from.m_translationScale), Vector(to.m_translationScale), t);
Transform lerped(NoInit);
lerped.m_rotation = rotation;
lerped.m_translationScale = translationAndScale;
return lerped;
}
inline Transform Transform::Delta(const Transform& from, const Transform& to)
{
ASSERT(from.m_rotation.IsNormalized() && to.m_rotation.IsNormalized());
ASSERT(!from.m_translationScale.IsW0() && !to.m_translationScale.IsW0());
Transform result;
Vector const inverseScale = from.GetInverseScaleVector();
Vector const deltaScale = to.GetScaleVector() * inverseScale;
// If we have negative scaling, we need to use matrices to calculate the deltas
Vector const minScale = Vector::Min(from.m_translationScale.GetSplatW(), to.m_translationScale.GetSplatW());
if (minScale.IsAnyLessThan(Vector::Zero))
{
// Multiply the transforms using matrices to get the correct rotation and then remove the scale;
Matrix const toMtx = to.ToMatrix();
Matrix const fromMtx = from.ToMatrix();
Matrix resultMtx = toMtx * fromMtx.GetInverse();
resultMtx.RemoveScaleFast();
// Apply back the signs from the final scale
Vector const sign = deltaScale.GetSign();
resultMtx[0] *= sign.GetSplatX();
resultMtx[1] *= sign.GetSplatY();
resultMtx[2] *= sign.GetSplatZ();
result.m_rotation = resultMtx.GetRotation();
ASSERT(result.m_rotation.IsNormalized());
result.m_translationScale = Vector::Select(resultMtx.GetTranslation(), deltaScale, Vector::Select0001);
}
else
{
Quaternion const fromInverseRotation = from.m_rotation.GetInverse();
result.m_rotation = to.m_rotation * fromInverseRotation;
Vector const deltaTranslation = to.m_translationScale - from.m_translationScale;
Vector const translation = fromInverseRotation.RotateVector(deltaTranslation) * inverseScale;
result.m_translationScale = Vector::Select(translation, deltaScale, Vector::Select0001);
}
return result;
}
inline Transform Transform::DeltaNoScale(const Transform& from, const Transform& to)
{
Quaternion const inverseFromRotation = from.m_rotation.GetInverse();
Vector const deltaTranslation = to.GetTranslation() - from.GetTranslation();
Transform delta;
delta.m_rotation = to.m_rotation * inverseFromRotation;
delta.m_translationScale = inverseFromRotation.RotateVector(deltaTranslation).GetWithW1();
return delta;
}
inline void Transform::DirectlySetRotation(Transform& transform, Quaternion&& rotation)
{
transform.m_rotation = rotation;
}
inline void Transform::DirectlySetRotation(Transform& transform, const Quaternion& rotation)
{
transform.m_rotation = rotation;
}
inline void Transform::DirectlySetTranslationScale(Transform& transform, Vector&& translationScale)
{
transform.m_translationScale = translationScale;
}
inline void Transform::DirectlySetTranslationScale(Transform& transform, const Vector& translationScale)
{
transform.m_translationScale = translationScale;
}
inline Transform::Transform(NoInit_t)
: m_rotation(NoInit)
, m_translationScale(NoInit)
{
}
inline Transform::Transform(const Matrix& m)
{
Vector mTranslation, mScale;
m.Decompose(m_rotation, mTranslation, mScale);
ASSERT(Math::IsNearEqual(mScale.GetX(), mScale.GetY()) && Math::IsNearEqual(mScale.GetY(),mScale.GetZ()));
m_translationScale = Vector::Select(mTranslation, mScale, Vector::Select0001);
}
inline Transform::Transform(const Quaternion& rotation, const Vector& translation, float scale)
: m_rotation(rotation)
, m_translationScale(Vector::Select(translation, Vector(scale), Vector::Select0001))
{
}
inline Transform::Transform(const AxisAngle& rotation)
: m_rotation(rotation)
, m_translationScale(Vector::UnitW)
{
}
inline Matrix Transform::ToMatrix() const
{
return Matrix(m_rotation, m_translationScale.GetWithW1(), m_translationScale.GetSplatW());
}
inline Matrix Transform::ToMatrixNoScale() const
{
return Matrix(m_rotation, m_translationScale.GetWithW1(), Vector::One);
}
inline EulerAngles Transform::ToEulerAngles() const
{
return m_rotation.ToEulerAngles();
}
inline Vector Transform::GetAxisX() const
{
return m_rotation.RotateVector(Vector::UnitX);
}
inline Vector Transform::GetAxisY() const
{
return m_rotation.RotateVector(Vector::UnitY);
}
inline Vector Transform::GetAxisZ() const
{
return m_rotation.RotateVector(Vector::UnitZ);
}
inline Vector Transform::GetRightVector() const
{
return m_rotation.RotateVector(Vector::WorldRight);
}
inline Vector Transform::GetForwardVector() const
{
return m_rotation.RotateVector(Vector::WorldForward);
}
inline Vector Transform::GetUpVector() const
{
return m_rotation.RotateVector(Vector::WorldUp);
}
inline bool Transform::IsIdentity() const
{
return m_rotation.IsIdentity() && m_translationScale.IsEqual4(Vector::UnitW);
}
inline bool Transform::IsRigidTransform() const
{
return GetScale() == 1.0f;
}
inline void Transform::MakeRigidTransform()
{
SetScale(1.0f);
}
inline Transform& Transform::Inverse()
{
ASSERT(!m_translationScale.IsW0());
Quaternion const inverseRotation = m_rotation.GetInverse();
m_rotation = inverseRotation;
Vector const inverseScale = GetInverseScaleVector();
Vector const inverselyScaledTranslation = inverseScale * m_translationScale.GetWithW0();
Vector const inverselyRotatedTranslation = inverseRotation.RotateVector(inverselyScaledTranslation);
Vector const inverseTranslation = inverselyRotatedTranslation.GetNegated().SetW0();
m_translationScale = Vector::Select(inverseTranslation, inverseScale, Vector::Select0001);
return *this;
}
inline Transform Transform::GetInverse() const
{
Transform inverse = *this;
return inverse.Inverse();
}
inline Transform Transform::GetDeltaToOther(const Transform& targetTransform) const
{
return Transform::Delta(*this, targetTransform);
}
inline Transform Transform::GetDeltaFromOther(const Transform& startTransform) const
{
return Transform::Delta(startTransform, *this);
}
inline const Quaternion& Transform::GetRotation() const
{
return m_rotation;
}
inline void Transform::SetRotation(const Quaternion& rotation)
{
ASSERT(rotation.IsNormalized());
m_rotation = rotation;
}
inline void Transform::AddRotation(const Quaternion& delta)
{
ASSERT(delta.IsNormalized());
m_rotation = delta * m_rotation;
}
inline const Vector& Transform::GetTranslation() const
{
return m_translationScale;
}
inline const Vector& Transform::GetTranslationAndScale() const
{
return m_translationScale;
}
inline void Transform::SetTranslation(const Vector& newTranslation)
{
m_translationScale = Vector::Select(newTranslation, m_translationScale, Vector::Select0001);
}
inline void Transform::SetTranslationAndScale(const Vector& newTranslationScale)
{
ASSERT(newTranslationScale.GetW() != 0.0f);
m_translationScale = newTranslationScale;
}
inline void Transform::AddTranslation(const Vector& translationDelta)
{
m_translationScale += translationDelta.GetWithW0();
}
inline Vector Transform::GetTranslationAsVector() const
{
return m_translationScale.GetWithW0();
}
inline Vector Transform::GetTranslationAsPoint() const
{
return m_translationScale.GetWithW1();
}
inline float Transform::GetScale() const
{
return m_translationScale.GetW();
}
inline Vector Transform::GetScaleVector() const
{
return m_translationScale.GetSplatW();
}
inline Vector Transform::GetInverseScaleVector() const
{
return m_translationScale.GetSplatW().GetInverse();
}
inline void Transform::SetScale(float uniformScale)
{
m_translationScale.SetW(uniformScale);
}
inline bool Transform::HasScale() const
{
return m_translationScale.GetW() != 1.0f;
}
inline bool Transform::HasNegativeScale() const
{
return m_translationScale.GetW() < 0.0f;
}
inline Vector Transform::TranslateVector(const Vector& vector) const
{
return vector + m_translationScale.GetWithW0();
}
inline Vector Transform::ScaleVector(const Vector& vector) const
{
return vector * GetScaleVector();
}
inline Vector Transform::TransformPoint(const Vector& point) const
{
ASSERT(!m_translationScale.IsW0());
Vector transformedPoint = point * m_translationScale.GetSplatW();
transformedPoint = (m_translationScale + m_rotation.RotateVector(transformedPoint)).GetWithW0();
return transformedPoint;
}
inline Vector Transform::TransformPointNoScale(const Vector& point) const
{
Vector transformedPoint = (m_translationScale + m_rotation.RotateVector(point)).GetWithW0();;
return transformedPoint;
}
inline Vector Transform::RotateVector(const Vector& vector) const
{
return m_rotation.RotateVector(vector);
}
inline Vector Transform::TransformNormal(const Vector& vector) const
{
return RotateVector(vector);
}
inline Vector Transform::InverseRotateVector(const Vector& vector) const
{
return m_rotation.RotateVectorInverse(vector);
}
inline Vector Transform::InverseTransformPoint(const Vector& point) const
{
ASSERT(!m_translationScale.IsW0());
Vector const shiftedPoint = point - m_translationScale;
Vector const unrotatedShiftedPoint = m_rotation.RotateVectorInverse(shiftedPoint);
Vector const inverseScale = GetInverseScaleVector();
Vector const result = unrotatedShiftedPoint * inverseScale;
return result;
}
inline Vector Transform::InverseTransformPointNoScale(const Vector& point) const
{
Vector const shiftedPoint = point - m_translationScale;
Vector const unrotatedShiftedPoint = m_rotation.RotateVectorInverse(shiftedPoint);
return unrotatedShiftedPoint;
}
inline Vector Transform::TransformVector(const Vector& vector) const
{
ASSERT(!m_translationScale.IsW0());
Vector transformedVector = vector * GetScaleVector();
transformedVector = m_rotation.RotateVector(transformedVector);
return transformedVector;
}
inline Vector Transform::TransformVectorNoScale(const Vector& vector) const
{
return RotateVector(vector);
}
inline Vector Transform::InverseTransformVector(const Vector& vector) const
{
ASSERT(!m_translationScale.IsW0());
Vector const unrotatedVector = m_rotation.RotateVectorInverse(vector);
Vector const inverseScale = GetInverseScaleVector();
Vector const result = unrotatedVector * inverseScale;
return result;
}
inline Vector Transform::InverseTransformVectorNoScale(const Vector& vector) const
{
return m_rotation.RotateVectorInverse(vector);
}
inline Transform Transform::operator*(const Transform& rhs) const
{
Transform transform = *this;
transform *= rhs;
return transform;
}
inline Transform& Transform::operator*=(const Transform& rhs)
{
Vector const scale = GetScaleVector();
Vector const rhsScale = rhs.GetScaleVector();
Vector const minScale = Vector::Min(scale, rhsScale);
Vector const finalScale = scale * rhsScale;
if (minScale.IsAnyLessThan(Vector::Zero))
{
// Multiply the transforms using matrices to
// get the correct rotation and then remove the scale;
Matrix const lhsMtx = ToMatrix();
Matrix const rhsMtx = rhs.ToMatrix();
Matrix resultMtx = lhsMtx * rhsMtx;
resultMtx.RemoveScaleFast();
// Apply back the signs from the final scale
Vector const sign = finalScale.GetSign();
resultMtx[0] *= sign.GetSplatX();
resultMtx[1] *= sign.GetSplatY();
resultMtx[2] *= sign.GetSplatZ();
m_rotation = resultMtx.GetRotation();
ASSERT(m_rotation.IsNormalized());
m_translationScale = Vector::Select(resultMtx.GetTranslation(), finalScale, Vector::Select0001);
}
else
{
// Normal case
m_rotation = m_rotation * rhs.m_rotation;
m_rotation.Normalize();
Vector const translation = rhs.m_rotation.RotateVector(m_translationScale * rhsScale) + rhs.m_translationScale;
m_translationScale = Vector::Select(translation, finalScale, Vector::Select0001);
}
return *this;
}
inline bool Transform::IsNearEqual(const Transform& rhs, const Radians angleThreshold, float translationScaleThreshold) const
{
if (!m_rotation.IsNearEqual(rhs.m_rotation, angleThreshold))
{
return false;
}
if (!m_translationScale.IsNearEqual4(rhs.m_translationScale, translationScaleThreshold))
{
return false;
}
return true;
}
inline bool Transform::operator==(const Transform& rhs) const
{
if (m_translationScale != rhs.m_translationScale)
{
return false;
}
if (m_rotation != rhs.m_rotation)
{
return false;
}
return true;
}
inline bool Transform::operator!=(const Transform& rhs) const
{
return !operator==(rhs);
}
}