2015-10-29 56 views
0

使用Three.js我有一个球体(球体)和几个附着在火山点上的精灵。我可以旋转(旋转)地球,并且精灵会保持在他们的位置,因为它们被作为一个组添加到球体中。Three.js将球体旋转到任意位置

现在我希望能够使用按钮将地球旋转到任意位置。我怎样才能做到这一点?例如,如果我想要旋转的点位于地球的后面,那么我如何旋转地球仪以便它位于前方?

这段代码实质上就是我现在所拥有的。我添加精灵的主要网格。

<html> 
<head></head> 
<body> 


<script src="three.min.js"></script> 

<script> 

    var scene, camera, renderer; 
    var geometry, material, mesh; 

    init(); 
    animate(); 

    function init() { 

     scene = new THREE.Scene(); 
     camera = new THREE.PerspectiveCamera(75, window.innerWidth/window.innerHeight, 1, 10000); 
     camera.position.z = 1000; 

     material = new THREE.MeshBasicMaterial({ color: 0xff0000, wireframe: false }); 

     geometry = new THREE.SphereGeometry(159, 32, 32); 
     mesh = new THREE.Mesh(geometry, material); 
     scene.add(mesh); 

     var map = THREE.ImageUtils.loadTexture("sprite1.png"); 
     var material2 = new THREE.SpriteMaterial({ map:map, color:0x00ff00 }); 
     var sprite1 = new THREE.Sprite(material2); 
     sprite1.position.set(100,100,100); 
     sprite1.scale.set(40,40,40); 
     mesh.add(sprite1); 

     var sprite2 = new THREE.Sprite(material2); 
     sprite2.position.set(-100,-100,-100); 
     sprite2.scale.set(30,30,30); 
     mesh.add(sprite2); 

     var sprite3 = new THREE.Sprite(material2); 
     sprite3.position.set(100,-100,100); 
     sprite3.scale.set(20,20,20); 
     mesh.add(sprite3); 

     renderer = new THREE.WebGLRenderer({alpha:true}); 
     renderer.setSize(window.innerWidth, window.innerHeight); 

     document.body.appendChild(renderer.domElement); 

    } 

    function animate() { 
     requestAnimationFrame(animate); 
     mesh.rotation.y += 0.01; 
     renderer.render(scene, camera); 
    } 

</script> 
</body> 
</html> 

Diagram example

+0

你能告诉你已经有了什么代码吗?这将帮助 – Jesse

回答

0

这将是我的做法:

// as sprite is a child of mesh get world position 
var spritePos = new THREE.Vector3().setFromMatrixPosition(sprite.matrixWorld); 

// get the vectors for calculating angle 
var cv3 = new THREE.Vector3().subVectors(camera.position, mesh.position); 
var sv3 = new THREE.Vector3().subVectors(spritePos, mesh.position); 

// we only want to rotate around y-axis, so only the angle in x-z-plane is relevant 
var cv2 = new THREE.Vector2(cv3.x, cv3.z); 
var sv2 = new THREE.Vector2(sv3.x, sv3.z); 

// normalize Vectors 
cv2.normalize(); 
sv2.normalize(); 

// dot product 
var dot = cv2.dot(sv2); 

// angle to between sprite and camera in radians 
// cosinus is from 1 to -1, so we need to normalize and invert it and multiply it with PI to get proper angle 
var angle = (1 - (dot + 1)/2) * Math.PI; 

// is sprite left or right from camera? 
if(spritePos.x < 0) 
    mesh.rotation += angle; 
else 
    mesh.rotation -= angle; 

现在,我做了一个Plunker

它似乎有点不准确,因为它总是向左或向右转动到最前端的位置。也许这是由于cosinus接近某些特定的角度。

还要记住的是,精灵是左还是右,从相机的确定是一个比较困难的,如果相机或网是场景中的其他地方。点积后

说明:

点积给出了两个矢量作为余弦的角度。所以我们得到-1和1之间的一个值。 cos(0) = 1cos(PI/2) = 0cos(PI) = -1所以现在是0°= 1和180°= -1。

我们想要获得以弧度表示的角度来旋转网格。所以首先我们对它进行归一化,因此0°= 1和180°= 0。 )。

现在,我们有旋转角度,但我们不知道是否需要旋转到左边或右边,这就是为什么我检查精灵是向左或向右的相机。

我不知道这是否是足够的解释,或者如果它是comprehensable呢?

+0

我明白到“点积”部分。我在原文中添加了一个图表,希望我能正确理解它。你的代码似乎每次都给我一个固定的旋转,而不是每次都到达正确的位置。你能否澄清“点积”是怎么回事?我猜这是两个向量之间的角度,然后旋转这个数量? – user5504603

+0

是的,你的图是正确的。我更新了我的答案。我不得不改正一些东西,比如'setPositionFromMatrix'到'setFromMatrixPosition','>'到'<'。我也做了一个Plunker作为现场演示和解释。 – Brakebein