最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - 3D rotation with Axis & Angle - Stack Overflow

programmeradmin0浏览0评论

I know 3D rotation is well documented on SO and many other sites, but despite reading countless explanations I still haven't figured out where I'm going wrong. My background is in art and design, not math and programming, and I'm never really certain if my angle of attack (no pun intended) is the right one. Rather than paste a patchwork of my dismal code, I'm including an image describing my problem. What I'd really like is a step-by-step worded breakdown of how to solve it. Pseudo code is useful, but I will learn more if someone will just aim me in the right direction or point out common pitfalls.


Red = X-Axis, Green = Y-Axis, Blue = Z-Axis

Magenta vectors = origin --> some X,Y,Z point

Magenta cube = average of the endpoints of the two magenta vectors (is there a better name for this?)

White vector = cross product of the two magenta vectors (extended for display, actual vector is normalized)

Cyan cube object = rotation fail


I've previously used Away3D and Papervision; in these libraries, applying Euler angles to an object's rotationX, rotationY, or rotationZ properties will rotate the object locally, as if it's at the origin regardless of its actual position. With Three.js, this is not the case. Modifying an object's rotation.x and rotation.y properties produces a bizarre effect where the object apparently tilts a bit on the Z axis. Even more confusing is that this happens when the object rests at the origin. I thought that maybe using Quaternion-->Matrix or Axis/Angle-->Matrix functions would solve my problem, but no dice. It seems there's a core concept I'm not getting.

Anyway, what I'd like to do is orient the cube to the cross product vector (white), so that the top of the cube is facing the direction of that vector. Then I'd like to rotate the cube along the same axis. The image I've attached shows the result of more hours than I'd like to admit trying to achieve this result. My code loosely looks like this:

axis = Vector3.cross(a, b)
axis.normalize()
angle = 45 * TO_RADIANS;
quat = AxisAngle2Quaternion(axis, angle)
rot = Quaternion2Matrix(quat)
cube.matrix = rot

Thanks in advance,

Casey


Edit: Starting a bounty

Maybe I am misunderstanding how this is supposed to work. Here's another image:

Am I incorrect in thinking that this magenta vector is the axis, and the orange arrows indicate rotation about this axis based on the angle? One way or another, I want to orient the cyan cube based on some directional vector and spin it. What am I doing wrong!?

I know 3D rotation is well documented on SO and many other sites, but despite reading countless explanations I still haven't figured out where I'm going wrong. My background is in art and design, not math and programming, and I'm never really certain if my angle of attack (no pun intended) is the right one. Rather than paste a patchwork of my dismal code, I'm including an image describing my problem. What I'd really like is a step-by-step worded breakdown of how to solve it. Pseudo code is useful, but I will learn more if someone will just aim me in the right direction or point out common pitfalls.


Red = X-Axis, Green = Y-Axis, Blue = Z-Axis

Magenta vectors = origin --> some X,Y,Z point

Magenta cube = average of the endpoints of the two magenta vectors (is there a better name for this?)

White vector = cross product of the two magenta vectors (extended for display, actual vector is normalized)

Cyan cube object = rotation fail


I've previously used Away3D and Papervision; in these libraries, applying Euler angles to an object's rotationX, rotationY, or rotationZ properties will rotate the object locally, as if it's at the origin regardless of its actual position. With Three.js, this is not the case. Modifying an object's rotation.x and rotation.y properties produces a bizarre effect where the object apparently tilts a bit on the Z axis. Even more confusing is that this happens when the object rests at the origin. I thought that maybe using Quaternion-->Matrix or Axis/Angle-->Matrix functions would solve my problem, but no dice. It seems there's a core concept I'm not getting.

Anyway, what I'd like to do is orient the cube to the cross product vector (white), so that the top of the cube is facing the direction of that vector. Then I'd like to rotate the cube along the same axis. The image I've attached shows the result of more hours than I'd like to admit trying to achieve this result. My code loosely looks like this:

axis = Vector3.cross(a, b)
axis.normalize()
angle = 45 * TO_RADIANS;
quat = AxisAngle2Quaternion(axis, angle)
rot = Quaternion2Matrix(quat)
cube.matrix = rot

Thanks in advance,

Casey


Edit: Starting a bounty

Maybe I am misunderstanding how this is supposed to work. Here's another image:

Am I incorrect in thinking that this magenta vector is the axis, and the orange arrows indicate rotation about this axis based on the angle? One way or another, I want to orient the cyan cube based on some directional vector and spin it. What am I doing wrong!?

Share Improve this question edited Sep 30, 2010 at 5:44 Casey asked Sep 28, 2010 at 4:56 CaseyCasey 1,8063 gold badges22 silver badges37 bronze badges 5
  • 1 Nobody reacts, but I actually think, that your question is one of the best formulated ones I saw here so far. Maybe just nobody knows? I would also be curious to see an answer here. – erikbstack Commented Sep 28, 2010 at 9:45
  • Maybe they are shying away from the Three.js aspect... I expected this to be a pretty basic problem – Casey Commented Sep 28, 2010 at 20:45
  • I was able to get closer with the "Utils3D.pointTowards()" method in Flash: help.adobe.com/en_US/AS3LCR/Flash_10.0/flash/geom/Utils3D.html But I don't know how to apply the rotation about the axis and I can't find any comparable OSS functions – Casey Commented Sep 30, 2010 at 6:33
  • I've posted a similar question, and maybe its a little less formulated. Yes, you are correct in stating that the magenta unit vector is the axis of rotation, and yes, this is very difficult. I do not know anything about Three.js, but I am curious about it. Instead, I tried writing a project myself. I found that researching what is known as a quaternion was very useful, yet painful. Also, try Googling rotating around arbitrary axis for a number of answers, they helped me. – WebWanderer Commented Jul 22, 2014 at 18:23
  • Or even, check out this, it helped me the most. – WebWanderer Commented Jul 22, 2014 at 18:24
Add a comment  | 

3 Answers 3

Reset to default 5 +50

Your approach sounds correct but you don't show what the a, b vectors are and the constant angle is, I'm guessing, just for testing. I did this before so I dug up my code and this is the math I found...

given:
originalVec = unit vector pointing up Y axis (direction of cube top/normal)
targetVec = white vector

Now you want the axis and angle that will rotate originalVec to align with targetVec. The most direct axis of rotation is perpendicular to both input vectors, so take their cross product. That axis is not a unit vector so also normalise it. The angle to rotate (in radians) is the inverse-cosine of the dot-product.

axis = Vector3.cross(originalVec, targetVec)
axis.normalise
angle = inversecos(Vector3.dot(originalVec, targetVec))

quat = AxisAngle2Quaternion(axis, angle)
rot = Quaternion2Matrix(quat)
cube.matrix = rot

Instead of replacing the cube's matrix I think you want to compose it with the new transform...

cube.matrix.multiplyBy(rot)

...but I'm not 100% sure about that. Also, I've seen implementations where AxisAngle2Quaternion takes an angle in degrees. When the input vectors are parallel or opposite the axis is <0,0,0> so that should be tested for. If the cube rotates the wrong way then the cross-product vector parameters are in the wrong order, I never remember which and just try them both. hth.

Edit
I've had a chance to play with Three.js and hacked one of the examples to orient a cube. Comments show where I added stuff and all the orienting math happens in alignCube().
Align and Spin example
Mousing up/down moves the target line. Mousing left/right spins on the line.

Scene objects in Three.js seem to all inherit from Object3D which has a autoUpdateMatrix property set true by default. This needs to be set false otherwise the updateMatrix function gets called which recalculates the matrix from the objects position, scale and rotation properties. Alternately you could assign a different updateMatrix function.

It'd be nice if Three.js had some documentation :)

From Trochoid's example, here's the function that I use to achieve the alignment and spin from the second image:

//object, normalized direction vector, rotation in radians
function align(target, dir, rot) {
    //Three.js uses a Y up coordinate system, so the cube inits with this vector
    var up = new THREE.Vector3(0, 1, 0);

    //euler angle between direction vector and up vector
    var angle = Math.acos(up.dot(dir));

    //cross product of the up vector and direction vector
    var axis = new THREE.Vector3();
    axis.cross(up, dir);
    axis.normalize();

    //rotation to aligns the target with the direction vector
    var rotate = THREE.Matrix4.rotationAxisAngleMatrix(axis, angle);

    //rotation around direction vector
    var revolve = THREE.Matrix4.rotationAxisAngleMatrix(dir, rot);

    //compose the rotations (order matters, can be done other ways)
    revolve.multiplySelf(rotate);

    //assign matrix (autoUpdateMatrix = false)
    target.matrix = revolve;
}

Because nobody has a really good solution, I can at least advice you on how to get closer.

There are 3 possible problems and you have one of them:

  1. The math is not right, or you don't understand it. (Should not be so much a problem here)
  2. Floating points arithmetics are always a problem for computers (Should also not be a problem, because it is a pretty basic one. If your framework can not deliver a solution, then the framework has no value at all for 3d programming)
  3. You don't use the framework right

Because it is pretty likely that No. 3 is the case, try finding a mailing list or support forum or whatever for the framework and talk to the people there. They should be able to explain to you, what you do wrong with their framework. Then come back and post the solution here!

发布评论

评论列表(0)

  1. 暂无评论