在 3D 中旋转后计算顶点位置 space
Calculating vertex position after rotating in 3D space
我试图在 javascript 中在 Y 轴上旋转(在我自己的 3D 引擎中)
我试过这个功能:
function rotateY(amount) {
for (var i = 0; i < points.length; i++) {
points[i].z = Math.sin(amount) * points[i].x + Math.cos(amount) * points[i].z;
points[i].x = Math.cos(amount) * points[i].x - Math.sin(amount) * points[i].z;
}
}
它在旋转,但每次旋转都会改变它的 x 和 z 比例,所以它会变薄。你能帮我如何正确旋转它吗?谢谢:)
假设 i) 旋转是相对于全局原点而不是对象本身,并且 ii) 您想要应用增量(如果我们不能采用这些,请参见下文):
对于每个点:
1.求点相对轴的距离
2.求当前点相对轴的角度
3. 使用基本的二维 cos/sin polar projection, since the excluded axis is a unit vector.
function rotateY( points, deltaAngle ) {
const _points = points;
if ( ! Array.isArray( points ) ) points = [ points ];
for ( let i = 0; i < points.length; i ++ ) {
const newAngle = Math.atan2( points[ i ].z, points[ i ].x ) + deltaAngle;
const distance = ( points[ i ].x ** 2 + points[ i ].z ** 2 ) ** ( 1 / 2 );
points[ i ].x = distance * Math.cos( newAngle );
points[ i ].z = distance * Math.sin( newAngle );
}
return _points;
}
X 和 Z 旋转的算法相同,只要 Math.atan2
中使用的第一个轴与使用 Math.sin
的轴相同。
NOTE: I used the exponentiation operator. I wouldn't use this in production unless you're using Babel/something similar or don't care about IE/old users.
如果假设ii)不成立,我们只想存储点的原始角度,并将newAngle
定义为原始角度加上新角度。
如果不能采用假设 i),它就会变得复杂。如果对象的轴只是偏移,您可以在 newAngle
和 distance
中减去该偏移量,然后在设置 x
和 z
时将其加回去。如果轴本身不分别平行于全局轴,您需要切换到使用 quaternion to avoid gimbal lock. I would suggest copying or at least looking three.js's implementation.
我试图在 javascript 中在 Y 轴上旋转(在我自己的 3D 引擎中) 我试过这个功能:
function rotateY(amount) {
for (var i = 0; i < points.length; i++) {
points[i].z = Math.sin(amount) * points[i].x + Math.cos(amount) * points[i].z;
points[i].x = Math.cos(amount) * points[i].x - Math.sin(amount) * points[i].z;
}
}
它在旋转,但每次旋转都会改变它的 x 和 z 比例,所以它会变薄。你能帮我如何正确旋转它吗?谢谢:)
假设 i) 旋转是相对于全局原点而不是对象本身,并且 ii) 您想要应用增量(如果我们不能采用这些,请参见下文):
对于每个点:
1.求点相对轴的距离
2.求当前点相对轴的角度
3. 使用基本的二维 cos/sin polar projection, since the excluded axis is a unit vector.
function rotateY( points, deltaAngle ) {
const _points = points;
if ( ! Array.isArray( points ) ) points = [ points ];
for ( let i = 0; i < points.length; i ++ ) {
const newAngle = Math.atan2( points[ i ].z, points[ i ].x ) + deltaAngle;
const distance = ( points[ i ].x ** 2 + points[ i ].z ** 2 ) ** ( 1 / 2 );
points[ i ].x = distance * Math.cos( newAngle );
points[ i ].z = distance * Math.sin( newAngle );
}
return _points;
}
X 和 Z 旋转的算法相同,只要 Math.atan2
中使用的第一个轴与使用 Math.sin
的轴相同。
NOTE: I used the exponentiation operator. I wouldn't use this in production unless you're using Babel/something similar or don't care about IE/old users.
如果假设ii)不成立,我们只想存储点的原始角度,并将newAngle
定义为原始角度加上新角度。
如果不能采用假设 i),它就会变得复杂。如果对象的轴只是偏移,您可以在 newAngle
和 distance
中减去该偏移量,然后在设置 x
和 z
时将其加回去。如果轴本身不分别平行于全局轴,您需要切换到使用 quaternion to avoid gimbal lock. I would suggest copying or at least looking three.js's implementation.