imagethree.js2dmeshtexture-mapping

How to Maintain Texture Dimensions in Three.js When Scaling Mesh?


I am working on a Three.js project where I have a mesh object with a texture applied. The texture is a PNG file with dimensions 64x64.

Problem: When the dimensions of the mesh object change, the texture gets stretched in height and width, which distorts its appearance. I want the texture to maintain its original dimensions (64x64) regardless of the mesh's size.

When the mesh is 64x64
screenshot

When the mesh is 16x07 (or anything other than NxN)
screenshot

I have tried looking into texture properties and material settings in Three.js but couldn't find a way to keep the texture dimensions fixed while scaling the mesh.

How can I prevent the texture from stretching and keep it at its original 64x64 size when the mesh dimensions change in Three.js?

Here is how the meshObject & material is created
Material Creation

function _createMaterial(url: string): THREE.MeshBasicMaterial {
    let material = new THREE.MeshBasicMaterial();

    this.loader.load(url, (texture) => {
        texture.magFilter = THREE.NearestFilter;
        texture.minFilter = THREE.LinearMipMapLinearFilter;
        material.setValues({ map: texture });
    });
    return material;
}

MeshObject Creation

this._meshObject = new Utils3.myTHREE.Mesh(geometry, material);

Solution

  • The solution provided by Łukasz D. Mastalerz also makes sense, but for my use case, I eliminated the texture approach and used sprites.

    Sprite creation:

        private static _createSprite(url: string): THREE.Sprite {
            let spriteMaterial: THREE.SpriteMaterial = null;
            let sprite: THREE.Sprite = new THREE.Sprite(); // Initialize the sprite
        
            this.loader.load(url, (texture) => {
                // Create a sprite material with the loaded texture
                spriteMaterial = new THREE.SpriteMaterial({ map: texture });
            
                // Assign the material to the sprite
                sprite.material = spriteMaterial;
        
                // Set the dimensions of the sprite
                sprite.scale.set(32, 32, 1);
        
                // Indicate that the sprite needs an update
                sprite.material.needsUpdate = true;
        
                // this.render(); // Uncomment if you need to render the scene after loading the texture
            });
        
            // Return the sprite, even if the texture is not done loading
            return sprite;
        }
    

    The line,

    // Set the dimensions of the sprite  
    sprite.scale.set(32, 32, 1);
    

    plays the important role of fitting the image inside the mesh object.

    Here is the final result
    screenshot