web-dev-qa-db-ja.com

THREE.jsで惑星の周りに月を回転させるにはどうすればよいですか?

この写真が私の問題を最もよく説明していると思います:

hooray for optical illusions

まず、ボックスを赤い線に沿って移動します。次に、回転の効果をaの青い線にしたいのですが、実際に起こっているのはbの青い線に似ています。回転の変更は常に元のオブジェクト空間に相対的であるように感じますが、平行移動(最初に発生するにもかかわらず)は常に親に相対的であり、オブジェクト空間に関連するジオメトリポイントには実際には影響しません。混乱を招く場合はお詫びします。明らかに私はこれで新しいです。

この効果を生成するコードの重要な部分を以下に示します。画像の向きはこのコードが生成するものとは異なることに注意してください。画像は効果を明確に示すための単なる例です。

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

私が考えることができる唯一の解決策は、各ボックスを別のオブジェクト空間にラップしてそれを中心に回転させることですが、それは過度の作業のようです。私が探している結果を達成するために推奨される方法は何ですか?

31
Nick Larsen

あなたがやりたいことを行う方法はいくつかありますが、最も簡単な方法はそうだと思います:

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

次に、レンダーループで:

parent.rotation.z += 0.01;

編集:更新されたフィドル: http://jsfiddle.net/hbt9c/317/

three.js r.70

32
WestLangley

中心が内部オブジェクトの回転の中心となる複合オブジェクトを作成することは1つの明白な答えであり、非常に速く書くことができます。 Object3Dにボックスを追加します。

同様のアプローチは この質問 でカバーされています。オブジェクトの頂点の点を移動するため、効果的に新しい中心ができます。

または、手作業で行列をいじることもできます。これを試して:

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 );
6
CL22