基础设置
开发Physijs的主要目标是使其尽可能简单和用户友好。物理引擎可能令人生畏,难以设置,有如此多的选项和配置,很容易让人不知所措。Physijs将所有额外的逻辑抽象出来,这样您就可以专注于项目的其余部分。
-
将 <script> 标记 添加 到页面并将其指向 physi.js 文件。
-
配置 Physijs.scripts.worker 和 Physijs.scripts.ammo Javascript参数以指向Web worker Ammo.js脚本
-
用来 Physijs.Scene 代替 THREE.Scene
-
相反的 THREE.Mesh ,选择最好的物理网等 Physijs.BoxMesh , Physijs.SphereMesh 或 Physijs.ConvexMesh
-
scene.simulate
在渲染时或者想要迭代物理设置时调用方法。
<!DOCTYPE html>
<html>
<head>
<script type="text/javascript" src="/js/Three.js"></script>
<script type="text/javascript" src="/js/physi.js"></script>
</head>
<body>
<div id="viewport"></div>
<script type="text/javascript">
'use strict';
Physijs.scripts.worker = '/js/physijs_worker.js';
Physijs.scripts.ammo = '/js/ammo.js';
var initScene, render, renderer, scene, camera, box;
initScene = function() {
renderer = new THREE.WebGLRenderer({ antialias: true });
renderer.setSize( window.innerWidth, window.innerHeight );
document.getElementById( 'viewport' ).appendChild( renderer.domElement );
// 场景创建
scene = new Physijs.Scene;
camera = new THREE.PerspectiveCamera(
35,
window.innerWidth / window.innerHeight,
1,
1000
);
camera.position.set( 60, 50, 60 );
camera.lookAt( scene.position );
scene.add( camera );
// Box
box = new Physijs.BoxMesh(
new THREE.CubeGeometry( 5, 5, 5 ),
new THREE.MeshBasicMaterial({ color: 0x888888 })
);
scene.add( box );
requestAnimationFrame( render );
};
render = function() {
scene.simulate(); // run physics
renderer.render( scene, camera); // render the scene
requestAnimationFrame( render );
};
window.onload = initScene();
</script>
</body>
</html>复制代码
基本形状
Physijs.PlaneMesh
- 无限零厚度平面Physijs.BoxMesh-匹配
THREE.CubeGeometry
Physijs.SphereMesh- 匹配
THREE.SphereGeometry
Physijs.CylinderMesh- 匹配
THREE.CylinderGeometry
Physijs.ConeMesh- 匹配
THREE.CylinderGeometry
(锥形)Physijs.CapsuleMesh- 匹配
THREE.CylinderGeometry
,除了在两端有两个半球Physijs.ConvexMesh
- 匹配您拥有的任何凸几何Physijs.ConcaveMesh
- 匹配您拥有的任何凹几何,即任意网格(比如人行)Physijs.HeightfieldMesh
- 匹配z坐标中给定的高度值的规则网格
scene.add( mesh_object )
笔记
-
使用 Physijs.ConcaveMesh 谨慎,它表现最差
THREE.PlaneMesh和
Physijs.PlaneMesh
不严格类似,因为后者是无限的。非常薄BoxMesh可以更好地表示有限平面。Physijs.CapsuleMesh
通常适合人形玩家角色
回调和事件
场景更新(scene.simulate):
var scene = new Physijs.scene;
scene.addEventListener( 'update', function() {
// the scene's physics have finished updating
scene.simulate( undefined, 1 );
physics_stats.update();
});复制代码
碰撞(Collisions):
var mesh = new Physijs.BoxMesh( geometry, material );
mesh.addEventListener( 'collision', function( other_object, linear_velocity, angular_velocity ) {
// `this` 监听事件的网格对象
// other_object 另一个跟‘this’碰撞的对象
// linear_velocity 碰撞的速度Vector3对象
// angular_velocity 碰撞的角度Vector3 对象
});复制代码
添加对象:
var readyHandler = function() {
// 对象添加到场景成功
};
var mesh = new Physijs.SphereMesh( geometry, material );
mesh.addEventListener( 'ready', readyHandler );
scene.add( mesh );复制代码
Collisions碰撞
var mesh = new Physijs.SphereMesh(
new THREE.SphereGeometry( 3 ),
new THREE.MeshBasicMaterial({ color: 0x888888 })
);
mesh.addEventListener( 'collision', function( other_object, relative_velocity, relative_rotation, contact_normal ) {
// `this`与`other_object`相撞,冲击速度为`relative_velocity`,
// 旋转力为'relative_rotation`,正常'contact_normal`
});复制代码
运动夹紧(Motion Clamping)
// Enable CCD if the object moves more than 1 meter in one simulation frame
// 如果对象在一个模拟框架中移动超过1米,则启用CCD
mesh.setCcdMotionThreshold(1);
// Set the radius of the embedded sphere such that it is smaller than the object
// 设置嵌入球体的半径,使其小于对象
mesh.setCcdSweptSphereRadius(0.2);复制代码
复合形状Compound Shapes
var parent = new THREE.Mesh( new THREE.CubeGeometry( 5, 5, 5 ), new THREE.MeshBasicMaterial({ color: 0x888888 }) );
var child = new THREE.Mesh( new THREE.SphereGeometry( 2.5 ), new THREE.MeshBasicMaterial({ color: 0x888888 }) );
child.position.z = 5;
parent.add( child );
scene.add( parent );复制代码
上面的代码将创建一个5x5x5的立方体,并在z轴上距离它5个单位处附加一个2.5半径的球体。移动和旋转父对象会直接影响子对象。为了使Physijs插件保持简单和简单,这正是其复合形状的工作原理。唯一需要改变的是替换THREE.Mesh Physijs等价:
var parent = new Physijs.BoxMesh( new THREE.CubeGeometry( 5, 5, 5 ), new THREE.MeshBasicMaterial({ color: 0x888888 }) );
var child = new Physijs.SphereMesh( new THREE.SphereGeometry( 2.5 ), new THREE.MeshBasicMaterial({ color: 0x888888 }) );
child.position.z = 5;
parent.add( child );
scene.add( parent );复制代码
约束Constraints
Point to Point(点到点)
点约束允许对象绑定到场景中的某个点,并且可以用于将两个对象约束在它们之间的某个点上。
var constraint = new Physijs.PointConstraint(
physijs_mesh_a, // First object to be constrained 第一个被约束的对象
physijs_mesh_b, // OPTIONAL second object - if omitted then physijs_mesh_1 will be constrained to the scene
// 可选的第二个对象 - 如果省略,则physijs_mesh_1将被约束到场景
new THREE.Vector3( 0, 10, 0 ) // point in the scene to apply the constraint
);
scene.addConstraint( constraint );复制代码
Hinge Constraint(链约束)
铰链约束限制物体的运动,就像它在铰链(例如门)上一样。与点约束一样,铰链可以使用1或2个对象创建。
var constraint = new Physijs.HingeConstraint(
physijs_mesh_a, // First object to be constrained
physijs_mesh_b, // OPTIONAL second object - if omitted then physijs_mesh_1 will be constrained to the scene
new THREE.Vector3( 0, 10, 0 ), // point in the scene to apply the constraint
new THREE.Vector3( 1, 0, 0 ) // Axis along which the hinge lies - in this case it is the X axis 铰链所在的轴
);
scene.addConstraint( constraint );
constraint.setLimits(
low, // minimum angle of motion, in radians 最小运动角度,以弧度为单位
high, // maximum angle of motion, in radians 最大运动角度,以弧度为单位
bias_factor, // applied as a factor to constraint error 作为约束错误的一个因素
relaxation_factor, // controls bounce at limit (0.0 == no bounce) 控件在极限处反弹(0.0 ==无反弹)
);
constraint.enableAngularMotor( target_velocity, acceration_force );
constraint.disableMotor();复制代码
Slider Constraint
var constraint = new Physijs.SliderConstraint(
physijs_mesh_a, // First object to be constrained
physijs_mesh_b, // OPTIONAL second object - if omitted then physijs_mesh_1 will be constrained to the scene
new THREE.Vector3( 0, 10, 0 ), // point in the scene to apply the constraint
new THREE.Vector3( 1, 0, 0 ) // Axis along which the hinge lies - in this case it is the X axis
);
scene.addConstraint( constraint );
constraint.setLimits(
linear_lower, // lower limit of linear movement, expressed in world units 线性运动的下限,以世界单位表示
linear_upper, // upper limit of linear movement, expressed in world units 线性运动的上限,以世界单位表示
angular_lower, // lower limit of angular movement, expressed in radians 线性运动的上限,以世界单位表示
angular_upper // upper limit of angular movement, expressed in radians 角运动的上限,以弧度表示
);
constraint.setRestitution(
linear, // amount of restitution when reaching the linear limits 归还的量到达所述线性限制时
angular // amount of restitution when reaching the angular limits 恢复原状的量到达角限制时
);
constraint.enableLinearMotor( target_velocity, acceration_force );
constraint.disableLinearMotor();
constraint.enableAngularMotor( target_velocity, acceration_force );
constraint.disableAngularMotor();复制代码
ConeTwist Constraint
var constraint = new Physijs.ConeTwistConstraint(
physijs_mesh_a, // First object to be constrained
physijs_mesh_b, // Second object to be constrained
new THREE.Vector3( 0, 10, 0 ), // point in the scene to apply the constraint
);
scene.addConstraint( constraint );
constraint.setLimit( x, y, z ); // rotational limit, in radians, for each axis
constraint.setMotorMaxImpulse( max_impulse ); // float value of the maximum impulse the motor can apply toward its target
constraint.setMotorTarget( target ); // target is the desired rotation for the constraint and can be expressed by a THREE.Vector3, THREE.Matrix4, or THREE.Quaternion
constraint.enableMotor();
constraint.disableMotor();复制代码
Degree Of Freedom Constraint
自由度约束可以完全控制对象如何在线性和角度运动中受到约束。
var constraint = new Physijs.DOFConstraint(
physijs_mesh_a, // First object to be constrained
physijs_mesh_b, // OPTIONAL second object - if omitted then physijs_mesh_1 will be constrained to the scene
new THREE.Vector3( 0, 10, 0 ), // point in the scene to apply the constraint
);
scene.addConstraint( constraint );
constraint.setLinearLowerLimit( new THREE.Vector3( -10, -5, 0 ) ); // sets the lower end of the linear movement along the x, y, and z axes.
constraint.setLinearUpperLimit( new THREE.Vector3( 10, 5, 0 ) ); // sets the upper end of the linear movement along the x, y, and z axes.
constraint.setAngularLowerLimit( new THREE.Vector3( 0, -Math.PI, 0 ) ); // sets the lower end of the angular movement, in radians, along the x, y, and z axes.
constraint.setAngularUpperLimit( new THREE.Vector3( 0, Math.PI, 0 ) ); // sets the upper end of the angular movement, in radians, along the x, y, and z axes.
constraint.configureAngularMotor(
which, // which angular motor to configure - 0,1,2 match x,y,z
low_limit, // lower limit of the motor
high_limit, // upper limit of the motor
velocity, // target velocity
max_force // maximum force the motor can apply
);
constraint.enableAngularMotor( which ); // which angular motor to configure - 0,1,2 match x,y,z
constraint.disableAngularMotor( which ); // which angular motor to configure - 0,1,2 match x,y,z复制代码
THREE.Vector3( 0, 0, 0 )
则没有能量将被应用到该对象。
您可以使用
object.setAngularVelocity并
object.setLinearVelocity
以相同的方式清除对象可能已具有的任何速度。
稍后您可以将对象的线性和角度因子重置为
( 1, 1, 1 )
。
// 设置为静止的
_vector.set( 0, 0, 0 );
selected_block.setAngularFactor( _vector );
selected_block.setAngularVelocity( _vector );
selected_block.setLinearFactor( _vector );
selected_block.setLinearVelocity( _vector );
// 设置受重力影响
_vector.set( 0, 0, 0 );
selected_block.setAngularFactor( _vector );
selected_block.setAngularVelocity( _vector );
复制代码
Materials材质
var friction = 0.8; // high friction 摩擦
var restitution = 0.3; // low restitution
var material = Physijs.createMaterial(
new THREE.MeshBasicMaterial({ color: 0x888888 }),
friction,
restitution
);
// Create a cube with friction of .8 and restitution of .3
var mesh = new Physijs.BoxMesh(
new THREE.CubeGeometry( 5, 5, 5 ),
material
);复制代码
Object scaling对象缩放
Pausing Simulation暂停模拟
停止模拟只需要在渲染时停止调用模拟函数(如下所示)。
var render = function() {
if (!isPaused) {
scene.simulate();
}
renderer.render();
};复制代码
var unpauseSimulation = function() {
isPaused = false;
scene.onSimulationResume();
};复制代码
Scene Configuration场景配置
var scene = new Physijs.Scene({ reportsize: 50, fixedTimeStep: 1 / 60 });复制代码
场景构造函数参数
-
fixedTimeStep default 1 / 60 此数字确定模拟一个模拟步骤的时间。数字越小,模拟越准确(越慢)。
-
broadphasedefault dynamic指定将使用哪个broadphase,选择是dynamic和sweepprune。
-
reportsize default 50 作为优化,包含对象位置的世界报告将根据此编号进行预初始化。最好将其设置为场景所具有的对象数量。
场景配置方法:
-
setGravity default ( 0, -10, 0 )设定重力的量和方向的方法。用法:scene.setGravity(new THREE.Vector3( x_force, y_force, z_force ))
-
setFixedTimeStep default 1 / 60 重置 fixedTimeStep 构造函数中给定的值。该方法用于允许动态物理精度配置。不要每帧都调用它!
自定义模拟步骤:
timeStep
maxSteps
scene = new Physijs.Scene; scene.setGravity(new THREE.Vector3( 0, -30, 0 )); // 设定重力的量和方向 scene.addEventListener( 'update', function() { scene.simulate( undefined, 1 ); } );复制代码
Updating an object's position & rotation更新对象的位置和旋转
var mesh = new Physijs.BoxMesh( geometry, material );
scene.add( mesh );
var render = function() {
// Change the object's position
mesh.position.set( 0, 0, 0 );
mesh.__dirtyPosition = true;
// Change the object's rotation
mesh.rotation.set(0, 90, 180);
mesh.__dirtyRotation = true;
// You may also want to cancel the object's velocity
mesh.setLinearVelocity(new THREE.Vector3(0, 0, 0));
mesh.setAngularVelocity(new THREE.Vector3(0, 0, 0));
scene.simulate();
renderer.render();
};复制代码