Effects - apply rotation on vector without scale and translation (in HLSL)?

Might be a silly question but couldn’t find an answer…
Given a matrix and a vector, whats the proper way to apply rotation only on the vector? ie no scale and translation.

Thanks!

Edit: guess I wasn’t clear enough, I meant in HLSL not in c#…)

// Apply rotation on Vector
__Rotation.X   = 95;
__Rotatatuin.Y = 45;

// Compute Rotation matrix from a Vector
//
XF.Matrix.CreateFromYawPitchRoll( 
         XF.MathHelper.ToRadians( __Rotation.Y ),
         XF.MathHelper.ToRadians( __Rotation.X ),
         XF.MathHelper.ToRadians( __Rotation.Z ), out __MatRotation );

// NOTE: From here you already have matrix rotation from a vector


// No Scale
__MatScale    = Matrix.Identity; 

// No Transalation
__MatTranslation = Matrix.Identity; 

// Compute world
__EntityWorld = ( __MatScale * __MatRotation ) * __MatTranslation;

I do it like the code above, If I understand your inquiry correctly ^_^y

This may be a (ugly?) solution :

Vector3 ApplyRotationOnly(Vector3 v, Matrix matrix)
{
    Vector3 scale, translation;
    Quaternion rotationQuat;
    matrix.Decompose(out scale, out rotationQuat, out translation);
    return Vector3.Transform(v, rotationQuat);
}

In HLSL you pretty much have to grab the 3x3 out the larger matrix. After you’ve rotated + scaled the normal using that matrix then normalize the normal.

Otherwise you have to normalize your vectors before you build the new 3x3, which is kind of stupid. 3 vs. 1 normalize.

HLSL does have matrix swizzle operators for extracting vectors. They are arcane as hell though. myMatrix._01_02_03 etc.

1 Like

Thanks but wouldn’t this apply translation too? Also if I normalize the vector instead of the matrix it wouldnt give right results if scale is not uniformed (for example 5,1,1)

I guess it’s not the most efficient solution but what should work is that you save the length of the vector before multiplying with the float3x3 casted matrix. After the multiplication you would then normalize the vector and multiply it again with the saved length…

Oh just overlooked the last answer which suggests the same. :slight_smile:

I think with non uniform scale this will not work though…

Where do you get the vector from? Maybe you could save more information like the scale and pass it to your shader?

In a 4x4 matrix the translation is in the 4th column. If you only take a 3x3 portion the translation will be gone.

1 Like

Alternatively to the swizzle operators there is also the row operator, you can zero out the 4th row then multiply your vector.

float3x3 mat = world;
mat[3] = zeroVector; // be aware if this is a vector4 the m_33 w element needs to be 1.0f
float4 nvec = mul(vec, mat);

1 Like