10

Jest to prawdopodobnie bardzo podstawowy problem, ale nie znalazłem jeszcze rozwiązania i to mnie wkurzyło. Chciałbym pokazać strzałki wskazujące kierunki współrzędnych świata (x, y, z) w prawym dolnym rogu kamery, tak jak to się dzieje w Mayi, tak aby podczas obracania aparatu wokół obiektu lub poruszania się po scenie nadal możesz określić kierunki współrzędnych świata. Próbowałem tego dokonać za pomocą dwóch różnych podejść i żadne z nich nie zadziałało tak daleko.Three.js: Pokaż światowe osie współrzędnych w rogu sceny

Mam obiekt z trzema strzałkami jako dzieci używające klasy THREE.ArrowHelper, na razie nazwiemy to XYZ. Pierwsze podejście polega na uczynieniu z XYZ dziecka sceny i dostarczeniu mu pozycji obliczonej z aktualnej pozycji kamery oraz przesunięcia w kierunku wskazywanym przez kamerę i regulacji, tak aby pojawiła się w rogu, w którym chcę, zamiast w środek ekranu. Już prawie udało mi się to zrobić, ponieważ na strzałkach zachowano prawidłową rotację, ale pozycja jest trochę zabawna i przestałem jechać tą trasą, ponieważ podczas przesuwania kamery było naprawdę "roztrzęsione". Nie jestem pewien, czy to był problem z wydajnością, czy coś innego.

Druga metoda polega na uczynieniu XYZ dzieckiem kamery z lokalnym przesunięciem pozycji, a następnie odwróceniem obrotu kamery i zastosowaniem odwróconego obrotu do XYZ, aby dopasować współrzędne światowe. Wydaje mi się, że blisko używam tej metody, ale mogę albo uzyskać poprawne położenie, albo obrót jest poprawny, a nie oba.

Aktualnie używam kodu XYZ.matrix.extractRotation(camera.matrixWorldInverse);, aby zapewnić mi prawidłową orientację dla XYZ, ale jego pozycjonowanie jest wyłączone. Jeśli używam XYZ.matrixWorld.extractRotation(camera.matrixWorldInverse);, pozycja pozostaje dobra (dołączona do aparatu), ale orientacja się nie zmienia.

Jeśli ktoś ma szybki hack, aby to działało, byłoby to bardzo cenne. Jeśli masz lepszą metodę, niż ta, którą ścigam, to też byłoby to pomocne.

** - EDIT - ** Należy wspomnieć, że prawdopodobnie można znaleźć wersję roboczą tutaj - (https://googledrive.com/host/0B45QP71QXoR0Mm9Mbkp3WGI1Qkk/) Jestem przechowywania mojego kodu w Dysku Google, ale pracuje lokalnie przy użyciu wamp i aliasingu, co oznacza, że ​​wszelkie zmiany robię lokalnie uzyskać odzwierciedlenie w Internecie, jak tylko dysk Google zsynchronizuje. TO ZNACZY. może być zepsuty, gdy spojrzysz.

Odpowiedz

12

To pojawiło się przed here.

Sztuką jest dodanie drugiej sceny z drugą kamerą, która ma tę samą orientację co kamera oryginalna, ale zachowuje określoną odległość od początku.

camera2.position.copy(camera.position); 
camera2.position.sub(controls.target); 
camera2.position.setLength(CAM_DISTANCE); 
camera2.lookAt(scene2.position); 

EDIT: Aktualizacja skrzypce: http://jsfiddle.net/aqnL1mx9/

Three.js r.69

+0

Nieodebrane połączenie. Przyjrzę się tej metodzie i wrócę do ciebie. Zastanawiam się jednak, czy dodanie drugiej kamery zmniejszy wydajność bardziej niż uzyskanie jednej z powyższych metod do pracy? – wackozacko

+0

To działa! Musiał usunąć linię 'camera2.position.sub (controls.target);' ponieważ OribtControls.js nie utrzymuje docelowej pozycji, ale w przeciwnym razie rozwiązanie jest praktycznie takie samo. – wackozacko

+0

Nie usuwaj linii. Użyj 'controls.center' w r.58. – WestLangley

10

Z nowych three.js wersjach (nie wiem od kiedy) można użyć:

var axisHelper = new THREE.AxisHelper(5); 
scene.add(axisHelper); 

Numer referencyjny: AxisHelper

+0

@Jessica jasne, tutaj jest JSFiddle https://jsfiddle.net/84usyfsz/ – Andres

+0

To skrzypce nie robi tego, co OP szukał ... – trusktr

1

var camera, scene, renderer, geometry, material, mesh, axisHelper, localToCameraAxesPlacement; 
 

 
init(); 
 
animate(); 
 

 
function init() { 
 

 
    scene = new THREE.Scene(); 
 

 
    camera = new THREE.PerspectiveCamera(50, window.innerWidth/window.innerHeight, 1, 10000); 
 
    camera.position.z = 500; 
 
    camera.up = new THREE.Vector3(0,0,1); 
 
    scene.add(camera); 
 
    
 
    axisHelper = new THREE.AxisHelper(0.1) 
 
    localToCameraAxesPlacement = new THREE.Vector3(0.45 * camera.aspect,-0.45, -2); // make sure to update this on window resize 
 
\t \t scene.add(axisHelper) 
 

 
    geometry = new THREE.CubeGeometry(200, 200, 200); 
 
    material = new THREE.MeshNormalMaterial(); 
 

 
    mesh = new THREE.Mesh(geometry, material); 
 
    scene.add(mesh); 
 

 
    renderer = new THREE.WebGLRenderer(); 
 
    renderer.setSize(window.innerWidth, window.innerHeight); 
 

 
    document.body.appendChild(renderer.domElement); 
 

 
} 
 

 
function animate() { 
 

 
    requestAnimationFrame(animate); 
 
    render(); 
 

 
} 
 

 
var t = 0 
 
function render() { 
 
    t++ 
 
    
 
    camera.position.x = Math.cos(t/80) * 500 
 
    camera.position.y = Math.sin(t/80) * 500 
 
    camera.lookAt(mesh.position) 
 
    
 
    camera.updateMatrixWorld() 
 
    var axesPlacement = camera.localToWorld(localToCameraAxesPlacement.clone()) 
 
\t \t axisHelper.position.copy(axesPlacement); 
 

 
    renderer.render(scene, camera); 
 

 
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/87/three.min.js"></script>

Jest to „szybkie i brudne” sposobem dodania AxisHelper bez tworzenia dodatkowej sceny.Działa poprzez przesuwanie pomocnika osi przed kamerą przy każdym renderowaniu.

// Initialize 
var scene = getScene(); 
axisHelper = new THREE.AxisHelper(0.1); 
var localToCameraAxesPlacement = new THREE.Vector3(0.45 * camera.aspect,-0.45,-2); // make sure to update this on window resize 
scene.add(axisHelper); 

// On every render 
var camera = getCamera(); 
camera.updateMatrixWorld(); 
var axesPlacement = camera.localToWorld(localToCameraAxesPlacement.clone()); 
axisHelper.position.copy(axesPlacement); 
+1

Ile 'Vector3's tworzysz co sekundę? Utwórz jeden i użyj go ponownie. – WestLangley

+0

Czy mógłbyś napisać proste skrzypce? – trusktr

+0

@trusktr przepraszam za opóźnienie, dodałem działający fragment – seveibar