如何使对象绕垂直轴旋转并围绕另一个对象Three.js

时间:2019-04-12 15:13:49

标签: 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);

然后我在render函数中声明了旋转,如下所示:

                   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;
                }

1 个答案:

答案 0 :(得分:0)

您可以轻松地使用THREE.Object3D彼此嵌套,通过旋转半径将它们移动并围绕中心旋转。

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

enter image description here

<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 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(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);
    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:对不起,我的英语