Используйте vector.applyQuaternion или аналогичный в ammo.js

Я хочу сделать браузерную виртуальную стрелялку, используя Three.js и Ammo.js для физики и твердых тел. Виртуальная голова и контроллеры настроены, модели заряжены, но пули не будут стрелять из пистолета, как я хочу. Когда я попытался сделать то же самое, используя только Three.js без твердых тел в сцене, я использовал «vector.applyQuaternion» из документации Three.js, и это сработало, пули были выпущены из верхней части пистолета. Проблема в том, что я не нашел ничего подобного для использования 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. Скорость пули2 изменяется, если я перемещаю контроллер по оси x, а пули движутся только по оси z. Bullets of the bullet1 следует за движением по осям x, y, z, но не за вращением контроллера. "bullet2.userData.physicsBody.applyQuaternion(controller2.quaternion);" строка является комментарием, если я удаляю полосы, я получаю эту ошибку «TypeError: bullet2.userData.physicsBody.applyQuaternion не является функцией». Я ожидал сделать то же самое, что и в предыдущем примере, без патронов (userData.velocity.applyQuaternion), но в ammo.js нет LinearVelocity, я могу использовать только getLinearVelocity и setLinearVelocity.


person MrDaveMustaine    schedule 21.10.2019    source источник


Ответы (1)


Судя по версиям боеприпасов, которые я видел, ваш вызов setLinearVelocity() неверен. Конструктор btVector3 должен принимать только x,y,z. Вычислите его, используя математику ThreeJS, аналогично тому, как вы это делали в другом месте (выберите величину и поверните вектор3 на кватернион контроллера). Это, вероятно, решает вашу проблему.

Примечание. Я задаюсь вопросом, почему ваши пули должны быть физически смоделированы. Большинство стрелялок этого не делают. Проще и быстрее визуально обновлять его прогресс, проверяя, когда он перехватывает игрока/стену. Если вам нужен эффект гравитации, применяйте небольшой вертикальный перепад в каждом кадре. Если вы хотите рикошет, используйте нормаль перехваченной поверхности, чтобы изменить скорость. Боеприпасы хороши для таких вещей, как отскок гранаты (сложные, непредсказуемые взаимодействия).

person DAG    schedule 18.12.2019