How to Map Pre-defined Texture Areas on a 3D Mesh Using Fabric.js for T-shirt Customization

Hello everyone,

I’m working on a T-shirt customizer where users can personalize different parts of a T-shirt (e.g., front, back, sleeves) using Fabric.js. My goal is to have specific areas on the 2D canvas in Fabric.js correspond exactly to the pre-defined texture areas on a 3D T-shirt model.
For example.

The 3D model of the T-shirt is rendered using Three.js, and I’m struggling with how to accurately map the 2D canvas areas (created in Fabric.js) to the corresponding parts of the 3D mesh. Specifically, I need guidance on:

  1. Creating the Pre-defined Areas: How can I define these areas on the 3D model and translate them accurately onto the Fabric.js canvas?
  2. UV Mapping Considerations: Are there specific UV mapping techniques or tools I should use to ensure that the texture from the Fabric.js canvas aligns perfectly with the 3D model?

Thanks in advance!

If you don’t mind some stretching, you can generate UVs for front projection pretty easily, by just copying/scaling the vertices x/y into the uv attribute of the geometry.
smth like:

mesh.geometry.computeBoundingBox();
let box = mesh.goemetry.box;
let size = box.getSize(new THREE.Vector3());
let pa=mesh.geometry.attributes.position.array;

let uva=mesh.geometry.attributes.uv.array;
let v = new THREE.Vector3();
for(let i=0,j=0;i<pa.length;i+=3,j+=2){
  v.set(pa[i],pa[i+1],pa[i+2]);
  v.sub(box.min);
  v.muliplyScalar(size);
//write out the 2 axis we want to project on... for front projection this might be x and y
 uva[j] = v.x;
 uva[j+1] = v.y;
}
mesh.geometry.attributes.uv.needsUpdate = true; //Mark it for update in case its already been updated

Do do a higher quality mapping, you would use a tool like blender to manually unwrap the UVs in a pleasing way that matches your fabricjs 2d template, and just import that modified mapping.
Another option / approach more independent of UV mapping is to use decal splatting:
https://threejs.org/examples/webgl_decals.html
But this is more complex.