我需要帮助将网格定位到根据本地坐标给出的特定点。我创建了高度为0.1的粉红色圆柱体,以展示我想要互相接触的多维立方体的局部点。
此外,我希望cube2成为cube1的孩子,但这暂时不是一个交易破坏者。
预期结果:立方体与其特定角落接触并且正确旋转 - 粉红色圆柱应该是完美的像素相互覆盖。
我尝试用以下方法解决它:
cube2.position.copy(cube_position.clone().add(cube2_position))
cube2.rotation.setFromVector3(cube_rotation.clone().add(cube2_rotation))
但这并没有像预期的那样发挥作用。我应该使用某种矩阵变换吗?
const scene = new THREE.Scene();
const camera = new THREE.PerspectiveCamera(45, window.innerWidth / window.innerHeight, 1, 1000);
camera.position.set(25, 25, 12);
// setup cubes
var geometry = new THREE.CubeGeometry(6, 6, 6);
var material = new THREE.MeshLambertMaterial({
color: 0x00fff0
});
var cube = new THREE.Mesh(geometry, material);
scene.add(cube);
cube.position.set(0.3, 1, -2);
cube.rotation.set(Math.PI / 3, Math.PI / 2, 1)
var geometry2 = new THREE.CubeGeometry(4, 4, 4);
var material2 = new THREE.MeshLambertMaterial({
color: 0x0fff00
});
var cube2 = new THREE.Mesh(geometry2, material2);
cube.add(cube2);
cube_position = new THREE.Vector3(3, 3, 3)
cube_rotation = new THREE.Vector3(Math.PI / 3, Math.PI / 4, 0)
cube2_position = new THREE.Vector3(2, -2, 2)
cube2_rotation = new THREE.Vector3(Math.PI / 2, Math.PI / 2, 0)
// visualize points
vmat = new THREE.MeshLambertMaterial({
color: 0xFF00FF,
opacity: 0.5,
transparent: true
});
v1 = new THREE.Mesh(new THREE.CylinderGeometry(1, 1, 0.1, 10), vmat);
cube.add(v1)
v1.position.copy(cube_position)
v1.rotation.setFromVector3(cube_rotation)
v2 = new THREE.Mesh(new THREE.CylinderGeometry(1, 1, 0.1, 10), vmat);
cube2.add(v2)
v2.position.copy(cube2_position)
v2.rotation.setFromVector3(cube2_rotation)
// BUG: connect cube with cube2 on specified points
cube2.position.copy(cube_position.clone().add(cube2_position))
cube2.rotation.setFromVector3(cube_rotation.clone().add(cube2_rotation))
// setup rest
var pointLight = new THREE.PointLight(0xFFFFFF);
pointLight.position.x = 10;
pointLight.position.y = 50;
pointLight.position.z = 130;
scene.add(pointLight)
const renderer = new THREE.WebGLRenderer({
antialias: true
});
renderer.setSize(window.innerWidth, window.innerHeight);
renderer.setClearColor(0x20252f);
renderer.setPixelRatio(window.devicePixelRatio);
document.body.appendChild(renderer.domElement);
const controls = new THREE.OrbitControls(camera, renderer.domElement);
animate();
function animate() {
requestAnimationFrame(animate);
render();
}
function render() {
renderer.render(scene, camera);
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.2.3/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/r82/three.js"></script>
<script src="https://yume.human-interactive.org/examples/buffer-geometry/OrbitControls.js"></script>
答案 0 :(得分:1)
因此,Matrix非常强大,可以解决旋转问题。我流了两步,正确设置cube2
旋转和位置。
轮换
cube1
,cube2
,v1
,v2
之间的关系是:
我们想要的是v2
世界轮换等于v1
相反的世界轮换。当两个对象具有相同的旋转时,它们具有相同的旋转矩阵(世界矩阵)。我们有这些公式:
V1opposite.w = V2.w
V1opposite.l * C1.w = V2.l * C2.l * C1.l
V1opposite.l = V2.l * C2.l
C2.l = V1opposite.l * V2.l(-1)
其中V1opposite.w表示v1
相反的世界矩阵,V2.w是v2
世界矩阵,C表示cube
,V2.l(-1)表示{的逆矩阵{1}}局部矩阵。现在,我们可以计算v2
旋转矩阵。
位置
我们需要的是使cube2
和v1
世界位置相同。以下是显示坐标空间的图表:
由于v2
是v2
的孩子,我们需要移动cube2
。在世界空间中,我们应将cube2
的距离从cube2
翻译为v2
,现在我们获得v1
世界位置,cube2
是cube2
,只需应用cube1
的逆矩阵即可获得cube1
本地位置。
这是一个jsfiddle example。
希望它有所帮助。<强>更新强>
我写了一个函数,你可以在没有cube2
和v1
的情况下使用它。
v2
我还添加了一个包含//connect obj1 and obj2 on obj1's point1 and obj2's point2.
function connect(obj1,obj2,point1,point2)
{
var point1World = new THREE.Vector3().copy(point1).applyMatrix4(obj1.matrixWorld);
var point2World = new THREE.Vector3().copy(point2).applyMatrix4(obj2.matrixWorld);
var translation = new THREE.Vector3().subVectors(point1World,point2World);
var obj2World = new THREE.Vector3().copy(obj2.getWorldPosition());
obj2World.add(translation);
if(obj2.parent !== null)
{
var inverseMatrix = new THREE.Matrix4().getInverse(obj2.parent.matrixWorld);
obj2World.applyMatrix4(inverseMatrix);
}
obj2.position.copy(obj2World);
}
和cube1
的祖父多维数据集。
jsfiddle