I'm trying to scale the geometries y-axis. This made my cube scale both up and down. I think mesh.transformY works to animate the cube up half of the scaling value. This would make it look like the cube just scaled upwards. Are there other solutions for this?
var geometry = new THREE.BoxGeometry(1, 1, 1);
var mesh = new THREE.Mesh(geometry, new THREE.MeshPhongMaterial({
color: 0xffffff
}));
mesh.position.set(0, 2, 0);
mesh.scale.set(0.98, 0.95, 0.992);
mesh.castShadow = true;
scene.add(mesh);
var tween = new TWEEN.Tween(mesh.scale)tween.to({y: 2}, 1000)
tween.easing(TWEEN.Easing.Elastic.InOut);
tween.yoyo(true);
tween.start();
I'm trying to scale the geometries y-axis. This made my cube scale both up and down. I think mesh.transformY works to animate the cube up half of the scaling value. This would make it look like the cube just scaled upwards. Are there other solutions for this?
var geometry = new THREE.BoxGeometry(1, 1, 1);
var mesh = new THREE.Mesh(geometry, new THREE.MeshPhongMaterial({
color: 0xffffff
}));
mesh.position.set(0, 2, 0);
mesh.scale.set(0.98, 0.95, 0.992);
mesh.castShadow = true;
scene.add(mesh);
var tween = new TWEEN.Tween(mesh.scale)tween.to({y: 2}, 1000)
tween.easing(TWEEN.Easing.Elastic.InOut);
tween.yoyo(true);
tween.start();
Share
Improve this question
asked Oct 31, 2015 at 18:11
Alexander HeinAlexander Hein
9903 gold badges20 silver badges44 bronze badges
1
- 2 This is because 3D object positions in Three.js are at the center of the object. So if you wish to "scale upwards" you will need to move the object up while also scaling it. Though there may be an easier way to achieve what you want. – EvilZebra Commented Oct 31, 2015 at 18:28
3 Answers
Reset to default 11If you want your geometry to scale only "up", all you need to do is make sure the "bottom" of your geometry passes through the origin. In your case, you can use the translate()
method like so:
var geometry = new THREE.BoxGeometry( 1, 1, 1 );
geometry.translate( 0, 0.5, 0 );
var tween = new TWEEN.Tween( mesh.scale ).to( { y: 2 }, 1000 );
tween.start();
The bottom of the box will remain fixed, and the box's height will change.
three.js r.73
The usual case of your question is something on a 'ground', like a 'person' mesh, that shall always have its feet on the ground whatever its size. There are two ways for that.
The way Evilzebra proposed in the comment. Based on the height of your mesh you can implement it easily : as you wrote, when scaling in
y
, the mesh will get half taller both on top and bottom. So you just have to move its position toheight * scale / 2
:function scaleY ( mesh, scale ) { mesh.scale.y = scale ; if( ! mesh.geometry.boundingBox ) mesh.geometry.computeBoundingBox(); var height = mesh.geometry.boundingBox.max.y - mesh.geometry.boundingBox.min.y; //height is here the native height of the geometry //that does not change with scaling. //So we need to multiply with scale again mesh.position.y = height * scale / 2 ; }
Another way is to move the origin of the coordinates (local space) at the bottom of the geometry, so the position is not changed. For that you have to move the origin of the geometry to the lowest
y
coordinate. You will then be able to change your scale at will with the native ThreeJS method :function originToBottom ( geometry ) { //1. Find the lowest `y` coordinate var shift = geometry.boundingBox ? geometry.boundingBox.min.y : geometry.computeBoundingBox().min.y; //2. Then you translate all your vertices up //so the vertical origin is the bottom of the feet : for ( var i = 0 ; i < geometry.vertices.length ; i++ ) { geometry.vertices[ i ].y -= shift; } //or as threejs implements (WestLangley's answer) : geometry.translate( 0, -shift, 0); //finally geometry.verticesNeedUpdate = true; }
Since this is, in my case, the first item on Google on how to scale a geometry I'll post my function to alter a geometry.
function _alterGeometry(geometry, opt) {
var toAlter = [];
var matrixMultiplier = function (mtx) {
var matrix = new THREE.Matrix4();
mtx.forEach(function (m, index) {
matrix = new THREE.Matrix4().multiplyMatrices(matrix, m);
});
return matrix;
};
if (opt.position)
toAlter.push(new THREE.Matrix4().setPosition(new THREE.Vector3(opt.position.x, opt.position.y, opt.position.z)));
if (opt.rotation && opt.rotation.x)
toAlter.push(new THREE.Matrix4().makeRotationAxis(new THREE.Vector3(1, 0, 0), opt.rotation.x));
if (opt.rotation && opt.rotation.y)
toAlter.push(new THREE.Matrix4().makeRotationAxis(new THREE.Vector3(0, 1, 0), opt.rotation.y));
if (opt.rotation && opt.rotation.z)
toAlter.push(new THREE.Matrix4().makeRotationAxis(new THREE.Vector3(0, 0, 1), opt.rotation.z));
if (opt.scale)
toAlter.push(new THREE.Matrix4().scale(opt.scale));
geometry.applyMatrix(matrixMultiplier(toAlter));
return geometry;
}