【发布时间】: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