我正在尝试围绕另一个已经在轴上旋转的 (THREE.mesh) 3d 对象旋转。任何指针?
I'm trying to rotate a (THREE.mesh) 3d object around another that is already rotating on an axis. Any pointers?
我正在寻找一种方法,让卫星绕着我的行星运行,而我的行星又绕着我的太阳运行。
(所有这些都是three.js中的3d对象)
我已经定义了我所有的物体,目前地球绕着我的太阳旋转,但我很难让月球绕着已经旋转的地球旋转。
sun = models['sun'];
earth = models['earth'];
moon = models['moon'];
let suns = new THREE.Group();
suns.add(sun);
let planets = new THREE.Group();
planets.add(earth);
let moons = new THREE.Group();
moons.add(moon);
scene.add(sun);
scene.add(earth);
scene.add(moon);
var orbit = 3;
var date = Date.now() * 0.0005;
earth.position.set(Math.cos(date) * orbit, 0, Math.sin(date) * orbit);
earth.rotation.y += 0.01*animation_speed;
moon.rotation.y += 0.01*animation_speed;
预期:地球围绕太阳旋转(静态),而月球在围绕太阳旋转时也围绕地球旋转。
当前:地球围绕太阳旋转。不确定如何处理月亮...
如果你为你的对象创建一个层次结构,那么它们会围绕它们的父对象旋转。
首先请注意,您的群组毫无意义。如果您调用 suns.add(sun)
然后调用 scene.add(sun)
,第二次调用会从 suns
中删除 sun
并将其添加到 scene
,因此您的组为空。所以在下面的例子中,我不会使用分组。
F.e.
const sun = models['sun'];
const earth = models['earth'];
const moon = models['moon'];
const sunContainer = new THREE.Object3D
sunContainer.add(sun)
const earthContainer = new THREE.Object3D
earthContainer.add(earth)
const moonContainer = new THREE.Object3D
moonContainer.add(moon)
scene.add(sunContainer); // sunContainer is child of scene
sunContainer.add(earthContainer); // earthContainer is child of sunContainer
earthContainer.add(moonContainer); // moonContainer is child of earthContainer
var earthOrbitRadius = 3;
var moonOrbitRadius = 0.2;
// position them at their orbit radius (relative to their parents)
earthContainer.position.set(earthOrbitRadius, 0, 0);
moonContainer.position.set(moonOrbitRadius, 0, 0);
// each planet rotates around its poles
sun.rotation.y += 1*animation_speed;
earth.rotation.y += 1*animation_speed;
moon.rotation.y += 1*animation_speed;
// and each planet orbits around its parent
sunContainer.rotation.y += 0.1*animation_speed;
earthContainer.rotation.y += 0.1*animation_speed;
现在将这些位恢复到您的代码中,根据需要调整数字,它应该会像想要的那样工作。
还有其他方法,这只是一种方法。要使行星旋转独立于轨道旋转,您可以使用负轨道旋转调整行星旋转。或者,您可以让容器绕轨道运行,然后将太阳、地球和月亮直接添加到场景而不是容器,然后将容器位置复制到它们,同时它们独立旋转。或者您可以使用物理引擎(Bullet Physics 内置于 Three.js 中)。或者你使用 pivot points.
顺便说一下,如果您 post 工作代码,那将会有所帮助。 :)
我开发了一个简单的示例来说明 THREE.Object3D
的层次结构以及子项与其 "parents" 及其位置和旋转的关系。
var scene = new THREE.Scene();
var aspect = window.innerWidth / window.innerHeight;
var camera = new THREE.PerspectiveCamera(75, aspect, 0.1, 1000);
var renderer = new THREE.WebGLRenderer();
renderer.setSize( window.innerWidth, window.innerHeight );
document.body.appendChild( renderer.domElement );
solarsystem.forEach(d => create(d, scene))
scene.add(sphere({radius:5, orbit:0}))
function create(d, target) {
var o = new THREE.Object3D(d.name);
o.add(orbit(d));
let p = sphere(d)
o.add(p);
d.satellites && d.satellites.forEach(d1 => create(d1, p))
target.add(o);
d.o=o;
}
function orbit(d) {
var o = new THREE.Object3D('orbit '+d.name);
o.rotateX(Math.PI/2);
o.add( new THREE.Line(
new THREE.CircleGeometry( d.orbit, 64 ),
new THREE.LineBasicMaterial( { color: 0xffffff } ) ));
return o;
}
function sphere(d){
var o = new THREE.Object3D('sphere '+d.name);
o.add(new THREE.Mesh(
new THREE.SphereGeometry(d.radius, 16, 16),
new THREE.MeshBasicMaterial({
color: 0x2980b9, wireframe: true
})));
o.translateX(d.orbit)
return o;
}
var grid = new THREE.GridHelper(500, 100, 0x666666, 0x444444)
grid.rotateY(Math.PI/2);
scene.add(grid);
camera.position.set(5,5,0);
new THREE.OrbitControls( camera, renderer.domElement );
let t = 0;
function render(dt) {
let t2= dt-t;
requestAnimationFrame( render );
renderer.render( scene, camera );
solarsystem.forEach(upd)
t = dt;
function upd(d) {
d.o.rotateY(t2/10000*d.speed);
d.satellites && d.satellites.forEach(upd)
}
}
requestAnimationFrame( render );
body, canvas {
margin: 0;
width: 100%;
height: 100%;
overflow: hidden;
background-color: black;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/103/three.min.js"></script>
<script src="https://threejs.org/examples/js/controls/OrbitControls.js"></script>
<script>
let solarsystem = [{
name: 'earth', radius: 2, orbit: 30, speed: 2,
satellites: [{
name: 'moon', radius: 1, orbit: 6, speed: 1,
}]
}, {
name: 'mars', radius: 2, orbit: 50, speed: 1,
satellites: [{
name: 'phobos', radius: 0.5, orbit: 3, speed: 1,
}, {
name: 'deimos', radius: 0.5, orbit: 4, speed: 3,
}]
}];
</script>
我正在寻找一种方法,让卫星绕着我的行星运行,而我的行星又绕着我的太阳运行。
(所有这些都是three.js中的3d对象)
我已经定义了我所有的物体,目前地球绕着我的太阳旋转,但我很难让月球绕着已经旋转的地球旋转。
sun = models['sun'];
earth = models['earth'];
moon = models['moon'];
let suns = new THREE.Group();
suns.add(sun);
let planets = new THREE.Group();
planets.add(earth);
let moons = new THREE.Group();
moons.add(moon);
scene.add(sun);
scene.add(earth);
scene.add(moon);
var orbit = 3;
var date = Date.now() * 0.0005;
earth.position.set(Math.cos(date) * orbit, 0, Math.sin(date) * orbit);
earth.rotation.y += 0.01*animation_speed;
moon.rotation.y += 0.01*animation_speed;
预期:地球围绕太阳旋转(静态),而月球在围绕太阳旋转时也围绕地球旋转。
当前:地球围绕太阳旋转。不确定如何处理月亮...
如果你为你的对象创建一个层次结构,那么它们会围绕它们的父对象旋转。
首先请注意,您的群组毫无意义。如果您调用 suns.add(sun)
然后调用 scene.add(sun)
,第二次调用会从 suns
中删除 sun
并将其添加到 scene
,因此您的组为空。所以在下面的例子中,我不会使用分组。
F.e.
const sun = models['sun'];
const earth = models['earth'];
const moon = models['moon'];
const sunContainer = new THREE.Object3D
sunContainer.add(sun)
const earthContainer = new THREE.Object3D
earthContainer.add(earth)
const moonContainer = new THREE.Object3D
moonContainer.add(moon)
scene.add(sunContainer); // sunContainer is child of scene
sunContainer.add(earthContainer); // earthContainer is child of sunContainer
earthContainer.add(moonContainer); // moonContainer is child of earthContainer
var earthOrbitRadius = 3;
var moonOrbitRadius = 0.2;
// position them at their orbit radius (relative to their parents)
earthContainer.position.set(earthOrbitRadius, 0, 0);
moonContainer.position.set(moonOrbitRadius, 0, 0);
// each planet rotates around its poles
sun.rotation.y += 1*animation_speed;
earth.rotation.y += 1*animation_speed;
moon.rotation.y += 1*animation_speed;
// and each planet orbits around its parent
sunContainer.rotation.y += 0.1*animation_speed;
earthContainer.rotation.y += 0.1*animation_speed;
现在将这些位恢复到您的代码中,根据需要调整数字,它应该会像想要的那样工作。
还有其他方法,这只是一种方法。要使行星旋转独立于轨道旋转,您可以使用负轨道旋转调整行星旋转。或者,您可以让容器绕轨道运行,然后将太阳、地球和月亮直接添加到场景而不是容器,然后将容器位置复制到它们,同时它们独立旋转。或者您可以使用物理引擎(Bullet Physics 内置于 Three.js 中)。或者你使用 pivot points.
顺便说一下,如果您 post 工作代码,那将会有所帮助。 :)
我开发了一个简单的示例来说明 THREE.Object3D
的层次结构以及子项与其 "parents" 及其位置和旋转的关系。
var scene = new THREE.Scene();
var aspect = window.innerWidth / window.innerHeight;
var camera = new THREE.PerspectiveCamera(75, aspect, 0.1, 1000);
var renderer = new THREE.WebGLRenderer();
renderer.setSize( window.innerWidth, window.innerHeight );
document.body.appendChild( renderer.domElement );
solarsystem.forEach(d => create(d, scene))
scene.add(sphere({radius:5, orbit:0}))
function create(d, target) {
var o = new THREE.Object3D(d.name);
o.add(orbit(d));
let p = sphere(d)
o.add(p);
d.satellites && d.satellites.forEach(d1 => create(d1, p))
target.add(o);
d.o=o;
}
function orbit(d) {
var o = new THREE.Object3D('orbit '+d.name);
o.rotateX(Math.PI/2);
o.add( new THREE.Line(
new THREE.CircleGeometry( d.orbit, 64 ),
new THREE.LineBasicMaterial( { color: 0xffffff } ) ));
return o;
}
function sphere(d){
var o = new THREE.Object3D('sphere '+d.name);
o.add(new THREE.Mesh(
new THREE.SphereGeometry(d.radius, 16, 16),
new THREE.MeshBasicMaterial({
color: 0x2980b9, wireframe: true
})));
o.translateX(d.orbit)
return o;
}
var grid = new THREE.GridHelper(500, 100, 0x666666, 0x444444)
grid.rotateY(Math.PI/2);
scene.add(grid);
camera.position.set(5,5,0);
new THREE.OrbitControls( camera, renderer.domElement );
let t = 0;
function render(dt) {
let t2= dt-t;
requestAnimationFrame( render );
renderer.render( scene, camera );
solarsystem.forEach(upd)
t = dt;
function upd(d) {
d.o.rotateY(t2/10000*d.speed);
d.satellites && d.satellites.forEach(upd)
}
}
requestAnimationFrame( render );
body, canvas {
margin: 0;
width: 100%;
height: 100%;
overflow: hidden;
background-color: black;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/103/three.min.js"></script>
<script src="https://threejs.org/examples/js/controls/OrbitControls.js"></script>
<script>
let solarsystem = [{
name: 'earth', radius: 2, orbit: 30, speed: 2,
satellites: [{
name: 'moon', radius: 1, orbit: 6, speed: 1,
}]
}, {
name: 'mars', radius: 2, orbit: 50, speed: 1,
satellites: [{
name: 'phobos', radius: 0.5, orbit: 3, speed: 1,
}, {
name: 'deimos', radius: 0.5, orbit: 4, speed: 3,
}]
}];
</script>