【问题标题】:Static Object in Scene - Three.js场景中的静态对象 - Three.js
【发布时间】:2022-03-07 14:27:22
【问题描述】:

我的场景中有两个对象。我正在使用

 <script src="js/controls/LeapTrackballControls.js"  ></script>

用于移动相机,所以感觉就像物体随着我手的移动而旋转。

问题是另一个物体也在移动,我希望它始终保持在我面前。我的意思是,即使相机移动,对象总是在画布/资源管理器内的同一位置。

对不起,如果我没有正确解释自己。

感谢任何帮助。

编辑:

var controls = new THREE.LeapTrackballControls( camera , controller );

所以,我在场景中间有一个球体。我使用 LeapTrackball 库围绕场景中心移动相机。这让用户感觉球体围绕着他的中心旋转。

model = new THREE.Mesh(modelGeo, modelMat);
model.geometry.dynamic = true;
model.position.set(0, 0, 0);
scene.add(model);

我的问题是我有另一个形状:

myMesh = new THREE.Mesh(circleGeometry, material);
myMesh.position.set(0, 0, 10);
scene.add(myMesh);

这也受相机旋转的影响。我想要的是保持球体的“假旋转”,而另一个网格保持在屏幕中间(0,0,10)。

好的,这是我的相机对象。

var camera = new THREE.PerspectiveCamera(55, window.innerWidth / window.innerHeight, 0.1, 5000);

还有我的渲染函数,用于更新相机的控制/移动。

   function render() {
        controls.update();
        renderer.render(scene, camera);
        doMouse();
        if(useOrbitControls){
            orbitControls.update();
        }
    }

我正在使用 Leap 控制器,这是构建它的函数:

function leapMotion() {
                var controllerOptions = {
                    enableGestures: true
                    , background: true
            , frameEventName: 'animationFrame'
                , };

[...]

    controller.on('frame', onFrame);

基本上,这意味着 onFrame 函数在每次接收到帧时都会执行(大约每秒 60 个)

    function onFrame(frame){
[...]
        }

仅此而已,所有魔法都来自您可以在此处找到的库:

https://leapmotion.github.io/Leap-Three-Camera-Controls/

【问题讨论】:

  • 嗯,您不需要 静态 对象,因为根据您的说法,您的对象已经在固定位置。如果您移动相机,当然两个物体都会移动(虽然这是您的 POV 移动),您应该实际旋转物体或用相机移动固定物体,如果您发布更多代码,我可以帮助您。
  • @Sosdoc 已编辑!你还需要什么吗?
  • 多一点代码(你的相机对象,requestAninationFrame 函数)会有所帮助,如果你能放一个 jsfiddle 或其他东西会更好。

标签: javascript 3d three.js leap-motion


【解决方案1】:

如果您希望将某个对象(例如十字准线)固定在相机前面,可以通过将该对象添加为相机的子对象来实现。使用这样的模式:

scene.add( camera ); // required when the camera has a child
camera.add( object );
object.position.set( 0, 0, - 100 ); // or whatever distance you want

three.js r.71

【讨论】:

  • 这很完美!我喜欢它没有在渲染函数中声明。
【解决方案2】:

这样做的简单方法是让您的对象跟踪相机的位置。

跟踪意味着,在每次相机更新时,您将相机和对象移动相同的量,同时保持它们之间的固定距离。

为此,您需要设置一个固定位置,在该位置始终可以查看您的对象,在您的示例中它应该是 (0, 0, 10)。

var fixedPosition = new THREE.Vector3(0, 0, 10);

然后,在您的 render() 函数中,您需要在移动相机之后,但在渲染所有内容之前更新对象的位置。

function render() {
        controls.update();

        // let's update the object's position now!
        myMesh.position.sub(camera.position, fixedPosition);
        // now camera and mesh are at the same distance
        renderer.render(scene, camera);
        //...
    }

在这种情况下,矢量减法可以正常工作,我们基本上取相机的位置,减去我们的固定量(Z 轴上的 10),然后您的对象的位置将 始终位于 Z 轴上距离相机 10 个单位的位置

一般来说,您将要进行的许多运算都涉及 3D 矢量和一些数学运算,因此了解这些运算(基本的加法、减法、乘法等)如何影响您在屏幕上看到的内容会很有帮助。

如果您有更多疑问,我建议您阅读一些有关矢量数学的内容,这并不难,并且您不需要记住公式(Three.js 已经实现了您需要的所有数学),但了解这些操作的作用会非常有用。

【讨论】:

  • 这也很好用,但我认为@WestLangley 的回答要容易一些,因为它不需要在每次更新中额外调用。
  • 是的,这是更好的选择,因为三个允许您附加子对象。如果那是不可能的(比如如果你直接使用 webgl),你唯一的选择就是像我一样自己操纵对象的位置。
  • 看起来 sub 方法需要 1 个参数,而不是 2 个。
【解决方案3】:

希望这对使用@react-three/fiber的人有所帮助

import {useFrame, useThree} from "@react-three/fiber";

const { gl } = useThree();

const [ vrEnabled, setVREnabled ] = useState(false);

useFrame(({camera}) => {
    setVREnabled(gl.xr.isPresenting);

    if (vrEnabled) {
        camera.add(ref.current);
        ref.current.position.set( 18, 0, 0 );
    }
});

【讨论】:

    猜你喜欢
    • 2017-07-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-02-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-03-03
    相关资源
    最近更新 更多