动画行星绕其父母的旋转状态进行轨道运动 [英] Animating planet orbiting it's parent idependent on parent's rotation state
问题描述
我正在努力学习Three.js,对这些技术不熟悉。我实现了一个绕行星绕行的太阳,月亮环绕着行星。我关心的是,到目前为止,我必须做很多对象并在渲染循环中执行大量计算。
I'm trying to learn Three.js, beeing new to those technologies. I achieved a sun with planet orbitting around, with moon orbitting around planet. What am I concerned of, is to do what i have so far i have to make quite a lot of objects and perform quite a lot of calculations during rendering loops.
WestLangley 为我们提供了更多问题的小提示易于理解的方式:
WestLangley provided us with fiddles presenting problem in more easy-to-understand way so:
- 这个小提琴呈现的更像它现在正在寻找 - 行星的父母在太阳内,旋转那个父母将使行星轨道。但是每个行星/月球还有一个额外的物体,在
updateMatrixWorld
Object3D方法期间,父旋转也会将行星旋转到位。因此,通过查看mesh2.rotateOnAxis(AXIS,0.01);
位,它会比你想象的更快一点。 - < a href =http://jsfiddle.net/t83pzoj2/4/ =nofollow noreferrer>这个小提琴显示了一个无父母的方法。案例是,我正试图找到方法,我可以在系统启动时配置行星位置/旋转速度/轨道速度,而不仅仅是服务器时间,因此它会让玩家在同一位置感觉同步。
- this fiddle presents more like it is looking right now - planet has its parent inside sun, and rotating that parent will make planet orbit. But along with one extra object per planet/moon, theres an issue that parent rotation spins planet in place too, during to
updateMatrixWorld
Object3D method. So it will spin a bit faster than you may assume by looking atmesh2.rotateOnAxis( AXIS, 0.01 );
bit. - this fiddle shows one parent-less approach. Case is, I'm trying to find way, where I can configure planet positions/spins-speed/orbit-speed at system start and than just feed it with server time, so it will make it feel synchronised between players being at same location.
据我浏览手册,我发现可能有可能使用Three.js矩阵逻辑执行此类动画。我愿意尽可能减少对象内部 :: animate()
的使用(可能通过覆盖 updateMatrix
和 updateMatrixWorld
方法)。不幸的是,我的英语和数学都不够理解,有什么方法可以解决这些矩阵问题。如果有人可以帮助我,我会非常感激。
As far as I travelled through manuals, I found there may be a possibility of performing such animation using Three.js matrix logic. I'm willing to reduce usage of ::animate()
inside objects as far as possible (maybe by overriding updateMatrix
and updateMatrixWorld
methods). Unfortunately my english nor math are not good enough to understand, whats going around with those matrixes. If somebody can help me, I would really appreciate this.
工作小提琴是这里。我能够创造一个星球并且几乎拥有我想要的一切。剩下的一个问题就是,想要以更随机的度数运行行星。
Working fiddle is here. I was able to create a Planet and have almost all I want. One left issue is that, a would like to planet orbit at more random-looking degrees.
推荐答案
将这一点分开。我愿意减少太阳系中的物体数量,隐藏动画循环中的计算,并使其尽可能配置。
Forked this bit around. I was willing to reduce object count in my solar system, hide calculations from animation loop nad make it as configurable as possible.
为此,我实现了自定义 Mesh
名为 Planet
:
To make this I implemented custom Mesh
called Planet
:
var Planet = function ( geometry, material ) {
THREE.Mesh.call( this, geometry, material );
this.type = 'Planet';
};
Planet.prototype = Object.create( THREE.Mesh.prototype );
并覆盖标准 Object3D
矩阵计算函数:
and overriden standard Object3D
matrix-calculation functions:
Planet.prototype._matrixUpdate = THREE.Object3D.prototype.updateMatrix;
Planet.prototype._updateMatrixWorld = THREE.Object3D.prototype.updateMatrixWorld;
Planet.prototype.updateMatrix = function() {};
Planet.prototype.updateMatrixWorld = function() {};
由于这个原因,我可以重新计算标准方法中在该基础上创建的行星/卫星的位置和旋转每次渲染调用都会运行。
Thanks to that I can recalculate positions and rotations of planets/moons created on that base inside standard methods been running every render call.
为了好的开始,我在Planet构造函数中构建了一些我需要的基本参数原型:
For good start I've prototyped in Planet constructor some basic arguments I will need:
this.rotationAxis = new THREE.Vector3( 0, 1, 0 ).normalize(); // always rotate on Y
this.rotationSpeed = Math.PI/2; // length of planet day
this.orbitAxis = new THREE.Vector3( 0, 0.1, 1 ).normalize(); // y,z for orbit AXIS
this.orbitSpeed = Math.PI / 8; // length of planet year
这些应该可以在创建时配置,但是现在硬编码还可以。
those should be configurable on creation time, but for now hardcode is ok.
比进入新的 updateMatrix()
,计算与其父母相关的当前行星位置:
Than going into new updateMatrix()
, to calculate current planet position in relation of it's parent:
Planet.prototype.updateMatrix = function() {
var dta = delta || 0; // THREE.Clock::getDelta
// just for now, sun is not orbiting around
// anything, so checking instance
if ( this.parent instanceof Planet ) {
// rotate position in relation to parent, to make planet orbit
this.position.applyAxisAngle(this.orbitAxis, this.orbitSpeed * dta);
}
// rotate planet in place, to make it spin
this.rotateOnAxis(this.rotationAxis, this.rotationSpeed * dta);
this._matrixUpdate(); // fabricating Object3D.matrix
};
最后,但并非最不重要 - 将这些更改提供给 Object3D.worldMatrix
via updateMatrixWorld
implementation:
And last, but not least - providing those changes to Object3D.worldMatrix
via updateMatrixWorld
implementation:
Planet.prototype.updateMatrixWorld = function() {
if ( this.matrixAutoUpdate === true ) this.updateMatrix();
if ( this.matrixWorldNeedsUpdate === true || force === true ) {
if ( this.parent === undefined ) {
this.matrixWorld.copy( this.matrix );
} else {
// THIS else block is all whats different
// between Planet and standard Object3Dmethod
v = new THREE.Vector3(); // empty vector
v.applyMatrix4(this.parent.matrixWorld); // setup with parent position
v.add(this.position); // add local position
// compose instead of multiplication
this.matrixWorld.compose(v, this.quaternion, this.scale);
}
// ... rest like in THREE's (71) git.
工作代码位于这个小提琴。这样我在渲染循环期间减少了数学时间,减少了嵌套代码,最后:减少了最多50%的对象数量。但我对这个答案并不是100%有信心,所以任何进一步的优化都会受到赞赏。
Working code is in this fiddle. This way I have reduced math-time during render loop, reduced nested code and finally: reduced objects count by up to 50%. But I'm am not 100% confident about that answer, so any further optimisations are appreciated.
这篇关于动画行星绕其父母的旋转状态进行轨道运动的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!