2016-02-29 1 views
7

J'ai une sphère de rotation sur laquelle j'ai un div attaché l'exemple peut être consulté ici: https://jsfiddle.net/ao5wdm04/ Je calcule les valeurs x et y et place la div en utilisant une translate3d transformer et ça marche plutôt bien.Trois.js cube visage rotation vecteur par rapport à la caméra

Ma question est de savoir comment peut obtenir les valeurs de la rotateX, rotateY et rotateZ ou rotate3d transforme donc les div « tangentes » la surface de la sphère. Je sais que le maillage du cube fait face au centre de la sphère, donc je suppose que le vecteur de rotation du vecteur normal faisant face à l'extérieur par rapport à la caméra contiendrait les valeurs dont j'ai besoin. Mais je ne suis pas sûr de savoir comment les obtenir.

Mise à jour

En utilisant des angles d'Euler Je suis presque les effets désirés, ici: https://jsfiddle.net/ao5wdm04/1/ mais la rotation est pas assez grand.

+0

[Ce violon] (http://jsfiddle.net/qa6erofL/) montre comment mélanger '' WebGLRenderer' et CSS3DRenderer'. Cela fonctionne dans Chrome pour moi, mais il peut y avoir quelques problèmes. Pouvez-vous utiliser 'TROIS.PlaneGeometry' au lieu de divs pour votre application et éviter CSS3D? – WestLangley

+0

C'est une bonne idée, mais cela ne fonctionne pas dans Safari, les transformations css ne sont-elles pas viables? –

+0

Désolé, je ne suis pas sûr de ce qui se passe. Envisagez d'utiliser 'WebGLRenderer' uniquement. – WestLangley

Répondre

2

Avertissement: Je ne sais rien à propos de three.js. Je viens de faire un peu d'OpenGL.

Vos angles euler proviennent d'une origine modèle-vue-projetée (lignes 74-80). Je ne peux pas voir la logique derrière cela.

Si votre div est sur la surface de la sphère, alors il doit être orienté par la normale de la sphère à l'emplacement de la div. Heureusement, vous avez déjà ces angles. Ils sont nommés rotation. Si vous remplacez les angles euler dans les lignes 82-84 par les angles de rotation utilisés pour positionner le div, alors dans mon navigateur, le div apparaît sur le bord quand il est au bord du cercle, et face dessus quand il est au centre. Cela ressemble à un mouvement en cercle, un bord à l'écran. Est-ce l'effet que vous voulez?

Ma modification du code lié:

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

EDIT

Ah, ok. La variable rotation est juste celle de l'appareil photo. Il gouverne la tangente à l'équateur. Vous devez également modifier l'orientation pour tenir compte de la latitude.

Faites rotY égale à la latitude de votre latitude. Ensuite, assurez-vous que cette rotation se produit avant la rotation équatoriale. Les rotations ne sont pas commutatives.

En résumé, les modifications du code au https://jsfiddle.net/ao5wdm04/1/ sont les suivantes:

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)'; 

Je ne sais pas comment la latitude devrait se propager entre les fonctions init et render. Comme je l'ai dit, je ne connais pas la langue.

+0

Eh bien, ça ne marchera que si le cercle est placé à l'équateur. Si je change la ligne 27 à quelque chose d'autre que 0 (c'est-à-dire 45), le cercle ne tourne pas correctement. –

+0

Merci, c'était l'effet que j'avais après! –

0

Pour plus de détails sur la transformation et la rotation dans OpenGL ou tout autre graphique, veuillez passer par here.


Basic -

Il y a essentiellement deux types de transformations en 3D World-

  1. Translation
  2. Rotation

enter image description here

Un petit exemple sur ce sujet est donné here.


Si vous les parcourez tous, je pense que vous avez un concept clair sur le système de transformation 3D.

Si vous pouvez comprendre cela, vous pouvez facilement simuler :) parce que vous devez faire ceci 2 choses pour chaque mouvement en même temps.

Essayez cette 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(p.x, p.y, p.z); 
 
    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 * (v.x + 1)/2) - 12.5; //compensate the box size 
 
    var y = (h - h * (v.y + 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>