问题
I'm trying to implement something very similar to what 3D modeling programs do, when dragging an object along a local axis. The main difference is, that you don't move the cursor around the screen, instead you freely move the camera and the cursor is always in the middle of the screen. Kind of like a first person game.
Imagine pointing the camera at the face of the cube below, marked with a blue cross (the cursor). You press and hold the mouse to "grab" the cube. The dragging of the cube should now be constrained to the axis, represented with the big red arrow.

For instance you could have moved the camera to the left and turned it to the right, as seen in the second image. In this case, the cube should be moved to the position of the wireframed cube. The single solid face of that cube is the same that you grabbed originally. Here, moving the turning the camera up/down (moving the cursor along the blue line) should have no effect on the cube's new position.

I'm having a hard time figuring out the math behind this. I know the cube's start position and rotation. I know the camera's position and rotation at all times. I can determine the face that was grabbed and its normal.
I was thinking about finding the plane that is parallel to the grabbed face and its intersection with the red arrow and the cursor are closest to each other, but this doesn't seem to be correct.
I was also trying to somehow project the cursor onto the red arrow, basically eliminating any movement along the blue line, but I'm not sure how.
回答1:
You can reduce the problem to a 2D problem, using 2 line (rays to be precise). The red arrow projected to the xy plane and the same with the ray from the camera (meaning you ignore the z axis for both), then map it back to 3D.
First get the center of the face (faceStartPos) and center of the camera.
Going by Blender's orientation (z
up, y
right, x
out from screen) of the you use the rotation of the camera to determine the line projected from the camera (I think you can figure that out, would be similar to how you got the norm from the cube, I assume), and the normal (with its starting position) as the line from the center of the face. Then you have a system of 2 linear equation with 2 unknowns, a little algebra and you can determine their values (for x
and y
). As for solving a system of 2 equation, I think you shoudl take the matrix approach (at least i find it easiest to implement in code, especially if you know it is is a system for 2 variables.
After that you can determine the values for x
and y
, you have the equation faceStartPos + t * normVec
where faceStartPos.x + t * normVec.x
, solve for t
.
t
is the magic variable that you really needed to move the cube, all you do is newCubeCenter = oldCubeCenter + t * normVec
Things to take into account:
- (The infamous) Floating point errors
- Points where camera is nearly (or exactly) aligned with the normal so that they are parallel
来源:https://stackoverflow.com/questions/22937929/constrain-dragging-to-local-axis-of-object