简体   繁体   English

Three.js将球体旋转到任意位置

[英]Three.js Rotate sphere to arbitrary position

Using Three.js I have a sphere (globe) and several sprites attached to volcano points. 使用Three.js,我有一个球体(球体)和几个附着在火山点上的精灵。 I can rotate (spin) the globe and the sprites stay in their positions because they're added as a group to the sphere. 我可以旋转(旋转)地球,并且精灵会保持其位置,因为它们是作为一个组添加到球体中的。

Now I want to be able to spin the globe to an arbitrary position using a button. 现在,我希望能够使用按钮将地球仪旋转到任意位置。 How can I do this? 我怎样才能做到这一点? For example if the point I want to spin to is at the back of the globe, how can I rotate the globe so it's in the front? 例如,如果我想旋转到的点在地球的后部,我如何旋转地球,使其在前部?

This code is essentially what I have right now. 这段代码本质上就是我现在所拥有的。 A main mesh which I add sprite to. 我添加精灵的主网格。

 <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 图表示例

This would be my approach: 这是我的方法:

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

Now, I made a Plunker . 现在,我做了一个柱塞

It seems a bit inaccurate as it always rotates a bit left or right to the very front position. 似乎总是不正确,因为它总是向左或向右旋转到最前面的位置。 Maybe it's due to the cosinus near to some specific angles. 可能是由于余弦接近某些特定角度。

Also keep in mind that the determination whether the sprite is left or right from the camera is a bit more difficult if camera or mesh is somewhere else in the scene. 还请记住,如果摄像机或网格物体位于场景中的其他位置,则确定摄像机的精灵是左侧还是右侧会更加困难。

Explanation after dot product: 点积后的说明:

The dot product gives the angle of two vectors as cosinus. 点积给出了两个向量的余弦角。 So we get a value between -1 and 1. eg cos(0) = 1 cos(PI/2) = 0 cos(PI) = -1 So at the moment is 0° = 1 and 180° = -1. 因此,我们得到一个介于-1和1之间的值。例如cos(0) = 1 cos(PI/2) = 0 cos(PI) = -1因此,此时的角度为0°= 1且180°= -1。

We want to get the angle in radians to rotate the mesh in position. 我们想要获得以弧度为单位的角度来旋转网格。 So first we normalize it (dot + 1) / 2 , so 0° = 1 and 180° = 0. 所以首先我们将其归一化(dot + 1) / 2 ,所以0°= 1和180°= 0。

Then invert it (0° = 0, 180° = 1) and multiply with PI (0° = 0, 180° = PI). 然后将其反转(0°= 0,180°= 1)并乘以PI(0°= 0,180°= PI)。

Now, we have the angle to rotate, but we don't know if need to rotate to the left or to the right, that's why I check if the sprite is left or right from camera. 现在,我们可以旋转角度了,但是我们不知道是否需要向左或向右旋转,这就是为什么我要检查相机是否将精灵向左或向右旋转。

I don't know if it's explanation enough or if it's comprehensable at all? 我不知道这是足够的解释还是完全可以理解?

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM