Reputation: 394
I'm trying to get my 2nd object to be directly behind (-distance) my 1st object that has been rotated.
Let's say I have 2 objects:
var object1 = new THREE.Object3D();
object1.position.set(5, 10, 53);
object1.rotateX(1);
object1.rotateY(1.5);
var distance = 20; //place object2 20 units behind object1
var object2 = new THREE.Object3D();
object2.position.set( /*position object2 right behind object1 -distance */);
object2.lookAt(object1);
In this instance, how do I place object2
directly behind object1
which has been rotated?
Visual 2D example. Not to scale
Upvotes: 7
Views: 6068
Reputation: 8866
In this specific use-case, you can add object2
to object1
, and simply set object2
's position to a single-axis value of the distance you want, in whatever axis serves as "behind" object1
.
// given: object1, object2
// assuming: the meshes' "forward" direction is locally +Z, both "up" are +Y
scene.add( object1 )
object1.add( object2 )
object2.position.z = -distance
the meshes' "forward" direction is locally +Z
This is important for determining what "behind" means. For example, a car would have the headlights pointing in the +Z direction.
both "up" are +Y
This is another aspect of the model orientation. If the "up" direction of both models is +Y, then both are "upright" relative to each other. This is like saying that for two cars, both of their roofs are oriented in the +Y direction.
Given that both meshes are--in their base orientation--oriented the same, then what you can do is manipulate object2
relative to object1
. You can do this by making object2
a child of object1
, which means object2
will now perform its transformations within object1
's local space, rather than world space. This is possible because Mesh
is a derivative of Object3D
, which is a generic 3D container in three.js. As a child, object2
automatically inherits object1
's transformations, so as you move/rotate object1
, object2
will follow.
You can continue chaining children to your heart's content, but at some point you might want to make one of the objects in your chain do something relative to an external or global object. Unwinding the transformations will take a few extra steps before you can perform your desired actions.
Upvotes: 2
Reputation: 31026
Do it like so:
let camera, scene, renderer;
init();
animate();
function init() {
camera = new THREE.PerspectiveCamera(70, window.innerWidth / window.innerHeight, 0.1, 100);
camera.position.set(5, 10, 55);
scene = new THREE.Scene();
const geometry = new THREE.PlaneGeometry();
const material = new THREE.MeshNormalMaterial();
const mesh1 = new THREE.Mesh(geometry, material);
mesh1.position.set(5, 10, 53);
mesh1.rotateX(1);
mesh1.rotateY(1.5);
scene.add(mesh1);
const mesh2 = new THREE.Mesh(geometry, material);
scene.add(mesh2);
const v1 = new THREE.Vector3(0, 0, 1).applyQuaternion(mesh1.quaternion);
mesh2.quaternion.copy(mesh1.quaternion);
mesh2.position.copy(mesh1.position).add(v1.multiplyScalar(-2));
renderer = new THREE.WebGLRenderer({
antialias: true
});
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement);
const controls = new THREE.OrbitControls(camera, renderer.domElement);
controls.target.copy(mesh1.position);
controls.update();
}
function animate() {
requestAnimationFrame(animate);
renderer.render(scene, camera);
}
body {
margin: 0;
}
<script src="https://cdn.jsdelivr.net/npm/[email protected]/build/three.js"></script>
<script src="https://cdn.jsdelivr.net/npm/[email protected]/examples/js/controls/OrbitControls.js"></script>
The idea is to apply the rotation of object1
to object2
and also use it to compute the position behind object1
. This is done by applying the rotation to a vector which is then scaled by a distance value (in the above case -2
) and then added to object1
's position value.
Upvotes: 4