【问题标题】:Use " vector.applyQuaternion " or similar in ammo.js在 ammo.js 中使用“vector.applyQuaternion”或类似的
【发布时间】:2019-10-21 10:09:25
【问题描述】:

我想制作一个浏览器 VR 射击游戏,使用 Three.js 和 Ammo.js 来制作物理和刚体。虚拟现实头和控制器已设置好模型已加载,但子弹不会像我想要的那样从枪中射出。当我尝试在场景中只使用没有刚体的 Three.js 来做同样的事情时,我使用了 Three.js 文档中的“vector.applyQuaternion”,它起作用了,子弹是从枪口发射的。问题是我没有发现任何类似使用 ammo.js 的东西

不使用 ammo.js 的代码

       ...  function handleController( controller ) {

               if ( controller1.userData.isSelecting ) {



                bullet1.position.set( controller1.position.x , controller1.position.y + 0.018 , controller1.position.z -0.01);
                bullet1.userData.velocity.x = 0;
                bullet1.userData.velocity.y = 10;
                bullet1.userData.velocity.z = 10;
                bullet1.userData.velocity.applyQuaternion( controller1.quaternion );
                scene.add(bullet1);



               }

                if ( controller2.userData.isSelecting ) {

                bullet2.position.set( controller2.position.x  , controller2.position.y + 0.018 , controller2.position.z -0.01 );
                bullet2.userData.velocity.x = 0;
                bullet2.userData.velocity.y = 10;
                bullet2.userData.velocity.z = 10;
                bullet2.userData.velocity.applyQuaternion( controller2.quaternion );
                scene.add(bullet2);


               }

          } ...

        function render() {
            handleController( controller1 );
            handleController( controller2 );

            var delta = clock.getDelta()
            bullet1.position.x -= bullet1.userData.velocity.x *  delta;
            bullet1.position.y -= bullet1.userData.velocity.y *  delta;
            bullet1.position.z -= bullet1.userData.velocity.z *  delta;



            bullet2.position.x -= bullet2.userData.velocity.x *  delta;
            bullet2.position.y -= bullet2.userData.velocity.y *  delta;
            bullet2.position.z -= bullet2.userData.velocity.z *  delta;

            renderer.render( scene, camera ); 
        } 

使用 ammo.js 编写代码

            function createBullet1RigidBody( threeObject, physicsShape, mass ) {
                //threeObject.position.copy( pos );
                //threeObject.quaternion.copy( quat1 );
                quat1.set( controller1.position.x, controller1.position.y , controller1.position.z , Math.PI/2 );
                pos1 = new THREE.Vector3 ( controller1.position.x, controller1.position.y , controller1.position.z  );
                var transform = new Ammo.btTransform();
                transform.setIdentity();
                transform.setOrigin( new Ammo.btVector3( controller1.position.x, controller1.position.y, controller1.position.z -0.5) );
                transform.setRotation( new Ammo.btQuaternion( quat1.x, quat1.y, quat1.z, quat1.w ) );
                var motionState = new Ammo.btDefaultMotionState( transform );
                var localInertia = new Ammo.btVector3( 0, 0, 0 );
                physicsShape.calculateLocalInertia( mass, localInertia );
                var rbInfo = new Ammo.btRigidBodyConstructionInfo( mass, motionState, physicsShape, localInertia );
                var body1 = new Ammo.btRigidBody( rbInfo );
                threeObject.userData.physicsBody = body1;
                scene.add( threeObject );
                if ( mass > 0 ) {
                    bullet1Bodies.push( threeObject );
                    // Disable deactivation
                    body1.setActivationState( 4 );
                }
                physicsWorld.addRigidBody( body1 );
                return body1;
            }


        function createBullet2RigidBody( threeObject, physicsShape, mass ) {
                //threeObject.position.copy( pos );
                //threeObject.quaternion.copy( quat2 );
                var transform = new Ammo.btTransform();
                transform.setIdentity();
                transform.setOrigin( new Ammo.btVector3( controller2.position.x, controller2.position.y, controller2.position.z -0.5 ) );
                transform.setRotation( new Ammo.btQuaternion( quat.x, quat.y, quat.z, quat.w ) );
                var motionState = new Ammo.btDefaultMotionState( transform );
                var localInertia = new Ammo.btVector3( 0, 0, 0 );
                physicsShape.calculateLocalInertia( mass, localInertia );
                var rbInfo = new Ammo.btRigidBodyConstructionInfo( mass, motionState, physicsShape, localInertia );
                var body2 = new Ammo.btRigidBody( rbInfo );
                threeObject.userData.physicsBody = body2;
                scene.add( threeObject );
                if ( mass > 0 ) {
                    bullet2Bodies.push( threeObject );
                    // Disable deactivation
                    body2.setActivationState( 4 );
                }
                physicsWorld.addRigidBody( body2 );
                return body2;
            }

 ...

    function handleController( controller ) {

            if ( controller1.userData.isSelecting ) {

            var bullet1Mass = 0.1;
            var bullet1Radius = 0.6;
            var bullet1 = new THREE.Mesh( geometry_bullet, new THREE.MeshLambertMaterial( { color: 0x2661b9 } ) );
            var bullet1Shape = new Ammo.btSphereShape ( bullet1Radius );

            bullet1Shape.setMargin ( margin );


            var bullet1_body = createBullet1RigidBody( bullet1, bullet1Shape, bullet1Mass, bullet1Radius );
            //bullet1.position.set( pos1.x, pos1.y, pos1.z );
            bullet1.userData.physicsBody.setFriction( 0 );
            bullet1_body.setLinearVelocity( new Ammo.btVector3( 100, 100, 100 , controller1.quaternion) );
            }

            if ( controller2.userData.isSelecting ) {


            var bullet2Mass = 0.1;
            var bullet2Radius = 0.6;
            var bullet2 = new THREE.Mesh( geometry_bullet, new THREE.MeshLambertMaterial( { color: 0xee2f2f } ) );
            var bullet2Shape = new Ammo.btSphereShape ( bullet2Radius );
            var pos2 = new THREE.Vector3 ( controller2.position.x, controller2.position.y + 10, controller2.position.z +10 );
            bullet2Shape.setMargin ( margin );

            //quat2.set( 0,0,0,1 );
            var bullet2_body = createBullet2RigidBody( bullet2, bullet2Shape, bullet2Mass, bullet2Radius, pos2, quat2 );
            //var pos2 = bullet2.position.set( controller2.position.x, controller2.position.y, controller2.position.z -0.1 );
            bullet2.userData.physicsBody.setFriction( 0 );
            bullet2_body.setLinearVelocity( new Ammo.btVector3( 0, 0, controller2.position.z *100 ) );
            //bullet2.userData.physicsBody.applyQuaternion(controller2.quaternion);
            }

        } 

结果是创建了子弹,但它们仅在 z 轴上移动。如果我在 x 轴上移动控制器,子弹 2 的速度会发生变化,而子弹只在 z 轴上移动。 bullet1 的子弹跟随 x、y、z 轴上的运动,但不跟随控制器的旋转。 “bullet2.userData.physicsBody.applyQuaternion(controller2.quaternion);”行是注释,如果我删除条形,我会收到此错误“TypeError:bullet2.userData.physicsBody.applyQuaternion 不是函数”。我希望在没有 ammo (userData.velocity.applyQuaternion) 的情况下执行与上一个示例相同的操作,但 ammo.js 中没有 LinearVelocity,我只能使用 getLinearVelocity 和 setLinearVelocity。

【问题讨论】:

    标签: javascript three.js webvr rigid-bodies ammo.js


    【解决方案1】:

    根据我见过的弹药版本,您对 setLinearVelocity() 的调用不正确。 btVector3 构造函数必须仅采用 x,y,z。使用与您在其他地方所做的类似的 ThreeJS 数学计算它(选择幅度并通过控制器的四元数旋转 vector3)。这可能会解决您的问题。

    注意:我质疑为什么你的子弹需要进行物理模拟。大多数射击游戏不这样做。更容易和更快的是在检查它何时拦截玩家/墙时直观地更新其进度。如果你想要重力效果,那么每帧都应用小的垂直落差。如果你想要弹跳,那么使用截取表面的法线来改变速度。弹药引擎适用于手榴弹弹跳(复杂、不可预测的交互)之类的事情。

    【讨论】:

      猜你喜欢
      • 2015-05-27
      • 1970-01-01
      • 1970-01-01
      • 2012-02-03
      • 2014-04-06
      • 1970-01-01
      • 2018-11-14
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多