Three.js将球体旋转到任意位置
Three.js Rotate sphere to arbitrary position
使用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>
图表示例
这将是我的方法:
// 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。
它似乎有点不准确,因为它总是向左或向右旋转一点到最前面的位置。也许是由于余弦在某些特定角度附近。
还要记住,如果摄影机或网格位于场景中的其他位置,则确定精灵是在摄影机的左侧还是右侧会有点困难。
点积后的解释:
点积将两个向量的角度表示为余弦。所以我们得到一个介于-1和1之间的值。例如cos(0) = 1
cos(PI/2) = 0
cos(PI) = -1
此时So为0°=1和180°=-1。
我们想要得到以弧度为单位的角度来旋转网格。因此,首先我们将其标准化为(dot + 1) / 2
,因此0°=1,180°=0。
然后将其反转(0°=0,180°=1)并乘以PI(0°=0,180°=PI)。
现在,我们有了旋转的角度,但我们不知道是需要向左还是向右旋转,这就是为什么我从相机中检查精灵是向左还是向右。
我不知道这是足够的解释,还是完全可以理解?
相关文章:
- 一个html/javascript'小工具'知道用户何时单击了小部件外的任意位置
- 单击任意位置如何关闭框
- 单击任意位置关闭菜单
- Angularjs-将指令中的值绑定到文档中的任意位置显示/隐藏
- 单击页面上的任意位置时隐藏两个元素
- 匹配字符串中任意位置的 3 个字符的正则表达式
- 当用户单击网页中的任意位置时,如何获得通知
- 分叉弹性网格插件,能够通过单击屏幕上的任意位置来关闭预览
- 如何通过单击页面上的任意位置关闭下拉列表
- 通过单击任意位置关闭 JavaScript 弹出窗口
- 当用户单击文档中的任意位置时淡化弹出窗口
- 将类添加到动态元素上的正文,在页面上的任意位置再次单击后删除
- 当用户单击该弹出窗口图面之外的页面上的任意位置时,如何关闭动态添加的弹出窗口
- 如何使输入组在完成写入后或单击任意位置时折叠
- JQuery:单击 #element 以外的任意位置
- 元素在页面上的任意位置按键时隐藏
- 如何通过单击任意位置关闭javascript下拉菜单
- 通过单击弹出窗口外部的任意位置来关闭弹出窗口
- 在模态之外的任意位置单击时关闭模态窗口
- 单击任意位置链接