最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - Scaling a Three.js geometry only up - Stack Overflow

programmeradmin3浏览0评论

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
Add a comment  | 

3 Answers 3

Reset to default 11

If 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 to height * 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;

}
发布评论

评论列表(0)

  1. 暂无评论