正弦波动画未在预期的原点发生

时间:2015-12-16 00:29:20

标签: javascript animation math three.js logic

我正在玩three.js并尝试创建一个正弦波动画,该动画源自用鼠标点击飞机的点。事实是,波纹的起源并不是你点击它的确切位置 - 它似乎总是来自飞机的中间,虽然点击飞机的最远区域确实似乎以某种方式改变了波浪。

数学从来就不是我的力量,所以我确定它是某种逻辑问题!

代码:

<!DOCTYPE html>
<html>
    <head>
        <meta http-equiv="Content-Type" content="text/html" charset="utf-8" />
    </head>
    <body>
    </body>
    <script src="three.min.js"></script>
    <script type="text/javascript" src="//ajax.googleapis.com/ajax/libs/jquery/1.11.2/jquery.min.js"></script>
    <script>
        var scene = new THREE.Scene();
        var camera = new THREE.PerspectiveCamera(75, window.innerWidth/window.innerHeight, 0.1, 10000);
        var renderer = new THREE.WebGLRenderer();
        renderer.setClearColor(0x17293a);
        renderer.setSize(window.innerWidth, window.innerHeight);
        document.body.appendChild(renderer.domElement);
        var mouse = new THREE.Vector3();

        var planeGeometry = new THREE.PlaneGeometry(200, 100, 50, 50);
        var planeMaterial = new THREE.MeshLambertMaterial({color: 0xEF3523, wireframe: true});
        var plane = new THREE.Mesh(planeGeometry, planeMaterial);
        plane.geometry.dynamic = true;
        plane.position.set(0, 0, 0);
        plane.rotation.x = -0.5 * Math.PI;
        scene.add(plane);
        camera.position.set(0, 90, 100);
        camera.lookAt(scene.position);

        var raycaster = new THREE.Raycaster();

        var checkMousePos = function() {
            mouse.x = ( event.clientX / window.innerWidth ) * 2 - 1;
            mouse.y = - ( event.clientY / window.innerHeight ) * 2 + 1;
            raycaster.setFromCamera( mouse, camera );   
            var intersects = raycaster.intersectObjects( scene.children );
                console.log(intersects.length);
                if (intersects.length > 0) {
                    var wave = {};
                    wave.x = intersects[0].point.x;
                    wave.y = intersects[0].point.y;
                    wave.z = intersects[0].point.z;
                    drawWave(wave);
                }
        };

        drawWave = function(wave){
            var center = new THREE.Vector3(wave.x, wave.y, wave.z);
            var anim = function(ts) {
                requestAnimationFrame(anim);
                var vLength = plane.geometry.vertices.length;
                for (var i = 0; i < vLength; i++) {
                    var v = plane.geometry.vertices[i];
                    var dist = new THREE.Vector3(v.x, v.y, v.z).sub(center);
                    var size = 5.0;
                    var magnitude = 4;
                    v.z = Math.sin(dist.length()/-size + (ts/500)) * magnitude;
                }
                plane.geometry.verticesNeedUpdate = true;
                renderer.render(scene, camera);             
            }
            anim();
        };

        $(document).on('click', function(e) {
            checkMousePos();
        });


        var render = function() {
            requestAnimationFrame(render);
            renderer.render(scene, camera);
        };
        render();
    </script>
</html>

JSfiddle:https://jsfiddle.net/dwo3kvLp/

2 个答案:

答案 0 :(得分:1)

在创建中心向量时,似乎需要交换y轴和z轴:

var center = new THREE.Vector3(wave.x, -wave.z, wave.y);

这似乎是因为飞机在这里旋转:

plane.rotation.x = -0.5 * Math.PI;

https://jsfiddle.net/dwo3kvLp/3/

答案 1 :(得分:1)

如果您移除旋转平面的线(plane.rotation.x = -0.5 * Math.PI;),您会注意到它的工作正常。

所以旋转后的x,y和z坐标必然意味着你会直觉地认为那些方向只是从它看起来(并且他们绝对 don&#39 ; t表示与用户点击时捕获的x和y相同的方向。发生的是你的y和z坐标是为了引用旧的方向而实现的。

如果您添加console.log语句,则在调用wave.xwave.ywave.z值之后立即打印出来drawWave(wave) 1}},然后打开控制台并点击一下,你应该看到问题。 (您可以在JSFiddle页面上执行此操作)

事实证明,当你将点分配到checkMousePos底部的波浪时,看起来像是#34; y&#34; (&#34;前进后退&#34;)由&#34; z&#34;并保持基本恒定加上或减去波浪的高度。这就是为什么波浪起源总是在中心(向前 - 向后)但是左右移动就好了。

所以,你需要做的就是改变这些方面:

wave.y = intersects[0].point.y;
wave.z = intersects[0].point.z;

wave.y = intersects[0].point.z * -1;
wave.z = intersects[0].point.y;

它应该有效。

完整更新的代码:

var scene = new THREE.Scene();
var camera = new THREE.PerspectiveCamera(75,
    window.innerWidth/window.innerHeight, 0.1, 10000);
var renderer = new THREE.WebGLRenderer();
renderer.setClearColor(0x17293a);
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement);
var mouse = new THREE.Vector3();

var planeGeometry = new THREE.PlaneGeometry(200, 100, 50, 50);
var planeMaterial = new THREE.MeshLambertMaterial({color: 0xEF3523, wireframe: true});
var plane = new THREE.Mesh(planeGeometry, planeMaterial);
plane.geometry.dynamic = true;
plane.position.set(0, 0, 0);
plane.rotation.x = -0.5 * Math.PI;
scene.add(plane);
camera.position.set(0, 90, 100);
camera.lookAt(scene.position);

var raycaster = new THREE.Raycaster();

var checkMousePos = function() {
  mouse.x = ( event.clientX / window.innerWidth ) * 2 - 1;
  mouse.y = - ( event.clientY / window.innerHeight ) * 2 + 1;
  raycaster.setFromCamera( mouse, camera ); 
  var intersects = raycaster.intersectObjects( scene.children );
  console.log(intersects.length);
  if (intersects.length > 0) {
    var wave = {};
    wave.x = intersects[0].point.x;
    wave.y = intersects[0].point.z * -1;
    wave.z = intersects[0].point.y;
    drawWave(wave);
  }
};

drawWave = function(wave){
  var center = new THREE.Vector3(wave.x, wave.y, wave.z);
  var anim = function(ts) {
    requestAnimationFrame(anim);
    var vLength = plane.geometry.vertices.length;
    for (var i = 0; i < vLength; i++) {
      var v = plane.geometry.vertices[i];
      var dist = new THREE.Vector3(v.x, v.y, v.z).sub(center);
      var size = 5.0;
      var magnitude = 4;
      v.z = Math.sin(dist.length()/-size + (ts/500)) * magnitude;
    }
    plane.geometry.verticesNeedUpdate = true;
    renderer.render(scene, camera);             
  }
  anim();
};

$(document).on('click', function(e) {
  checkMousePos();
});


var render = function() {
  requestAnimationFrame(render);
  renderer.render(scene, camera);
};
render();