携手创作,共同成长!这是我参与「掘金日新计划 · 8 月更文挑战」的第3天,点击查看活动详情
还是editor,今天的主角是坐标指示器。 先上图,gif效果图较大,想看请耐心加载。。。。
three 原本的位移 缩放 旋转是分开的,实际上一般操作也是分开的,不过,项目上合在一起了,这样就不需要手动切换模式了。 不过这个不是重点。
重点是,原本的旋转是只能旋转180度的,超过之后就倒退了。这大概是因为,余弦函数的对称轴是x=派。
现在想要的效果是能一直绕圈圈。 已经初步实现了,先看效果。
同事本来已经实现过一次了,但是她想换一种方式实现,结果遇到了问题,算不清楚。 让我来,我欣然接手了,心想这下之前学的东西不就排上用场了。
下面是three中相关代码的位置。
一般来说,拖曳控制旋转的原理就是把鼠标位移的转换到相机世界坐标的位移,转为角度。 这里没有这么直接。
按我原本的思路,比较复杂。 就是 计算,鼠标在旋转平面内的落点,就是从相机到鼠标位置的射线,与旋转轴垂直平面的交点。
用当前物体的position 减去落点得到一个向量,根据这个向量算出最终角度即可。
用反三角函数atan2(x,y)得到最终角度。
但是这个向量是空间向量,我没法直接用atan2算出角度。 需要把它转为平面向量,之前的思路是,用逆变换把整个物体回归原始位置,这样这个向量也会跟着回归到对应的平面。
然后,再区分x y z轴,取对应坐标计算。
遇到问题
我遇到的最大的问题不是怎么计算, 而是没搞清楚原先代码中变量对应的几何意义。 导致我换了几种方式都没成。越发心浮气躁。 于是,我强制冷静下来,一个个变量,溯源去看它是什么。
这样,我也大概看懂了原本代码的意图,比我的思路要简洁的多。
基本思路就是,记录鼠标按下时,交点与position相减得到向量,以这个向量为起始边。 以后mousemove的时候,再计算的向量就是,旋转之后向量。 而旋转轴已经知道了。
这样,就能抽象成如下问题。
已知一个向量a , 旋转轴M,a绕b旋转后的结果b , a M b是空间向量。 求a旋转了多少角度。
单位化后,点乘可以得到余弦值,但是上面也说了会有问题。 这个问题就用叉乘解决。 如果超过了180度,就要用2派减它。
这个旋转方向的正负,是因为有可能旋转轴是朝向屏幕里边的,这样我们的计算出来的结果刚好相反
问题就在这了 ,我是多此一举,自找麻烦。 因为我一直是按正方向计算的角度
//解决旋转方向的正负 多余
let k = M.z>0?1:-1 ; 删掉就好了
let a_ =a.clone().normalize(), b_= b.clone().normalize()
let cosval = a_.dot(b_), sinval = a_.cross(b_);
// 解决超过180度的问题 两个向量叉乘得到向量和旋转轴做点乘
let overHalf = sinval.dot(_tempVector)<0 ;
let rotationAngle = acos(cosval) ;
if(overHalf){
rotationAngle =2*PI - rotationAngle ;
}
小结
最后还有一点小问题要处理,先到这里。 总之,遇到问题不要烦躁,烦躁只会浪费时间。本来一个小时就能解决的,拖到现在。