What’s VR
Simply say, VR (Virtual reality) is a kind of technology which support real visual. It create to sight of a object, to insprire sense of eyes and lie our brand to believe that is true. The principle of VR is create Two scene with a tiny differnce of angle to imitate the distance of our two eyes.
Therefore WebVR is using same principle to create VR on Web, it use Three.js to create 3D object, and render it as 2 scenes.
Web polyfill
First step, declare a WebPolyfill class:
var config = (function() {
var config = {};
var q = window.location.search.substring(1);
if (q === '') {
return config;
}
var params = q.split('&');
var param, name, value;
for (var i = 0; i < params.length; i++) {
param = params[i].split('=');
name = param[0];
value = param[1];
// All config values are either boolean or float
config[name] = value === 'true' ? true :
value === 'false' ? false :
parseFloat(value);
}
return config;
})();
var polyfill = new WebVRPolyfill(config);
因为VR需要提供两个画面来制造视觉差,所以要使用效果器来把渲染器的画面一分为二, 这个步骤使用大佬做的库就好了:
var canvas = renderer.domElement
document.body.appendChild(canvas);
var effect = new THREE.VREffect(renderer);
effect.setSize(canvas.clientWidth, canvas.clientHeight, false);
然后我们就可以允许浏览器处理 Polyfill 在移动设备上. 之后, 我们需要获得用户正在使用的VR设备,然后把它代入全局变量:
var vrDisplay, controls;
navigator.getVRDisplays().then(function (vrDisplays) {
if (vrDisplays.length) {
vrDisplay = vrDisplays[0];
// 如果识别到了显示设备,则代入全局变量
controls = new THREE.VRControls(camera);
// 然后使用VR控制方法
vrDisplay.requestAnimationFrame(animate);
}
else {
// 如果没有VR显示设备,则使用Orbit控制器
controls = new THREE.OrbitControls(controlGroup,canvas);
controls.target.set(0, 0, -1);
var enterVRButton = document.querySelector('#vr');
enterVRButton.disabled = true;
requestAnimationFrame(animate);
}
});
无论有没有识别到vr显示设备, animation函数都会被执行, 但是不同的是,当使用vr设备时,我们要调用是 vr设备的RAF方法. 下一步,我们可以简单写一下animation函数里的requestAnimationFrame:
effect.render(scene, camera);
// 使用效果器
funciton animate(timestamp){
if (vrDisplay) {
vrDisplay.requestAnimationFrame(animate);
} else {
requestAnimationFrame(animate);
}
}
形态键动画
在THREE.js里,支持的3D动画类型有:
- 形态键 shapeKey
- 位置/旋转/比例 的关键帧动画 and morph weights
- 骨骼蒙皮动画 skinning
这些一般需要在3D建模软件上,如Blender来制作并导出. 通过添加不同的形态键,来改变原有物品的形状,并且通过插入关键帧来制作动画.现在我们主要了解一下形态键.
形态键可以由blender 2.80的修改器来添加,添加之后在 物体数据 的 形态键 中的 值 来制作动画. 之后导出成gltf格式. 要注意的是, 我们可以不需要导出材质.
导入THREE.js
我们使用THREE.GLTFLoader类来加载gltf文件, 在加载前,还需要声明一个混合器(mixer),
The AnimationMixer is a player for animations on a particular object in the scene. When multiple objects in the scene are animated independently, one AnimationMixer may be used for each object.
它是场景中的一个物品的动画播放器,如果有不同的物品动画,它可以分别播放他们. 其次,我们还需要一个clock类,用来记录时间点.
let mixer
let clock = new THREE.Clock();
loader = new THREE.GLTFLoader();
loader.load(
"js/bobo.glb",
function (gltf) {
obScene = gltf.scene
obScene.traverse(function (child) {
child.material = obMtr;
// 给场景中的子元素替换材质
});
mixer = new THREE.AnimationMixer(gltf.scene);
// 混合器,参数是根元素
gltf.animations.forEach((clip) => {
mixer.clipAction(clip).play();
// 给每个时间轴都开始播放
});
}
);
function animate(timestamp){
...
if ( mixer ) mixer.update( clock.getDelta() );
// 如果有混合器则更新
}
这种方法可以试blender文件里设置了时间轴的物品开始运动,不过如果想克隆一个元素,它会丧尸它的动画效果.具体原因暂时不清楚,不过在一篇git的更新报告里似乎提到了, SkeletonUtils.clone( object )
Adds a helper method, SkeletonUtils.clone( object ) that preserves SkinnedMesh/Bone relationships. Ideally this would “just work” with the usual object.clone(), but I can’t see any clean way of doing that — bones are not necessarily children of the SkinnedMesh(es?) they’re associated with, and trying to connect them requires logic that would need to live somewhere outside the recursive callback series. This helper method provides an easy way to work around the problem.
Based on https://gist.github.com/zellski/be4e9207ab8e70c4e89062d48ce345ba#file-gltf_utils-js-L19 by @zellski and https://gist.github.com/cdata/f2d7a6ccdec071839bc1954c32595e87 by @cdata.
根据上文,THREE肯定是拥有能够复制动画物体的可能性,并且还有它支持的骨骼蒙皮动画..应该也是非常有用.值得深入学习😂
Some Tips
- In WebVR / WebVR Polyfill, the position of camera will be Fixed or follow the HMD, so if we want to supply mouse control, we should bind OrbitControl at 3D Object rather than camera as common way.