anon
anon

Reputation: 634

THREE.js Image aspect ratio

I am having trouble figuring out how to set a PlaneGeometry to a good aspect ratio based on the image size.

var material = new THREE.MeshBasicMaterial({
        map : THREE.ImageUtils.loadTexture('img/bunny.png')
});
var plane = new THREE.Mesh(new THREE.PlaneGeometry(20, 20*.75), material);
plane.position.set(0, 10, -60)
scene.add(plane);

What I've tried so far sort of works, but I realise I'm still setting a fixed width/height on the Plane.

I'd like the plane to set the size of the image, then I could scale it down.

Upvotes: 3

Views: 6138

Answers (2)

Pierre Monico
Pierre Monico

Reputation: 1100

The accepted answer works but has to use the callback to set the width since the loader is asynchronous. Nowadays one can also use the loadAsync method, which IMO makes the code more readable:

const getImageRatioPlane = async () => {
    const texture = await new TextureLoader().loadAsync(imgSrc);
    const material = new MeshBasicMaterial({ map: texture });
    const geometry = new PlaneGeometry(texture.image.width, texture.image.height);

    const plane = new Mesh(geometry, material);
}

Upvotes: 0

manthrax
manthrax

Reputation: 5016

var planeGeom = new THREE.PlaneGeometry(20, 20);
var imgSrc = "https://upload.wikimedia.org/wikipedia/commons/5/5f/BBB-Bunny.png"
var mesh;
var tex = new THREE.TextureLoader().load(imgSrc, (tex) => {
  tex.needsUpdate = true;
  mesh.scale.set(1.0, tex.image.height / tex.image.width, 1.0);
});

var material = new THREE.MeshLambertMaterial({
  color: 0xffffff,
  map: tex
});
mesh = new THREE.Mesh(planeGeom, material);
scene.add(mesh);

//Working snippet is below...

var renderer = new THREE.WebGLRenderer();
var w = 300;
var h = 200;
renderer.setSize(w, h);
document.body.appendChild(renderer.domElement);

var scene = new THREE.Scene();
var camera = new THREE.PerspectiveCamera(
  45, // Field of view
  w / h, // Aspect ratio
  0.1, // Near
  10000 // Far
);
camera.position.set(15, 10, 15);
camera.lookAt(scene.position);
controls = new THREE.OrbitControls(camera, renderer.domElement);

var light = new THREE.PointLight(0xFFFFFF);
light.position.set(20, 20, 20);
scene.add(light);
var light1 = new THREE.AmbientLight(0x808080);
light1.position.set(20, 20, 20);
scene.add(light1);

var planeGeom = new THREE.PlaneGeometry(20, 20);
var imgSrc = "https://upload.wikimedia.org/wikipedia/commons/5/5f/BBB-Bunny.png"
var mesh;
var tex = new THREE.TextureLoader().load(imgSrc, (tex) => {
  tex.needsUpdate = true;
  mesh.scale.set(1.0, tex.image.height / tex.image.width, 1.0);
});

var material = new THREE.MeshLambertMaterial({
  color: 0xffffff,
  map: tex
});
mesh = new THREE.Mesh(planeGeom, material);
scene.add(mesh);
renderer.setClearColor(0xdddddd, 1);


(function animate() {
  requestAnimationFrame(animate);
  controls.update();
  renderer.render(scene, camera);
})();
<script src="https://threejs.org/build/three.min.js"></script>
<script src="https://cdn.rawgit.com/mrdoob/three.js/master/examples/js/controls/OrbitControls.js"></script>

Upvotes: 7

Related Questions