javascript - 如何让对象在垂直轴上并围绕另一个对象旋转 Three.js

标签 javascript three.js

您可能注意到我问了很多与我的项目相关的问题,所以提前感谢您的所有支持。

我的项目由围绕太阳旋转的地球和月球组成。 (它们并不是专门围绕太阳旋转,而是更多地围绕太阳所在的 0,0 轴旋转)。

我最初创建了几何图形,然后将它们添加到场景中,然后添加到轨道组中,如下所示

var orbitGroup = new THREE.Object3D();
                scene.add(orbitGroup); 

            scene.add(planetEarth);
            orbitGroup.add(planetEarth);
            scene.add(planetMoon);
            orbitGroup.add(planetMoon);

然后我在渲染函数中声明旋转,如下所示

                   planetEarth.add( planetMoon );
                planetEarth.add(rocketGroup);

            // call the render function
            var angle = 0;
            render();

            function render() {
                stats.update();

                 // rotate the orbit group
                angle += 0.002;                    
                angle += 0.002 * controls.EarthRotationSpeed;
                planetEarth.rotation.y += controls.EarthRotationSpeed;                    
                planetMoon.rotation.y += controls.MoonRotationSpeed;                    
                angle+= 0.01 * controls.SunRotationSpeed;
                planetSun.rotation.y += controls.SunRotationSpeed;        

                 // rotate the orbit group
                angle += 0.02;
                orbitGroup.rotation.y = -angle / 10;


                littleOrbitGroup.rotation.x = -angle;


                // render using requestAnimationFrame
                requestAnimationFrame(render);
                renderer.render(scene, camera);
            }

正如您所知,月球和地球都绕着太阳公转,而不是月球在绕太阳旋转时绕地球旋转。有没有一种方法可以声明它应该绕轨道运行的特定点或对象,并使其绕我想要的任何轴而不是专门在 y 轴上绕轨道运行?

----------------编辑-----------------

function createMesh(geom) {
                    var loader = new THREE.TextureLoader();
                    var planetTexture = loader.load("../assets/textures/planets/Earth.png");
                    var normalTexture = loader.load("../assets/textures/planets/EarthNormal.png");
                    var planetMaterial = new THREE.MeshPhongMaterial({map: planetTexture, bumpMap: normalTexture});
                    // create a multimaterial
                    var mesh = THREE.SceneUtils.createMultiMaterialObject(geom, [planetMaterial]);
                    return mesh;
                }

最佳答案

您可以使用将 THREE.Object3D 嵌套在另一个内部的方式轻松实现这一点,通过旋转半径移动它们并围绕中心旋转它们。

看这个简单的例子,这里使用了轨道控制 - 使用鼠标滚轮缩小并拖动旋转:

enter image description here

<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/110/three.min.js"></script>
<script src="https://threejs.org/examples/js/controls/OrbitControls.js"></script>

<script>
    THREE.TOUCH = {}
    let base64prefix = 'data:image/png;base64,'
    let blue = 'iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mNkuPn/PwAFkgLZdUNuXwAAAABJRU5ErkJggg=='
    let blue2= 'iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mNkqPz/HwAEcgJ5UUczUQAAAABJRU5ErkJggg=='
    let orange = 'iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mP8H8PwHwAGGQJcoBRfLQAAAABJRU5ErkJggg=='
    
let solarsystem = [{
        texture: blue,
        name: 'earth', radius: 2, orbit: 30, speed: 2,
        satellites: [{
            texture: blue2, rotation: [1, 1, 1],
            name: 'rock', radius: 0.5, orbit: 4, speed: 5,
        },{
            texture: blue2,
            name: 'moon', radius: 1, orbit: 6, speed: 1,
        }]
    }, {
        texture: orange,
        name: 'mars', radius: 2, orbit: 50, speed: 1,
        satellites: [{
            texture: blue2,
            name: 'phobos', radius: 0.5, orbit: 3, speed: 1,
        }, {
            texture: blue2,
            name: 'deimos', radius: 0.5, orbit: 4, speed: 3,
        }]
    }];
   
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 );


// planets
solarsystem.forEach(d => create(d, scene));

// sun
let sun = sphere({radius:3, orbit:0, texture: orange});
scene.add(sun)

function create(d, target) {
   var o = new THREE.Object3D(d.name);
   d.rotation && o.rotateX(d.rotation[0]);
   d.rotation && o.rotateY(d.rotation[1]);
   d.rotation && o.rotateZ(d.rotation[2]);
   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.translateX(d.orbit);
    var loader = new THREE.TextureLoader();
    loader.load( base64prefix + d.texture, function ( texture ) {
        var geometry = new THREE.SphereGeometry( d.radius, 20, 20 );
        var material = new THREE.MeshBasicMaterial( { 
            map: texture, overdraw: 0.5 
        } );
        o.add( new THREE.Mesh( geometry, material ) );
    } );    
    return o;
}

var grid = new THREE.GridHelper(500, 100, 0x666666, 0x444444)
grid.rotateY(Math.PI/2);
scene.add(grid);
camera.position.set(25,25,25);

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);
    sun.rotateY(t2/1000);
    t = dt;
    
    function upd(d) {
        d.o.rotateY(t2/10000*d.speed);
        d.satellites && d.satellites.forEach(upd)
    }
}

requestAnimationFrame( render );

</script>

<style>

  body, canvas { 
    margin: 0;  
    width: 100%;
    height: 100%;
    overflow: hidden;
    background-color: black;
  }
  
</style>

PS:抱歉我的英语

关于javascript - 如何让对象在垂直轴上并围绕另一个对象旋转 Three.js,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55654737/

相关文章:

javascript - Three.js - 如何在渲染期间更新连接对象的线

javascript - Require_Once 不链接服务器上的 PHP 文件

javascript - 将 HTML Canvas 导出为图像序列

javascript - 查找渲染/可见文本的高度

javascript - 使用 React 进行表单验证

javascript - 在 Three.js 中旋转天空盒

javascript - 三个js dat-gui : Change opacity and visibility of object coming from OBJMTL Loader

javascript - 三.JS看看

javascript - 如何根据 JavaScript 中的条件返回字符串的不同变体?

javascript - 如何使用 Angular.js 展开和折叠 div