【问题标题】:Move camera in aframe with physics engine使用物理引擎在框架中移动相机
【发布时间】:2017-09-16 03:49:27
【问题描述】:

我在我的 aframe 应用程序中使用物理引擎,并且我希望相机在用户单击按钮时移动。

我想保留物理引擎属性,所以我使用 applyImpulse 作为运动方法。

这是我的示例场景:

<script src="https://aframe.io/releases/0.3.0/aframe.min.js"></script>
<script src="//cdn.rawgit.com/donmccurdy/aframe-extras/v2.3.0/dist/aframe-extras.min.js"></script>
<a-scene physics>
<!-- Camera -->
<a-entity id="cameraWrapper" geometry="box" dynamic-body="mass:1" position="0 1 0" width="2" height="1" depth="2" listener>
<a-entity id="camera" camera universal-controls position="0 1 0" rotation="0 0 0">
</a-entity>
</a-entity>
<a-grid static-body position="0 0 0"></a-grid>
</a-scene>
<div>
<a id="impulseButton">Move</a>
</div>

应该移动相机的 javascript 方法如下所示:

$(document).ready(function(){
  $("#impulseButton").on("click",function(){
    applyImpulse();
  });

function applyImpulse(){
    var x = 0;
    var y = 0;
    var z = 1;
    var el = $('#cameraWrapper')[0];
    el.body.applyImpulse(
       new CANNON.Vec3(x,y,z),
       new CANNON.Vec3().copy(el.body.position)
    );
  }
});

但是,移动似乎不是很流畅,当用户使用 WASD 控件时,cameraWrapper 实体仍保留在旧位置。如何使用 applyImpulse 平滑移动相机?

【问题讨论】:

    标签: javascript aframe webvr cannon.js


    【解决方案1】:

    universal-controls 组件是 wasd-controlslook-controls 的替代品,它与 aframe-physics-system 开箱即用兼容。这有助于防止相机穿过障碍物的关键情况,I don't recommend in VR,但对于桌面非 VR 应用程序仍然有用。

    用法:

    <a-entity camera universal-controls kinematic-body></a-entity>
    

    添加了kinematic-body 组件以检测播放器上的碰撞。这是more complete example


    注意:aframe-extras 的未来版本可能不支持kinematic-body 和相机碰撞,因此您可能会被锁定在 3.X.X 版本。不幸的是,这对于更好地支持关键的 VR 案例是必要的,例如为多人体验提供物理,并在 Web Worker 中运行物理以提高性能。

    【讨论】:

    • 它确实有效,live demo here。该演示的源代码已链接在答案中。
    • 我知道 kinematic-body 会检测碰撞,但我不明白如何将其与 applyImpulse 或任何其他移动相机的方法结合使用,以在以编程方式移动相机时检测碰撞。抱歉,如果我的问题不清楚。
    • kinematic-body 不适用于applyImpulse(),但当与universal-controls 结合使用时,它会自动检测碰撞并防止相机穿过static-bodydynamic-body 对象。
    • 换句话说,您可以要么kinematic-bodyuniversal-controls一起使用,或者您可以将dynamic-bodyapplyImpulse()一起使用。后者可能需要 100 多行代码。
    【解决方案2】:

    我认为这只是一个运动问题,所以你只需要 js/aframe。它应该看起来像这样。这只是一个快速的肮脏但应该给你的想法。你可以搜索玩家移动的东西,并会找到很多方法来做到这一点。只需将按键功能更改为按钮功能即可。

    所以对于所有类型的实体(摄像头、灯光、播放器......)来说,它会更像这样:

    this.camMove = function(){
            // delta = change in time since last call (seconds)
                delta = clock.getDelta(); 
                var mDir = 100 * delta;
                moves = false;
    
                var mButtons = ["button1", "button2", "button3"];
                for (var i = 0; i < mButtons.length; i++)
                {
                    if ( mButtons >= 0 )
                        moves = true;
                }
    
                if ( mButtons === button1 )
                    cam.translateX( mDir );
                if ( mButtons === button2 )
                    cam.translateX( -mDir );
                if ( mButtons === button3 )
                    cam.translateY( -mDir );
                    ................
                    ............
                    ........
    }
    

    clock 应该是你的 aframe 中的一个函数,但我不确定,因为我使用 three.js 来处理这样的事情。

    【讨论】:

    • translateX 和动画的问题是物理引擎无法识别它们,只有外观控件可以识别。有什么方法可以使用 applyImpulse 来执行您的建议吗?
    • 要使用物理引擎(例如碰撞),您可以将 cam.translateX 替换为 cameraEl.body.applyImpulse(..., ...)。见docs for CANNON.Body.applyImpulse()
    • @DonMcCurdy 这似乎只适用于动态体示例。您能否提供一个示例,例如使用矢量 0,0,1 来移动运动体相机实体,就像我的问题一样?
    • @bear 正确,您不能对运动体施加脉冲。您可以将动态主体附加到相机上,使用el.body.fixedRotation = true 来防止滚动。但是完全实现这个可能是几百行代码,所以我不能为你写对不起。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-01-22
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多