Sunday, 18 July 2021

3D model in HTML/CSS; Calculate Euler rotation of triangle

TLDR; Given a set of triangle vertices and a normal vector (all in unit space), how do I calculate X, Y, Z Euler rotation angles of the triangle in world space?

I am attemping to display a 3D model in HTML - with actual HTML tags and CSS transforms. I've already loaded an OBJ file into a Javascript class instance.

The model is triangulated. My first aim is just to display the triangles as planes (HTML elements are rectangular) - I'll be 'cutting out' the triangle shapes with CSS clip-path later on.

I am really struggling to understand and get the triangles of the model rotated correctly.

I thought a rotation matrix could help me out, but my only experience with those is where I already have the rotation vector and I need to convert and send that to WebGL. This time there is no WebGL (or tutorials) to make things easier.

The following excerpt shows the face creation/'rendering' of faces. I'm using the face normal as the rotation but I know this is wrong.

for (const face of _obj.faces) {

  const vertices = face.vertices.map(_index => _obj.vertices[_index]);

  const center = [
    (vertices[0][0] + vertices[1][0] + vertices[2][0]) / 3,
    (vertices[0][1] + vertices[1][1] + vertices[2][1]) / 3,
    (vertices[0][2] + vertices[1][2] + vertices[2][2]) / 3
  ];

  // Each vertex has a normal but I am just picking the first vertex' normal
  // to use as the 'face normal'.

  const normals = face.normals.map(_index => _obj.normals[_index]);
  const normal = normals[0];

  // HTML element creation code goes here; reference is 'element'.

  // Set face position (unit space)

  element.style.setProperty('--posX', center[0]);
  element.style.setProperty('--posY', center[1]);
  element.style.setProperty('--posZ', center[2]);

  // Set face rotation, converting to degrees also.

  const rotation = [
    normal[0] * toDeg,
    normal[1] * toDeg,
    normal[2] * toDeg,
  ];

  element.style.setProperty('--rotX', rotation[0]);
  element.style.setProperty('--rotY', rotation[1]);
  element.style.setProperty('--rotZ', rotation[2]);
}

The CSS first translates the face on X,Y,Z, then rotates it on X,Y,Z in that order.

I think I need to 'decompose' my triangles' rotation into separate axis rotations - i.e rotate on X, then on Y, then on Z to get the correct rotation as per the model face.

I realise that the normal vector gives me an orientation but not a rotation around itself - I need to calculate that. I think I have to determine a vector along one triangle side and cross it with the normal, but this is something I am not clear on.

I have spent hours looking at similar questions on SO but I'm not smart enough to understand or make them work for me.

Is it possible to describe what steps to take without Latex equations? I'm good with pseudo code but my Math skills are severely lacking.

The full code is here: https://whoshotdk.co.uk/cssfps/ (view HTML source) The mesh building function is at line 422.

The OBJ file is here: https://whoshotdk.co.uk/cssfps/data/model/test.obj The Blender file is here: https://whoshotdk.co.uk/cssfps/data/model/test.blend

The mesh is just a single plane at an angle, displayed in my example (wrongly) in pink.

The world is setup so that -X is left, -Y is up, -Z is into the screen.

Thank You!



from 3D model in HTML/CSS; Calculate Euler rotation of triangle

No comments:

Post a Comment