1
votes

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

  • A = Correctly aligned geometry ( just a triangle for testing )
  • B = Incorrectly aligned geometry

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:

  • x 0.000000000 float
  • y 0.788205445 float
  • z 0.615412235 float

The direction vector values for point B:

  • x 0.0543831661 float
  • y 0.788205445 float
  • z -0.613004684 float

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!

1

1 Answers

2
votes

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.