3.js cube body rotation vector relative to the camera

I have a rotating sphere on which I have a div, an example can be seen here: https://jsfiddle.net/ao5wdm04/ I calculate the x and y values ​​and place the div using translate3d transform, and this works very well.

My question is how to get the values ​​for the rotateX , rotateY and rotateZ or rotate3d so that the div "touches" the surface of the sphere. I know that the cubic grid is facing the center of the sphere, so I assume that the rotation vector of the normal vector facing the environment with respect to the camera will contain the values ​​that I need. But I'm not quite sure how to get them.

Update

Using Euler angles, I almost achieve the desired effect shown here: https://jsfiddle.net/ao5wdm04/1/ , but the rotation is not large enough.

+7
css-transforms euler-angles
source share
2 answers

Disclaimer: I don't know anything about three.js . I just did a bit of OpenGL.

Your Euler angles come from the projected image on the model (lines 74-80). I do not see this logic.

If your div is on the surface of the sphere, then it should be oriented along the normal of the sphere at the location of the div. Fortunately, you already have these angles. They are called rotation .

If you replace the Euler angles in lines 82-84 with the rotation angles used to place the div, then in my browser the div appears on the edge when it is on the edge of the circle, and collide with it when it is in the center. It looks like it is moving in a circle, moving to the screen. Is this the effect you want?

My change to the related code:

 82 var rotX = (rotation.x * (180/ Math.PI)); 83 var rotY = (rotation.y * (180/ Math.PI)); 84 var rotZ = 0; 

EDIT

Oh good. The rotation variable is just a camera. He controls the tangent at the equator. You also need to change the accounting orientation for latitude.

Make rotY equal to negative your latitude. Then make sure that this rotation occurs before the equatorial rotation. Rotations are not commutative.

In general, the changes from the code https://jsfiddle.net/ao5wdm04/1/ are as follows:

 27 var lat = 45 * Math.PI / 180; ... 82 var rotX = (rotation.x * (180/ Math.PI)); 83 var rotY = - 45; ... 88 document.getElementById('face').style.webkitTransform = 'translate3d(' + x + 'px,' + y + 'px,0px) rotateY('+rotX+'deg) rotateX('+rotY+'deg)'; 

I don't know how latitude should spread between init and render functions. As I said, I am not familiar with the language.

+2
source share

More information about conversion and rotation in openGL or any other graphics go through here .


Highlights -

In the three-dimensional world, there are 2 types of transformations -

enter image description here

A small example on this subject is given here .


If you go through all of them, I think you have a clear idea of ​​the 3D conversion system.

If you can understand this, you can easily imitate this :) because you need to do 2 things for each movement at the same time.

Try this code -

 var camera, scene, renderer, raycaster, geometry, material, mesh, box; var rotation = { x: 0, y: 0 }; var distance = 500; init(); animate(); function init() { raycaster = new THREE.Raycaster(); ; scene = new THREE.Scene(); camera = new THREE.PerspectiveCamera(50, window.innerWidth / window.innerHeight, 1, 10000); camera.position.z = distance; camera.position.y = 100; scene.add(camera); geometry = new THREE.SphereGeometry(100, 50, 50, 50); material = new THREE.MeshNormalMaterial(); mesh = new THREE.Mesh(geometry, material); scene.add(mesh); var transform = new THREE.Matrix4().getInverse(scene.matrix); var lat = 0 * Math.PI / 180; var lon = 90 * Math.PI / 180; var r = 100; var p = new THREE.Vector3(-r * Math.cos(lat) * Math.cos(lon), r * Math.sin(lat), r * Math.cos(lat) * Math.sin(lon) ); p.applyMatrix4(transform); var geometry = new THREE.CubeGeometry(10, 10, 10); box = new THREE.Mesh(geometry, new THREE.MeshBasicMaterial({ color: 0xff0000, })); box.position.set(px, py, pz); box.lookAt(mesh.position); //scene.add(box); box.updateMatrix(); renderer = new THREE.WebGLRenderer(); renderer.setSize(window.innerWidth, window.innerHeight); document.body.appendChild(renderer.domElement); } function animate() { requestAnimationFrame(animate); render(); } function render() { rotation.x += 0.01; camera.position.x = distance * Math.sin(rotation.x) * Math.cos(rotation.y); camera.position.y = distance * Math.sin(rotation.y); camera.position.z = distance * Math.cos(rotation.x) * Math.cos(rotation.y); camera.lookAt(mesh.position); var w = window.innerWidth; var h = window.innerHeight; var mat = new THREE.Matrix4(); var v = new THREE.Vector3(); mat.copy(scene.matrix); mat.multiply(box.matrix); v.set(0, 0, 0); v.applyMatrix4(mat); v.project(camera); var euler = new THREE.Euler().setFromVector3(v); var rotX = (rotation.x * (180/ Math.PI)); var rotY = (rotation.y * (180/ Math.PI)); var rotZ = 0; var x = (w * (vx + 1) / 2) - 12.5; //compensate the box size var y = (h - h * (vy + 1) / 2) - 12.5; document.getElementById('face').style.webkitTransform = 'translate3d(' + x + 'px,' + y + 'px,0px) rotateX('+rotY+'deg) rotateY('+rotX+'deg) rotateZ('+rotZ+'deg)'; renderer.render(scene, camera); } 
 #face { position: absolute; width: 25px; height: 25px; border-radius: 50%; background-color: red; } 
 <script src="https://rawgit.com/mrdoob/three.js/master/build/three.min.js"></script> <div id="face"></div> 
0
source share

All Articles