使用lineTo和curveTo在Three.js中对线进行动画处理

时间:2018-08-22 17:02:59

标签: three.js

我是Three.js新手,我来自Processing / p5.js(所以我对动画循环有点迷恋)。我正在尝试创建以下简单的拉伸药丸形状:

Stretching pill shape

这就是我从网上发现的一些东西中吸取的东西。我只是呈“ O”形。我正在尝试使变量oHeight成为引起与Math.sin来回流通的变量。

我需要更新路径吗?还是bufferGeometry?还是THREE.PATH?

抱歉,此代码太乱了。刚开始!

        var camera, scene, renderer;
        var curve;
        var path;
        var oHeight = 0;
        var delta = 0;

        init();
        animate();

        function init() {
            camera = new THREE.PerspectiveCamera( 35, window.innerWidth / window.innerHeight, 1, 1000 );
            camera.position.z = 600;
            scene = new THREE.Scene();

            path = new THREE.Path();

            path.lineTo( 0, 0 );
            path.quadraticCurveTo( 0, 20, 20, 20 );
            path.lineTo( 40, 20 );
            path.quadraticCurveTo( 60,20, 60,0);
            path.lineTo(60,-40-oHeight);
            path.quadraticCurveTo( 60,-60-oHeight, 40,-60-oHeight);
            path.lineTo(20,-60-oHeight);
            path.quadraticCurveTo(0,-60,0,-40-oHeight);
            path.lineTo(0,0);

            var points = path.getPoints();

            var geometry = new THREE.BufferGeometry().setFromPoints( points );
            var material = new THREE.LineBasicMaterial( { color: 0xffffff } );

            curve = new THREE.Line( geometry, material );

            scene.add( curve );

            renderer = new THREE.WebGLRenderer( { antialias: true } );
            renderer.setPixelRatio( window.devicePixelRatio );
            renderer.setSize( window.innerWidth, window.innerHeight );
            document.body.appendChild( renderer.domElement );
        }

        function animate() {
            requestAnimationFrame( animate );

            delta +=.1;
            oHeight = Math.sin(delta)*20;
            line.needUpdate = true; //is this where I went wrong?

            renderer.render( scene, camera );
        }

1 个答案:

答案 0 :(得分:1)

您的代码中没有对象line,也没有从对象geometryoHeight的神秘引用。 THREE.Path只是一个临时对象,其中包含创建BufferGeoemtry所需的信息。请注意,最后geometry的顶点存储在GPU上的数组缓冲区中。

您必须在animate函数中创建路径并将其设置为BufferGeoemtry。因此,在每一帧中都会重新创建几何图形:

function animate() {
    requestAnimationFrame( animate );

    delta +=.1;
    oHeight = Math.sin(delta)*20;

    path = new THREE.Path();
    path.lineTo( 0, 0 );
    path.quadraticCurveTo( 0, 20, 20, 20 );
    path.lineTo( 40, 20 );
    path.quadraticCurveTo( 60,20, 60,0);
    path.lineTo(60,-40-oHeight);
    path.quadraticCurveTo( 60,-60-oHeight, 40,-60-oHeight);
    path.lineTo(20,-60-oHeight);
    path.quadraticCurveTo(0,-60-oHeight,0,-40-oHeight);
    path.lineTo(0,0);

    geometry.dispose();
    geometry.setFromPoints( path.getPoints() );

    renderer.render( scene, camera );
}

var camera, scene, renderer;
var curve;
var path;
var oHeight = 0;
var delta = 0;
var geometry;

init();
animate();

function init() {
    camera = new THREE.PerspectiveCamera( 35, window.innerWidth / window.innerHeight, 1, 1000 );
    camera.position.z = 600;
    scene = new THREE.Scene();

    geometry = new THREE.BufferGeometry();
    var material = new THREE.LineBasicMaterial( { color: 0xffffff } );

    curve = new THREE.Line( geometry, material );

    scene.add( curve );

    renderer = new THREE.WebGLRenderer( { antialias: true } );
    renderer.setPixelRatio( window.devicePixelRatio );
    renderer.setSize( window.innerWidth, window.innerHeight );
    document.body.appendChild( renderer.domElement );

    window.onresize = resize;
}

function animate() {
    requestAnimationFrame( animate );

    delta +=.1;
    oHeight = Math.sin(delta)*20;

    path = new THREE.Path();
    path.lineTo( 0, 0 );
    path.quadraticCurveTo( 0, 20, 20, 20 );
    path.lineTo( 40, 20 );
    path.quadraticCurveTo( 60,20, 60,0);
    path.lineTo(60,-40-oHeight);
    path.quadraticCurveTo( 60,-60-oHeight, 40,-60-oHeight);
    path.lineTo(20,-60-oHeight);
    path.quadraticCurveTo(0,-60-oHeight,0,-40-oHeight);
    path.lineTo(0,0);
    
    geometry.dispose();
    geometry.setFromPoints( path.getPoints() );
    
    renderer.render( scene, camera );
}

function resize() {   
    var aspect = window.innerWidth / window.innerHeight;
    renderer.setSize(window.innerWidth, window.innerHeight);
    camera.aspect = aspect;
    camera.updateProjectionMatrix();
}
<script src="https://threejs.org/build/three.min.js"></script>