Yonathan
Yonathan

Reputation: 1313

Rotate geometry to align to a direction vector

I've been trying to get my generated geometry to align with a direction vector. To illustrate what my current problem is:

Example of the problem

My current solution in code for this triangle example (This code is run for all the nodes you see on screen starting at the split, I am using the GLM math library):

glm::vec3 v1, v2, v3;

v1.x = -0.25f; 
v1.z = -0.25f; 

v2.x = 0.25f;
v2.z = -0.25f;

v3.x = 0.0f; 
v3.z = 0.25f;

v1.y = 0.0f;
v2.y = 0.0f;
v3.y = 0.0f;

glm::mat4x4 translate = glm::translate(glm::mat4x4(1.0f), sp.position);
glm::mat4x4 rotate = glm::lookAt(glm::vec3(0.0f, 0.0f, 0.0f), sp.direction, glm::vec3(0.0f, 1.0f, 0.0f));

v1 = glm::vec4(translate * rotate * glm::vec4(v1, 1.0f)).swizzle(glm::comp::X, glm::comp::Y, glm::comp::Z);
v2 = glm::vec4(translate * rotate * glm::vec4(v2, 1.0f)).swizzle(glm::comp::X, glm::comp::Y, glm::comp::Z);
v3 = glm::vec4(translate * rotate * glm::vec4(v3, 1.0f)).swizzle(glm::comp::X, glm::comp::Y, glm::comp::Z);

The direction vector values for point A:

The direction vector values for point B:

Edit 1 (24/11/2013 @ 20:36): A and B do not have any relation, both are generated separately. When generating A or B only a position and direction is known.

I've been looking at solutions posted here:

But I haven't been able to successfully rotate my geometry to align with my direction vector. I feel like I'm doing something rather basic wrong.

Any help would be greatly appreciated!

Upvotes: 1

Views: 3273

Answers (1)

Gene
Gene

Reputation: 46960

If A and B are unit vectors and you want a rotation matrix R that transforms B so that it aligns with A, then start by computing C = B x A (the cross-product of B and A). C is the axis of rotation, and arcsin(|C|) is the necessary rotation angle.

From these you can build the required rotation matrix. It looks like glm has support for this, so I won't explain further.

NB if you are doing many, many of these in performance-critical code, you can gain a bit of speed by noting |C| = sin(theta), sqrt(1 - |C|^2) = cos(theta) and computing the matrix yourself with these known values of sin(theta) and cos(theta). For this see for example this discussion. The glm routine will take your angle arcsin(|C|) and proceed immediately to compute its sin and cos, a small waste since you already knew these and the operations are relatively expensive.

If the rotation is about some point p other than the origin, then let T be a translation that takes p to the origin, and find X = T^-1 R T. This X will be the transformation you want.

Upvotes: 2

Related Questions