如何将一个Object3D的旋转与另一个(不同的父对象,不同的坐标)匹配? [英] How can I match the rotation of one Object3D to another (different parents, different coords)?

查看:60
本文介绍了如何将一个Object3D的旋转与另一个(不同的父对象,不同的坐标)匹配?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想匹配three.js中参考对象的旋转。我要旋转的object3d和参考对象在不同的​​局部变换中可能具有不同的父对象,但我希望它们在全局空间中沿旋转方向对齐。

I want to match the rotation of a reference object in three.js. The object3d I want to rotate and the reference object might have different parents in different local transforms, but I want them to align rotation-wise in the global space.

function matchRotationOfReference(myObj3D, referenceObj3D) {
    // what do I do here?
}

我知道如何针对这样的位置矢量:

I know how to do this for position vectors like so:

var pos = new THREE.Vector3();
function matchPositionOfReference(myObj3D, referenceObj3D) {
    referenceObj3D.updateMatrixWorld();
    pos.setFromMatrixPosition(referenceObj3D.matrixWorld);
    myObj3D.parentEl.worldToLocal(pos);
    myObj3D.position.copy(pos);
}


推荐答案

注意:通常会问到您到目前为止已经尝试了什么,因为听起来这很容易完成。但是当我自己尝试时,我无法使其工作,因此我不得不跳了几圈,以使其正常工作。

在下面的示例代码中,我从两个 Group s开始,每个都包含一个多维数据集。每个 Group 也具有自己的变换/旋转方式。

In the example code below, I start with two Groups, each containing a cube. Each Group also has its own transformation/rotation. This makes the cubes initially face in different directions.

animate 函数中,您可以看到旋转复选框已选中,我将 redCube 的世界矩阵拆开(分解),保存其四元数(用于旋转)转换为 tempQ 。我对 greenCube 做同样的事情。然后,使用原始转换和比例,重新构建( compose greenCube 的世界矩阵。 code> redCube 的四元数。 (并且请记住,这是 world 四元数,因此它不受局部转换的影响。)

In the animate function, you can see when the "Spin" checkbox is checked, I tear apart (decompose) the redCube's world matrix, saving its quaternion (used for rotation) into tempQ. I do the same thing to greenCube. I then re-build (compose) greenCube's world matrix, using its original translation and scale, but using redCube's quaternion. (And remember, this is the world quaternion, so it's not affected by local transformations.)

之所以有效,是因为我直接使用了变换对象最重要的部分是它的世界矩阵。我禁用了全面更新矩阵的功能,这消除了three.js的许多便利,但是它使我可以直接使用世界矩阵,而不会覆盖它们。

This works because I took a direct shortcut to the most important part of transforming the object: its world matrix. I disabled updating matrices across the board, which removes a lot of the convenience of three.js, but it allowed me to work directly with the world matrices without anything overwriting them.

希望有人可以为您找到更优雅的解决方案。

Here's hoping someone can find a more elegant solution for you.

var renderer, scene, camera, controls, stats, redCube, greenCube, t, q, tempQ, s;

var WIDTH = window.innerWidth,
	HEIGHT = window.innerHeight,
	FOV = 35,
	NEAR = 1,
	FAR = 1000;

var doUpdates = false;
var spinBox = document.getElementById("spin");
spinBox.addEventListener("change", function(){
  doUpdates = spinBox.checked;
});

function populateScene(){

  var axis = new THREE.Vector3();
  var pos = new THREE.Vector3();
  var cubeGeo = new THREE.BoxBufferGeometry(10, 10, 10);

  axis.set(Math.random(), Math.random(), Math.random());
  pos.set(-10, 0, 0);
  var p1 = new THREE.Group();
  p1.matrixWorld.makeRotationAxis(axis, Math.random());
  p1.matrixWorld.setPosition(pos);
	redCube = new THREE.Mesh(cubeGeo, new THREE.MeshPhongMaterial({ color: "red" }));
	p1.add(redCube);
  redCube.updateMatrixWorld(true);
  
  scene.add(p1);
  
  axis.set(Math.random(), Math.random(), Math.random());
  pos.set(10, 0, 0);
  var p2 = new THREE.Group();
  p2.matrixWorld.makeRotationAxis(axis, Math.random());
  p2.matrixWorld.setPosition(pos);
	greenCube = new THREE.Mesh(cubeGeo, new THREE.MeshPhongMaterial({ color: "green" }));
	p2.add(greenCube);
  greenCube.updateMatrixWorld(true);
  
  scene.add(p2);
}

function init() {
	document.body.style.backgroundColor = "slateGray";

	renderer = new THREE.WebGLRenderer({ antialias: true, alpha: true });

	document.body.appendChild(renderer.domElement);
	document.body.style.overflow = "hidden";
	document.body.style.margin = "0";
	document.body.style.padding = "0";

	scene = new THREE.Scene();
  scene.autoUpdate = false;

	camera = new THREE.PerspectiveCamera(FOV, WIDTH / HEIGHT, NEAR, FAR);
	camera.position.z = 50;
	scene.add(camera);

	controls = new THREE.TrackballControls(camera, renderer.domElement);
	controls.dynamicDampingFactor = 0.5;
	controls.rotateSpeed = 3;

	var light = new THREE.PointLight(0xffffff, 1, Infinity);
	camera.add(light);

	stats = new Stats();
	stats.domElement.style.position = 'absolute';
	stats.domElement.style.top = '0';
	document.body.appendChild(stats.domElement);

	resize();
	window.onresize = resize;

	populateScene();
  
  t = new THREE.Vector3();
  q = new THREE.Quaternion();
  tempQ = new THREE.Quaternion();
  s = new THREE.Vector3();

	animate();
}

function resize() {
	WIDTH = window.innerWidth;
	HEIGHT = window.innerHeight;
	if (renderer && camera && controls) {
		renderer.setSize(WIDTH, HEIGHT);
		camera.aspect = WIDTH / HEIGHT;
		camera.updateProjectionMatrix();
		controls.handleResize();
	}
}

function render() {
	renderer.render(scene, camera);
}

function animate() {
	requestAnimationFrame(animate);
  camera.updateMatrixWorld(true);
  
  if(doUpdates){
    redCube.rotation.x += 0.01;
    redCube.rotation.y += 0.02;
    redCube.rotation.z += 0.03;
    redCube.updateMatrixWorld(true);
    
    redCube.matrixWorld.decompose(t, tempQ, s);
    greenCube.matrixWorld.decompose(t, q, s);
    greenCube.matrixWorld.compose(t, tempQ, s);
  }
  
	render();
	controls.update();
	stats.update();
}

function threeReady() {
	init();
}

(function () {
	function addScript(url, callback) {
		callback = callback || function () { };
		var script = document.createElement("script");
		script.addEventListener("load", callback);
		script.setAttribute("src", url);
		document.head.appendChild(script);
	}

	addScript("https://threejs.org/build/three.js", function () {
		addScript("https://threejs.org/examples/js/controls/TrackballControls.js", function () {
			addScript("https://threejs.org/examples/js/libs/stats.min.js", function () {
				threeReady();
			})
		})
	})
})();

<label style="display: block; float: right; width: 200px;">Spin:<input type="checkbox" id="spin" /></label>

这篇关于如何将一个Object3D的旋转与另一个(不同的父对象,不同的坐标)匹配?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆