问题
I want to move objects along a plane parallel to the projection plane with the mouse. This means during the movement the distance between any picked object and camera projection plane (not camera position) must remain constant. A similar question has been asked: Mouse / Canvas X, Y to Three.js World X, Y, Z , but unlike there I need a solution working for arbitrary camera angles and camera/object positions not only for the plane with z=0. It also has to work for orthographic projection. Now I created a fiddle
http://jsfiddle.net/nmrNR/
the code in the mousemove event handler:
var v = new THREE.Vector3(
(event.clientX/window.innerWidth)*2-1,
-(event.clientY/window.innerHeight)*2+1,
1
);
projector.unprojectVector(v,camera);
var dist = circle.position.sub(camera.position,circle.position),
pos = camera.position.clone();
pos = pos.add(pos,
v.sub(v,camera.position).normalize().multiplyScalar(dist.length())
);
The circle is following the mouse position but its distance to the camera position is constant so it is actually performing a spherical movement. When switching to the ortographic camera (click) it also does not follow the mouse position as expected.
回答1:
I've modified the questioners excellent working version to work in a more current version (and a little more efficiently for me - just giving back, thanks. At first I found myself using clone to avoid jumpy behavior. Then I noted moving the object back and forth crept it forward so I used an initial click position (to get the distanceTo). There where also issues with warnings saying use addVectors and subVectors, but that was not necessary either.
camPos = cam.position;
var mv = new THREE.Vector3((event.clientX / window.innerWidth) * 2 - 1, -(event.clientY/window.innerHeight) * 2 + 1, 1).unproject(cam);
var pos = camPos.clone();
pos.add(mv.sub(camPos).normalize().multiplyScalar(initalClickPos.distanceTo(camPos)));
Setting the target object being moved's position to pos will move it from the mouse move position in the current camera plane, but it does in a way rotate as the camera distance is maintained for the object in perspective view.
It still looks a little funky to me so I'm thinking maybe this can be improved further with add and sub being cleaner. Possibly as seen in the others answer posted.
I still have issues with an offset for where I initially click so the position center doesn't pop around, maybe setting the objects pivot temporarily is worth exploring. This is working with r71.
回答2:
An older question which you might have long solved by now, here is an answer anyway.
You're not using a control like OrbitControls
which possibly makes this slightly easier, if only for visualising it in your head. OrbitControls
has not only the camera, but also a target object which directs the camera (it is always looking at it, and the y-axis is always up). The movement you want to achieve is perpendicular to the vector from camera to target
, rather than the vector to your object which changes as you move the object and whose change explains the circular movement. And handily, OrbitControls
provides the math you need.
From https://github.com/mrdoob/three.js/blob/master/examples/js/controls/OrbitControls.js#L147-L171, these functions compute a vector which are used to shift the camera and the target (which should work just as well for your object, though you'll probably need to invert the movement). Note that this.object
is the camera.
// pass in distance in world space to move left
this.panLeft = function ( distance ) {
var te = this.object.matrix.elements;
// get X column of matrix
panOffset.set( te[ 0 ], te[ 1 ], te[ 2 ] );
panOffset.multiplyScalar( - distance );
pan.add( panOffset );
};
// pass in distance in world space to move up
this.panUp = function ( distance ) {
var te = this.object.matrix.elements;
// get Y column of matrix
panOffset.set( te[ 4 ], te[ 5 ], te[ 6 ] );
panOffset.multiplyScalar( distance );
pan.add( panOffset );
};
Code is from r.68, if you have an older version it might not work without modification.
来源:https://stackoverflow.com/questions/19389854/moving-objects-parallel-to-projection-plane-in-three-js