Three.js自定义相机旋转动画:沿圆弧旋转
来源:互联网 发布:虚拟机ubuntu文件共享 编辑:程序博客网 时间:2024/05/16 13:45
因为Tween动画封装采样点默认是在起点和终点位置的直线上采点的,这样的话给的相机的起点和终点,如果沿着直线动画移动过去,其间必然会接近物体,从而造成物体变大。
为了解决这个问题,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 }; }
0 1
- Three.js自定义相机旋转动画:沿圆弧旋转
- 相机旋转动画
- three.js旋转元素
- three.js绕边缘旋转
- 自定义相机旋转拍照角度
- 自定义旋转动画
- three.js 绕其边缘旋转
- three.js 画一个旋转的立方体
- 自定义ProgressBar的旋转动画
- android自定义动画平移旋转
- android 自定义相机旋转问题解决及照片自动旋转问题解决
- js动画旋转与缩放
- 旋转动画
- 旋转动画
- 动画旋转
- 旋转动画
- 旋转动画
- 旋转动画
- MyEclipse添加Server Runtime的tomcat
- PAT(B) 1013数素数(20)
- 高斯消元模板
- App Runtime for Chrome打破边界,Android开始侵入Windows系统
- CSS基础教程——纯CSS开发的气泡式提示框
- Three.js自定义相机旋转动画:沿圆弧旋转
- 数据结构实验之查找四:二分查找
- simpledateformat
- 免费在线二维DataMatrix码生成器
- 数据结构上机实验之二分查找
- Codeforces 678E(Another Sith Tournament)
- 杭电-2063 过山车
- ssh无密登入机制
- 纯 HTML5 APP与原生APP的差距在哪?