How can I shear/skew a mesh (not the geometry directly)?

This answer from West Langley shows how to apply a shear matrix to a geometry, but this comment from him explains that the same matrix can not be applied to a Mesh, but only to a Mesh’s geometry.

How can we apply shear to an Object3D, not a geometry, without losing the convenience of rotation, position, scale, and quaternion? I’d like to be able to keep using those, if possible, but with added ability to shear.

If it’s simply not possible, then

  • How can I do it with only matrix (and taking into account wanting to also apply rotation, position, and scale to the matrix)?
  • Is there a way to patch Object3D or Matrix4 to add a shear/skew feature that can be composed from a simple prop on Object3D?

You can setup:

  • A group object that will give the position, rotation and the scale
  • The object itself, child of the group, and with the skew matrix computed manually (set .matrixAutoUpdate = false for this one) Just set the matrix manually.

That’s what I’m thinking, but it is inconvenient to modify existing tree structures of an existing app (for example). It is much easier to manipulate existing objects (without changing tree structure) and encourages separation of concerns.

Being able to apply a visual effect makes management of app code simpler and cleaner (f.e. like CSS, where style is applied to existing DOM elements without changing their structure; separation of concerns).

Sorry for late reply.

Oh, you can do a matrix with shear, position, rotation and scale in the same object. I supposed it was cleaner with the Group. Just concatenate the operations on the same matrix. BTW that’s because all those transforms are affine.

As West Langley says below the comment you linked, you will have to update the matrix by yourself and set matrixAutoUpdate = false:

// Initialization. This temporary matrix can be shared.
var rotScaleTranslation = new THREE.Matrix4();

obj.matrixAutoUpdate = false;
// On each transform change:
rotScaleTranslation.compose( obj.position, obj.quaternion, obj.scale );
object.matrix.makeShear( shearX, shearY, shearZ ).multiply( rotScaleTranslation )

As you’ve got an object hierarchy, you will need to call rootObject.updateMatrixWorld( true ), probably once each frame, after updating the matrices of objects which have shear.

A final note: Children of sheared objects will accumulate the shearing, which could be undesirable. Also their positions will be sheared, which is likely undesirable.

Alright, so basically the shear needs to be applied first, then the other stuff.

I’m wondering: why isn’t this baked into Object3D? It’d be nice not to have to convert all my code, which uses rotation, position, scale, into manual matrix manipulation. The simplicity is lost.

not every app needs shear, and you can implement it on top of three. But then, there are other things in there that not every app needs at the same time, so it’s a preference thing. Have you tried doing a PR with this?

I might just give it a go at some point. :slight_smile: