# How apply 3d transformations on 3d Mesh vertcies

I have This 3D mesh class , I use helixToolKit SharpDX to display the mesh and transformations , but i want to apply these transformations to the vertcies dirctly so the mesh can be exported with these transformations . how to do that ?

    using HelixToolkit.SharpDX.Core;
using SharpDX;
using System.Windows.Media.Media3D;

public class Vertex
{
public Vector3 Position { get; set; }
public Vector3 Normal { get; set; }
public int NormalW { get; set; }
public List<Vector3> UVs { get; set; }
public List<Vector4> Tangents { get; set; }
public Vector4 Bitangent { get; set; }
public List<VertexColor> Colors { get; set; }
}

public class Mesh
{

public Vector3 Translation { get; set; }

public Vector3 Rotation { get; set; } //radian values of Euler angels

public Vector3 Scale { get; set; }

public List<Vertex> Vertices { get; set; }

public List<int> Indices { get; set; }

public Transform3D Transform
{
get => new MatrixTransform3D(this.GetTransformMatrix().ToMatrix3D());
}

}


Following Enigmatisms answer and using SharpDX Namespace

it should be something like this

public static void ApplyTransformations(this MeshNodeViewModel mesh)
{
//Obtain the total transformations
var tm = SharpMatrix.Translation(mesh.Translation);
var sm = SharpMatrix.Scaling(mesh.Scale);
var rxm = SharpMatrix.RotationX(mesh.Rotation.X);
var rym = SharpMatrix.RotationY(mesh.Rotation.Y);
var rzm = SharpMatrix.RotationZ(mesh.Rotation.Z);
// Apply the transformations in the SRT order
var transformations = sm * (rxm * (rzm * (rym * tm)));

//Obtain the total rotations
SharpQuaternion rotationQuaternion = SharpQuaternion.RotationMatrix(rxm * rzm * rym);

List<MyVertex> vertices = new List<MyVertex>(mesh.Vertices);
foreach (var vertex in vertices)
{
// transform vertex position
SharpVector3 pos = vertex.Position;
SharpVector3.Transform(ref pos, ref transformations, out SharpVector3 newPos);

vertex.Position = newPos;

// transform normals
vertex.Normal = TransformVector3(vertex.Normal, rotationQuaternion);

// transform tangents (the w field is not accounted for)
for (int i = 0; i < vertex.Tangents.Count; i++)
{
vertex.Tangents[i] = TransformVector4(
vertex.Tangents[i].ToSharp4(),
rotationQuaternion
)
.ToNumerics();
}

// transform bi-tangents (the w field is not accounted for)
vertex.Bitangent = TransformVector4(vertex.Bitangent.ToSharp4(), rotationQuaternion)
.ToNumerics();
}

mesh.Vertices = vertices;
//Clear Transformations
mesh.Translation = SharpVector3.Zero;
mesh.Rotation = SharpVector3.Zero;
mesh.Scale = SharpVector3.One;
}

public static SharpVector3 TransformVector3(
SharpVector3 vector,
SharpQuaternion rotationQuaternion
)
{
Vector3D vector3D = new Vector3D(vector.X, vector.Y, vector.Z);
SharpVector3.Transform(
ref vector,
ref rotationQuaternion,
out SharpVector3 rotatedVector3D
);
return new SharpVector3(
(float)rotatedVector3D.X,
(float)rotatedVector3D.Y,
(float)rotatedVector3D.Z
);
}

public static SharpVector4 TransformVector4(
SharpVector4 vector,
SharpQuaternion rotationQuaternion
)
{
SharpVector3 vector3 = new SharpVector3(vector.X, vector.Y, vector.Z); // extract
SharpVector3.Transform(
ref vector3,
ref rotationQuaternion,
out SharpVector3 rotatedVector3D
);
return new SharpVector4(
(float)rotatedVector3D.X,
(float)rotatedVector3D.Y,
(float)rotatedVector3D.Z,
vector.W
);
}


however the normals/Light reflection would change a little after appling the transformations, But this will only happens if a scale is applied . Is this supposed to happen ?

before after

or as gif

• Ok, I omitted one thing, I didn't notice that your Scale is of type Vector3. For uniform scaling, we can only apply rotation to the normal, tangents and bitangents, yet if is scaling is non-uniform, all these fields can't just be transformed by rotation. See this article for how to resolve this problem. Commented Feb 26 at 2:00

Maybe you can try the the following code, I haven't used this for a while so usability is not guaranteed. Let's approach this in the most intuitive way (maybe there is some other API that can do the job but I simply can't recall). Essentially, you need to transform the position of each vertex, given translation, rotation and scaling factor. However, do not forget to transform the normal vector, tangents and bi-tangents (assume they are all in the same global coordinate frame). Note that the last field of tangents (and bitangents) should be preserved.

using HelixToolkit.Wpf;

public void ApplyTransformationsToVertices(Mesh3D mesh) {
Transform3DGroup transformGroup = new Transform3DGroup();       // translation, rotation, and scale all at once

// I don't know a way to directly transform from Euler angle to Quaternion or Rotation Matrix
Quaternion rotationQuaternion = new QuaternionRotation3D(
new Quaternion(new Vector3D(1, 0, 0), mesh.Rotation.X) *
new Quaternion(new Vector3D(0, 1, 0), mesh.Rotation.Y) *
new Quaternion(new Vector3D(0, 0, 1), mesh.Rotation.Z)
);

foreach (var vertex in mesh.Vertices) {
Point3D vertexPosition = new Point3D(vertex.Position.X, vertex.Position.Y, vertex.Position.Z);

// transform vertex position
Point3D transformedVertexPosition = transformGroup.Transform(vertexPosition);
vertex.Position = transformedVertexPosition.ToVector3();

// transform normals
vertex.Normal = TransformVector3d(vertex.Normal, rotationQuaternion);

// transform tangents (the w field is not accounted for)
for (int i = 0; i < vertex.Tangents.Count; i++) {
vertex.Tangents[i] = TransformVector3d(vertex.Tangents[i], rotationQuaternion);
}

// transform bi-tangents (the w field is not accounted for)
vertex.Bitangent = TransformVector3d(vertex.Bitangent, rotationQuaternion);
}
}

public Vector3 TransformVector3d(Vector3 vector, Quaternion rotationQuaternion) {
Vector3D vector3D = new Vector3D(vector.X, vector.Y, vector.Z);
Vector3D rotatedVector3D = rotationQuaternion.Rotate(vector3D);
return new Vector3((float)rotatedVector3D.X, (float)rotatedVector3D.Y, (float)rotatedVector3D.Z);
}

public Vector3 TransformVector4d(Vector4 vector, Quaternion rotationQuaternion) {
Vector3 vector3 = new Vector3(vector.X, vector.Y, vector.Z);        // extract
Vector3D vector3D = new Vector3D(vector3.X, vector3.Y, vector3.Z);
Vector3D rotatedVector3D = rotationQuaternion.Rotate(vector3D);
return new Vector4((float)rotatedVector3D.X, (float)rotatedVector3D.Y, (float)rotatedVector3D.Z, vector.W);
}
$$$$
`
• thanks for replaying. but i cant find Quaternion.Rotate in the sharpdx / Numerics /media3d namespaces Commented Feb 25 at 21:13