Download

About create FTransform from a 4x4 matrix

Recently, I’m trying to do something needs to convert a 4x4 matrix to FTransform. Of course, FMatrix is the right class to use, and I make a simple translate matrix like this:

1, 0, 0 10
0, 1, 0, 20
0, 0, 1, 30
0, 0, 0, 1

Generally, this matrix means translate by a Vector(10, 20, 30), at least that’s my understanding, but, I got Vector(0, 0, 0) for translate, I’m confused, so I go though relevant source code. I found this function FMatrix::SetFromMatrix

// /Engine/Source/Runtime/Core/Public/Math/TransformVectorized.h#L1209
	void SetFromMatrix(const FMatrix& InMatrix)
	{
		FMatrix M = InMatrix;

		// Get the 3D scale from the matrix
		FVector InScale = M.ExtractScaling();
		Scale3D = VectorLoadFloat3_W0(&InScale);

		// If there is negative scaling going on, we handle that here
		if(InMatrix.Determinant() < 0.f)
		{
			// Assume it is along X and modify transform accordingly. 
			// It doesn't actually matter which axis we choose, the 'appearance' will be the same			
			Scale3D = VectorMultiply(Scale3D, GlobalVectorConstants::FloatMinus1_111 );			
			M.SetAxis(0, -M.GetScaledAxis( EAxis::X ));
		}

		FQuat InRotation = FQuat(M);
		Rotation = VectorLoadAligned(&InRotation);
		FVector InTranslation = InMatrix.GetOrigin(); // this line for translation so let's go to GetOrigin
		Translation = VectorLoadFloat3_W0(&InTranslation);

		// Normalize rotation
		Rotation = VectorNormalizeQuaternion(Rotation);		
	}

and FMatrix::GetOrigin

// /Engine/Source/Runtime/Core/Public/Math/Matrix.inl#L525
inline FVector FMatrix::GetOrigin() const
{
	return FVector(M[3][0],M[3][1],M[3][2]);
}

Is that right? If I remembered clearly, M[0][3],M[1][3],M[2][3] is the right vector for translation, acoording to wikipedia, am I right?

@iKaivnD

Hi there!

I believe what you want to be looking at in the source code is actually this:

TranslationMatrix.h

// Copyright Epic Games, Inc. All Rights Reserved.

#pragma once

#include "CoreTypes.h"
#include "Math/Vector.h"
#include "Math/Plane.h"
#include "Math/Matrix.h"

class FTranslationMatrix
	: public FMatrix
{
public:

//...
FORCEINLINE FTranslationMatrix::FTranslationMatrix(const FVector& Delta)
	: FMatrix(
		FPlane(1.0f,	0.0f,	0.0f,	0.0f),
		FPlane(0.0f,	1.0f,	0.0f,	0.0f),
		FPlane(0.0f,	0.0f,	1.0f,	0.0f),
		FPlane(Delta.X,	Delta.Y,Delta.Z,1.0f)   //<<~~~~~~~~~~~~~~ ♥ Rama
	)
{ }

Then this constructor should get you what you want, from FTransform

TransformNonVectorized.h

/**
	* Constructor for converting a Matrix (including scale) into a FTransform.
	*/
	FORCEINLINE explicit FTransform(const FMatrix& InMatrix)
	{
		SetFromMatrix(InMatrix);
		DiagnosticCheckNaN_All();
	}

so the simplest case, isolating the translation component of your logics:

FTransform JoyfulTransform( FTranslationMatrix( FVector(10,20,30) ) );
//Do things with JoyfulTransform

Obviously that is just the logical ordering of getting from where you code is actually starting to your lofty FTransform Goal.

But hopefully the FTranslationMatrix source code makes it clear how to reorder your Matrix numbers for UE.

:heart:

Rama