0
$\begingroup$

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 enter image description here after enter image description here

or as gif enter image description here

$\endgroup$
1
  • $\begingroup$ 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. $\endgroup$
    – Enigmatisms
    Commented Feb 26 at 2:00

1 Answer 1

0
$\begingroup$

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
    transformGroup.Children.Add(new TranslateTransform3D(mesh.Translation.ToVector3D())); // translation

    // 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)
    );
    transformGroup.Children.Add(new RotateTransform3D(rotationQuaternion));     // rotation
    transformGroup.Children.Add(new ScaleTransform3D(mesh.Scale.ToVector3D())); // scale

    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);
}
```
$\endgroup$
1
  • $\begingroup$ thanks for replaying. but i cant find Quaternion.Rotate in the sharpdx / Numerics /media3d namespaces $\endgroup$ Commented Feb 25 at 21:13

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.