Three.js自定义相机旋转动画:沿圆弧旋转
2016-08-17 09:41
706 查看
因为Tween动画封装采样点默认是在起点和终点位置的直线上采点的,这样的话给的相机的起点和终点,如果沿着直线动画移动过去,其间必然会接近物体,从而造成物体变大。
为了解决这个问题,http://stackoverflow.com/questions/28091876/tween-camera-position-while-rotation-with-slerp-three-js,给出了解决方案,无奈对于四元数不太懂,而且把代码拷贝过去执行效果不佳,也不知道问题出在哪儿,所以干脆自己写个动画,即沿着圆弧移动相机。
代码也很简单,默认是沿着y轴旋转相机的,有时间抽取个函数,沿任意轴旋转相机。
相机沿着相机的位置到场景原点(世界坐标系的原点)连线(下面称之为OC)的垂直向量旋转,目的是切斜观察场景中的物体:
上面的方法使用的是绕任意轴的旋转矩阵求解相机旋转路径上的各个插值点。但是有个问题就是,相机旋转到临界点,即OC与世界坐标系的夹角phi接近0 的时候,相机会突然莫名其妙绕自身y轴旋转180度,不知道是不是浮点数计算的累计误差使相机的位置计算不准确所致,所以,我们将绕任意轴旋转的旋转矩阵换成下面的方法求解相机旋转路径上的点:
为了解决这个问题,http://stackoverflow.com/questions/28091876/tween-camera-position-while-rotation-with-slerp-three-js,给出了解决方案,无奈对于四元数不太懂,而且把代码拷贝过去执行效果不佳,也不知道问题出在哪儿,所以干脆自己写个动画,即沿着圆弧移动相机。
代码也很简单,默认是沿着y轴旋转相机的,有时间抽取个函数,沿任意轴旋转相机。
/* *camera:相机 *angle:旋转角度 *segs:分段,即圆弧对应的路径分为几段 *during:动画执行的时间 */ function myCameraTween(camera, angle, segs, during) { var x = camera.position.x; var y = camera.position.y; var z = camera.position.z; var endPosArray = new Array(); var perAngle = angle / segs; for (var i = 1 ; i <= segs ; i++) { var endPos = { "x": z * Math.sin(i * perAngle) + x * Math.cos(i * perAngle), "y": y, "z": z * Math.cos(i * perAngle) - x * Math.sin(i * perAngle) }; endPosArray.push(endPos); } var flag = 0; var id = setInterval(function () { if (flag == segs) { clearInterval(id); } else { camera.position.x = endPosArray[flag].x; camera.position.y = endPosArray[flag].y; camera.position.z = endPosArray[flag].z; flag++; } }, during / segs); }
相机沿着相机的位置到场景原点(世界坐标系的原点)连线(下面称之为OC)的垂直向量旋转,目的是切斜观察场景中的物体:
/* *camera:相机 *angle:旋转角度 *segs:分段,即圆弧对应的路径分为几段 *during:动画执行的时间 */ function myCameraTweenByAnyAxis(camera, angle, segs, during) { var x = camera.position.x; var y = camera.position.y; var z = camera.position.z; //相机向量(指向场景中心) var v1 = new THREE.Vector3(x, y, z); //求旋转轴,v1的垂直单位向量,令x=1,y=1,z=-(v1.x+v1.y)/v1.z var n = (new THREE.Vector3(1, 0, -1.0 * v1.x / v1.z)).normalize(); var endPosArray = new Array(); var perAngle = angle / segs; for (var i = 1 ; i <= segs ; i++) { var sinDelta = Math.sin(THREE.Math.degToRad(i * perAngle)); var cosDelta = Math.cos(THREE.Math.degToRad(i * perAngle)); var tempX = x * (n.x * n.x * (1 - cosDelta) + cosDelta) + y * (n.x * n.y * (1 - cosDelta) - n.z * sinDelta) + z * (n.x * n.z * (1 - cosDelta) + n.y * sinDelta); var tempY = x * (n.x * n.y * (1 - cosDelta) + n.z * sinDelta) + y * (n.y * n.y * (1 - cosDelta) + cosDelta) + z * (n.y * n.z * (1 - cosDelta) - n.x * sinDelta); var tempZ = x * (n.x * n.z * (1 - cosDelta) - n.y * sinDelta) + y * (n.y * n.z * (1 - cosDelta) + n.x * sinDelta) + z * (n.z * n.z * (1 - cosDelta) + cosDelta); var endPos = { "x": tempX, "y": tempY, "z": tempZ }; //console.log(endPos); endPosArray.push(endPos); } var flag = 0; var id = setInterval(function () { if (flag == segs) { clearInterval(id); } else { camera.position.x = endPosArray[flag].x; camera.position.y = endPosArray[flag].y; camera.position.z = endPosArray[flag].z; camera.updateMatrix(); flag++; } }, during / segs); }
上面的方法使用的是绕任意轴的旋转矩阵求解相机旋转路径上的各个插值点。但是有个问题就是,相机旋转到临界点,即OC与世界坐标系的夹角phi接近0 的时候,相机会突然莫名其妙绕自身y轴旋转180度,不知道是不是浮点数计算的累计误差使相机的位置计算不准确所致,所以,我们将绕任意轴旋转的旋转矩阵换成下面的方法求解相机旋转路径上的点:
/* * r OC的距离 * phi OC与世界坐标系y轴的夹角 * theta OC在XOZ平面投影与Z轴的夹角 */ function updateAngles(r, phi, theta) { //var vec = new THREE.Vector3(); var x, y, z; z = r * Math.sin(phi) * Math.cos(theta); x = r * Math.sin(phi) * Math.sin(theta); y = r * Math.cos(phi); console.log("x " + x + " : " + y + " : " + z + " theta:" + theta + " phi:" + phi); return { "x": x, "y": y, "z": z }; }
相关文章推荐
- Three.js纹理贴图正方体旋转动画效果
- js 动画,一个图片旋转的动画
- 自定义ProgressBar的旋转动画
- iOS 简单的动画自定义方法(旋转、移动、闪烁等)
- THREE.js--数学之美,国外有大牛做的webgl 曲线动画.
- 用js实现的模拟jquery的animate自定义动画(2.5K)
- IOS第18天(10,核心动画-转盘,自定义buton,旋转动画)
- Spin.js旋转的加载动画
- cocos2d-js 3.0 rc2 自定义UI控件组件 例子:能播放动画的MenuItem。MenuItemSprite的bug
- IOS 简单的动画自定义方法(旋转、移动、闪烁等)
- <iOS>解决自定义相机的打开时动画不一致问题
- three.js伪入门教程之旋转的九尾妖狐
- Three.js 保存camera(视角)设置到数据库,包括场景的缩放、旋转、移动等
- 【重头学习Android】关于自定义相机后照相旋转问题终极解决方案
- 视图自定义旋转动画 类似百度音乐
- three.js 绕其边缘旋转
- HTML5的一些知识:Canvas KineticJS旋转动画教程
- Android UI:看看Google官方自定义带旋转动画的ImageView-----RotateImageView怎么写(附 图片淡入淡出效果)
- 源码推荐(1.5):自定义相机控件,仿reddit ama的动画
- iOS开发——UI进阶篇(十八)核心动画小例子,转盘(裁剪图片、自定义按钮、旋转)图片折叠、音量震动条、倒影、粒子效果