【问题标题】:Three.js First Person ControlsThree.js 第一人称控制
【发布时间】:2012-09-12 03:01:05
【问题描述】:

我正在使用 Three.js 和 WebGL,无法完全按照我想要的方式获得控件。由于 Three.js 的 FirstPersonControls 不使用指针锁定,因此我选择尝试“滚动我自己的”控件。

无论如何,我从内置的 FirstPersonControls 中获取了大部分代码,将其转换为使用指针锁定(movementX 而不是 pageX - offset),但我无法平滑外观运动。

这是我的onMouseMove(使用originalEvent,因为它是一个jquery事件):

onMouseMove: function(e) {
    if(!document.pointerLockElement) return;

    var moveX = e.originalEvent.movementX       ||
                    e.originalEvent.mozMovementX    ||
                    e.originalEvent.webkitMovementX ||
                    0,
        moveY = e.originalEvent.movementY       ||
                    e.originalEvent.mozMovementY    ||
                    e.originalEvent.webkitMovementY ||
                    0;

    //Update the mouse movement for coming frames
    this.mouseMovementX = moveX;
    this.mouseMovementY = moveY;
}

还有我的Controls.update()(在每个动画帧上调用,带有THREE.Clock delta):

update: function(delta) {            
    if(this.freeze) {
        return;
    }

    //movement, works fine
    if(this.moveForward) this.camera.translateZ(-(actualMoveSpeed + this.autoSpeedFactor));
    if(this.moveBackward) this.camera.translateZ(actualMoveSpeed);

    if(this.moveLeft) this.camera.translateX(-actualMoveSpeed);
    if(this.moveRight) this.camera.translateX(actualMoveSpeed);

    /////////
    //ISSUES ARE WITH THIS CODE:
    /////////
    //look movement, really jumpy
    this.lon += this.mouseMovementX;
    this.lat -= this.mouseMovementY;

    this.lat = Math.max(-85, Math.min(85, this.lat));
    this.phi = (90 - this.lat) * Math.PI / 180;
    this.theta = this.lon * Math.PI / 180;

    this.target.x = this.camera.position.x + 100 * Math.sin(this.phi) * Math.cos(this.theta);
    this.target.y = this.camera.position.y + 100 * Math.cos(this.phi);
    this.target.z = this.camera.position.z + 100 * Math.sin(this.phi) * Math.sin(this.theta);

    this.camera.lookAt(this.target);
}

此代码确实有效,但是随着鼠标的移动,移动相机会变得很跳跃。我真的可以使用一些帮助来弄清楚如何平滑它。

你可以明白我所说的“跳跃”here 是什么意思。我是 Three.js、WebGL 和一般 3D 的新手,因此不胜感激。

谢谢,

-乍得


编辑在使用@przemo_li 之后,这是他想出的工作代码:

onMouseMove: function(e) {
    if(!document.pointerLockElement) return;

    var moveX = e.originalEvent.movementX       ||
                    e.originalEvent.mozMovementX    ||
                    e.originalEvent.webkitMovementX ||
                    0,
        moveY = e.originalEvent.movementY       ||
                    e.originalEvent.mozMovementY    ||
                    e.originalEvent.webkitMovementY ||
                    0;

    //Update the initial coords on mouse move
    this.mouseMovementX += moveX; //aggregate mouse movements as a total delta delta
    this.mouseMovementY += moveY;
},
update: function(delta) {            
    if(this.freeze) {
        return;
    }

    //movement
    if(this.moveForward) this.camera.translateZ(-(actualMoveSpeed + this.autoSpeedFactor));
    if(this.moveBackward) this.camera.translateZ(actualMoveSpeed);

    if(this.moveLeft) this.camera.translateX(-actualMoveSpeed);
    if(this.moveRight) this.camera.translateX(actualMoveSpeed);

    //look movement
    this.lon += this.mouseMovementX;
    this.lat -= this.mouseMovementY;

    this.mouseMovementX = 0; //reset mouse deltas to 0 each rendered frame
    this.mouseMovementY = 0;

    this.phi = (90 - this.lat) * Math.PI / 180;
    this.theta = this.lon * Math.PI / 180;

    if(this.constrainVertical) {
        this.phi = THREE.Math.mapLinear(this.phi, 0, Math.PI, this.verticalMin, this.verticalMax);
    }

    this.target.x = this.camera.position.x + 100 * Math.sin(this.phi) * Math.cos(this.theta);
    this.target.y = this.camera.position.y + 100 * Math.cos(this.phi);
    this.target.z = this.camera.position.z + 100 * Math.sin(this.phi) * Math.sin(this.theta);

    this.camera.lookAt(this.target);
}

【问题讨论】:

  • 你能获得多少 FPS?
  • @przemo_li 这绝对不是 FPS 问题,我得到了 60FPS,就像我提到的运动工作正常。如果我在它周围 WASD,它会非常顺利。我只需要用鼠标做大的手势来产生不连贯的动作。我显然只是没有得到正确计算所需的数学知识。
  • mouseMovementX/Y 在极端情况下会采取什么范围?
  • 看起来极值在+-200 范围内。尽管它们可以低至+-1 甚至0(没有移动)。
  • 嗯。阅读文档并检查什么是最大值。比将鼠标移动输入缩放到您的纬度和经度范围。也许这就是原因。或者它可能只是当前隐藏的另一个问题;)

标签: javascript 3d webgl three.js


【解决方案1】:

1) 约束? 在您的代码中,您将鼠标 X 移动限制为 -|+ 85 不太可能需要这种约束。

2) 聚合帧期间发生的所有事件 在您的代码中,您使用每个新事件覆盖鼠标移动。因此,如果您在帧期间收到 3 个事件,则只会存储最近的事件。

添加这些动作。比渲染帧后可以清除计数。然后重新开始收集活动。

【讨论】:

    【解决方案2】:
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-06-16
    • 1970-01-01
    • 2014-03-16
    • 2012-11-03
    相关资源
    最近更新 更多