2016-02-29 9 views
7

Ich habe eine rotierende Kugel, auf der ich ein div angehängt habe das Beispiel kann hier angesehen werden: https://jsfiddle.net/ao5wdm04/ Ich berechne die X-und Y-Werte und legen Sie die div mit einer translate3d Transform und das funktioniert ganz gut.Three.js Würfel Gesicht Rotationsvektor in Bezug auf Kamera

Meine Frage ist, wie die Werte für die rotateX zu bekommen, rotateY und rotateZ oder rotate3d verwandelt so die div „Tangenten“ die Kugeloberfläche. Ich weiß, dass das Würfelgitter dem Kugelzentrum zugewandt ist, also nehme ich an, dass der Rotationsvektor des nach außen gerichteten Normalvektors in Bezug auf die Kamera die Werte enthält, die ich brauche. Aber ich bin mir nicht sicher, wie ich diese erhalten soll.

aktualisiert

Durch die Verwendung von Euler-Winkel Ich bin zu erreichen fast die gewünschte Wirkung, hier gezeigt: https://jsfiddle.net/ao5wdm04/1/ aber die Rotation ist nicht groß genug.

+0

[Diese Geige] (http://jsfiddle.net/qa6erofL/) zeigt code- wie 'WebGLRenderer' und' CSS3DRenderer' zu mischen. Es funktioniert in Chrome für mich, aber es kann einige Probleme geben. Kannst du 'THREE.PlaneGeometry' statt divs für deine App verwenden und CSS3D vermeiden? – WestLangley

+0

Das ist ein schöner Gedanke, aber es funktioniert nicht in Safari, sind css Transformationen nicht lebensfähig? –

+0

Sorry, ich bin mir nicht sicher, was vor sich geht. Erwägen Sie nur die Verwendung von 'WebGLRenderer'. – WestLangley

Antwort

2

Haftungsausschluss: Ich weiß nichts über three.js. Ich habe gerade ein bisschen OpenGL gemacht.

Ihre Euler-Winkel stammen von einem Modell-projizierten Ursprung (Zeilen 74-80). Ich kann die Logik dahinter nicht sehen.

Wenn sich Ihr div auf der Kugeloberfläche befindet, sollte es sich an der Stelle der div an der Normalen der Kugel orientieren. Glücklicherweise haben Sie diese Winkel bereits. Sie heißen rotation.

Wenn Sie die Euler-Winkel in den Zeilen 82-84 durch die Drehwinkel ersetzen, die zur Positionierung des Divs verwendet werden, dann erscheint in meinem Browser das div am Rand des Kreises und das Gesicht auf, wenn es ist In der Mitte. Es sieht so aus, als ob es sich in einem Kreis bewegt, kanten Sie auf den Bildschirm. Ist das der gewünschte Effekt?

Meine Änderung an den verknüpften Code:

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

EDIT

Ah, ok. Die rotation Variable ist nur die der Kamera. Es regelt die Tangente am Äquator. Sie müssen auch die Ausrichtung ändern, um den Breitengrad zu berücksichtigen.

Machen Sie rotY gleich negativ Ihren Breitengrad. Stellen Sie dann sicher, dass diese Rotation vor der äquatorialen Rotation stattfindet. Rotationen sind nicht kommutativ.

Zusammengefasst Änderungen aus dem Code an https://jsfiddle.net/ao5wdm04/1/ sind wie folgt:

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

Ich weiß nicht, wie die Breite zwischen den init und render Funktionen propagieren sollte. Wie gesagt, ich bin mit der Sprache nicht vertraut.

+0

Nun gut, das funktioniert nur, wenn der Kreis am Äquator steht. Wenn ich Zeile 27 in etwas anderes als 0 (dh 45) ändere, wird der Kreis nicht richtig gedreht. –

+0

Danke das war der Effekt, den ich wollte! –

0

Für Details über Transformation und Rotation in OpenGL oder anderen Grafiken gehen Sie bitte here.


Grund -

Es gibt grundsätzlich zwei Arten von Transformationen in 3D welt-

  1. Translation
  2. Rotation

enter image description here

Ein kleines Beispiel zu diesen Dingen gibt here.


Wenn Sie alle durchlaufen, denke ich, dass Sie ein klares Konzept auf dem 3D-Transformationssystem haben.

Wenn Sie diese verstehen können, können Sie das einfach simulieren :), weil Sie 2 Dinge für jeden Zug zur gleichen Zeit tun müssen.

Versuchen Sie, diese

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>

Verwandte Themen