2013-03-05 3 views
27

Myślę, że ten obraz najlepiej wyjaśnia mój problem:Jak obrócić niektóre księżyce wokół planety za pomocą THREE.js?

hooray for optical illusions

Najpierw przetłumaczyć pole wzdłuż czerwonej linii. Następnie chcę, aby efekt rotacji był niebieską linią w a, ale to, co faktycznie się dzieje, jest bardziej podobne do niebieskiej linii w b. Wydaje się, że zmiana obrotu jest zawsze względna w stosunku do oryginalnej przestrzeni obiektu, ale tłumaczenie (mimo że dzieje się to jako pierwsze) jest zawsze względne względem obiektu macierzystego i tak naprawdę nie wpływa na punkty geometrii w odniesieniu do przestrzeni obiektu. Przepraszam, jeśli to jest mylące; wyraźnie jestem nowy w tym.

Ważna część kodu wywołującego ten efekt znajduje się poniżej. Należy pamiętać, że orientacja obrazu jest inna niż ten kod; obraz jest jedynie przykładem wyraźnego pokazania efektu.

var objectContainer = new THREE.Object3D(); 

var tubeRadius = 100; 
var tubeGeometry = new THREE.CylinderGeometry(tubeRadius, tubeRadius, tubeRadius * 3, 36, 1, false); 
var tube = new THREE.Mesh(tubeGeomtry, material); 
scene.add(tube); 

var boxes = new THREE.Object3D(); 
var boxEdge = 50; 
var boxGeometry = new THREE.CubeGeometry(boxEdge, boxEdge, boxEdge); 
var box1 = new THREE.Mesh(boxGeometry, material); 
box1.translateX(tubeRadius + boxEdge/2 + 5); 
box1.translateY(boxEdge/2); 
box1.rotation = new THREE.Vector3(0, 2*Math.PI/3*0, 0); 
boxes.add(box1); 
var box2 = box1.clone(); 
box2.rotation = new THREE.Vector3(0, 2*Math.PI/3*1, 0); 
boxes.add(box2); 
var box3 = box1.clone(); 
box3.rotation = new THREE.Vector3(0, 2*Math.PI/3*2, 0); 
boxes.add(box3); 
scene.add(boxes); 

Jedynym rozwiązaniem można myślę, jest zawinąć każde okno w innej przestrzeni obiektu i obracają się wokół tego, ale wydaje się, że nadmierne pracy. Jaka jest preferowana metoda uzyskania oczekiwanego rezultatu?

+0

Nie wiem, Three.js, ale co powiesz na przetłumaczenie go przez 'Math.cos (obrót) * boxEdge/2, Math.sin (obrót) * boxEdge/2' oraz lokalny obrót? – Ryan

+0

To jest jak podwójna praca, obracanie i tłumaczenie każdego pudełka. Naprawdę chcę to obrócić każdy klon o ten sam punkt, który jest źródłem przed tłumaczeniem. –

Odpowiedz

29

Istnieje kilka sposobów robienia tego, co chcesz, ale myślę, że najłatwiej jest tak:

// parent 
parent = new THREE.Object3D(); 
scene.add(parent); 

// pivots 
var pivot1 = new THREE.Object3D(); 
var pivot2 = new THREE.Object3D(); 
var pivot3 = new THREE.Object3D(); 

pivot1.rotation.z = 0; 
pivot2.rotation.z = 2 * Math.PI/3; 
pivot3.rotation.z = 4 * Math.PI/3; 

parent.add(pivot1); 
parent.add(pivot2); 
parent.add(pivot3); 

// mesh 
var mesh1 = new THREE.Mesh(geometry, material); 
var mesh2 = new THREE.Mesh(geometry, material); 
var mesh3 = new THREE.Mesh(geometry, material); 

mesh1.position.y = 5; 
mesh2.position.y = 5; 
mesh3.position.y = 5; 

pivot1.add(mesh1); 
pivot2.add(mesh2); 
pivot3.add(mesh3); 

potem w swojej renderowania pętli:

parent.rotation.z += 0.01; 

EDIT : zaktualizowane skrzypce: http://jsfiddle.net/hbt9c/317/

three.js r.70

+0

Dzięki za przykład. Jak wspomniałem w pytaniu, właśnie o tym myślałem. Czy to typowe rozwiązanie problemu? Zamierzam to rozwinąć na chwilę i chcę tylko upewnić się, że nie strzelam sobie w stopę. –

+0

Tak. Jest typowy. Innym rozwiązaniem jest, aby każde pole było dzieckiem sceny i obliczać nowy wektor 'position' i' rotation' dla każdej klatki używając matematyki. – WestLangley

5

Tworzenie złożonego obiektu, którego środek będzie punktem, wokół którego obracają się obiekty wewnętrzne, jest jedną oczywistą odpowiedzią i byłoby bardzo szybkie do napisania. Po prostu stwórz Object3D i dodaj do niego swoje pudełko.

Podobne podejście obejmuje this question. Przesuwa punkt wierzchołków dla obiektu, dzięki czemu efektywnie ma nowe centrum.

Ewentualnie można porysować ręcznie matrycami. Spróbuj tego:

var boxGeometry = new THREE.CubeGeometry(boxEdge, boxEdge, boxEdge); 
var mr = new THREE.Matrix4(); 
var mt = new THREE.Matrix4(); 
mt.setPosition(new THREE.Vector3(0,tubeRadius,0)); 
var box1 = new THREE.Mesh(boxGeometry, material); 
box1.applyMatrix(mt); 
var box2 = box1.clone(); 
mr.makeRotationZ(2 * Math.PI /3); 
box2.applyMatrix(mr); 
boxes.add(box2); 
var box3 = box1.clone(); 
mr.makeRotationZ(4 * Math.PI /3); 
box3.applyMatrix(mr); 
boxes.add(box3); 
boxes.add(box1); 
scene.add(boxes);