Archived

This topic is now archived and is closed to further replies.

CGameProgrammer

Applying a vector to a normal

Recommended Posts

Let's say there's a flower on the ground. Its facing mostly straight up, but slightly bent, so let's say its vector is the normalized version of (0.1, 1, 0.2). Now let's say there's a nearby brick wall. Its normal is (1, 0, 0) meaning the wall is facing right. Now if I picked up the flower and stuck it into the brick wall, such that it's sticking out of the wall at the same orientation it was from the ground, then what is the flower's new vector? Its vector relative to the brick wall is still (0.1, 1, 0.2) (normalized of course), but what's its absolute vector? Its vector would be close to (1, 0, 0), and in fact if the flower had been sticking straight up from the ground, that would be its new vector exactly. That's probably the best way I can explain it. So, how would you calculate the new vector of a vector applied to a normal? ~CGameProgrammer( );

Edited by - CGameProgrammer on February 19, 2002 6:04:14 PM

Share this post


Link to post
Share on other sites
BTW, in this example I know you can switch the Y with the X and so on, but this is just an example. The actual vectors and normals can be anything and I need to calculate the new vector.

~CGameProgrammer( );

Share this post


Link to post
Share on other sites
Your flower is on the ground, and it is facing up, in the direction (0, 1, 0). The wall is (1, 0, 0)... Simply rotate your vector exactly 90 degrees, in this case around the Z axis. Even in your example where the flower isn't exactly (0, 1, 0), rotating it 90 degrees will make it stick out of the wall in the same orientation as it stuck out of the ground. For any other case where you have one vector pointing up relative to some plane and you want to keep it pointing up relative to another plane look up you might try solving the equation linearly. It's been a while but having v*m=v1, where v is your original vector, m is some rotation matrix, and v1 is your new vector, you can find m if you know v and v1.

Now, the question you should be asking yourself is 'should my flower be sticking out of a wall?' ...It's a tough call

------------
- outRider -

Edited by - outRider on February 19, 2002 7:11:55 PM

Share this post


Link to post
Share on other sites
I''ve done some preliminary work on this, there IS a way to solve your problem without using any trigonometric functions, but the linear algebra involved is pretty funky.

I should have a solution by tomorrow, so check back and I''ll let you know.

Incidentally, the solution involves only multiplication and division of vector elements.

George D. Filiotis
Are you in support of the ban of Dihydrogen Monoxide? You should be!

Share this post


Link to post
Share on other sites
Well I solved it, basically. Rotation is not feasible because the normal (orientation of the wall in this example) and vector (of the flower in this example) can be anything. I merely used the wall and flower as an example. Usually, the normal and vector would not be 90 degrees apart, or any amount of degrees apart along a single axis of rotation.

The way I did it was by using not just the normal of the wall but three vectors: The vector along the X-axis of the wall, the vector along the Y axis (which is the normal), and the vector along the Z-axis of it. The new vector would be this:

NewVector = (Wall.XVector * Flower.X) + (Wall.YVector * Flower.Y) + (Wall.ZVector * Flower.Z);

I had been thinking that it would be simpler than that, but then I realized that given only the wall''s normal and the flower vector, the flower could be applied to that normal but still rotated around it. There would be no way to place it using only those two vectors.

~CGameProgrammer( );

Share this post


Link to post
Share on other sites
I'm still very interested in seeing your solution, Symphonic. Technically I shouldn't really need both the X-vector and Z-vectors of the wall, only one would be enough, basically to anchor the flower at a set rotation around the wall's normal. Or even a single scalar would do, I guess... well I'd like someone else's solution to this. It's a simple problem in a way.

~CGameProgrammer( );



Edited by - CGameProgrammer on February 19, 2002 12:38:58 AM

Share this post


Link to post
Share on other sites
Take the normal to the ground
Take the normal to the wall
Take the cross product of the two
This is the axis around which you rotated.

Take the normal to the ground
Take the normal to the wall
Take the dot product of the two
This is the cosine of the angle of rotation.

Share this post


Link to post
Share on other sites
Well, what I'm deriving is a general solution for a transformation matrix as follows.

Given vectors v and u in three dimensional space, there exists a 3x3 matrix A such that:

Av = u

However, if the two vectors given are not unit vectors, then there is a certain amount of scaling. Which is the part I'm trying it factor out. This is a really huge problem though, I spent three hours on it with seemingly no acceptable solution in sight. It's easy if you let yourself use trig functions, or square-root functions, but I'm restricting myself to finding a multiply/divide solution.

Edited by - symphonic on February 20, 2002 3:23:14 AM

Share this post


Link to post
Share on other sites
See, that''s what I thought as well, but it isn''t as simple as that.

Trust me, this is a really cool and very screwed up problem.

The trick lies in understanding that you''re actually solving for sets of four variables. Before you can generate a final matrix, you have to generate three separate rotation matrices and multiply them together. The reason there isn''t an infinite number of solutions is that we''re not working from basic lines. The vectors normals have to be unit vectors in order to be useable.

Share this post


Link to post
Share on other sites
Fruny, the cross product of the wall''s normal and ground normal is perpendicular to them both, which is wrong. In the example I gave, you would get a vector near (0,0,1). But the actual vector should be close to the wall''s normal, since the flower''s orientation was close to the ground normal.

~CGameProgrammer( );

Share this post


Link to post
Share on other sites
ok, going to give you guys a taste of what the final solution is going to look like (because I''ve gotten this far, and maybe you can solve it for me from here, and I''ll look stupid if I don''t).

Given two unit vectors in 2D space, both of which are normals to a line.

v=(a, b), u=(c, d)

a rotation about the origin (we assume that these vectors are based at the origin as well) can be described by the following.

u = x*v + y*w

where w is the normal to the vector v {w = (-b, a)}, and x, y are scalar multiples of the two perpendicular vectors.

This is guaranteed to be true, because:

span(v, w) = ALL of 2D space

So, to solve, we know:

x(a, b) + y(-b, a) = (c, d)

which can be represented by this Augmented Matrix

+a, -b| +c
+b, +a| +d

Which, after a few row operations, ends up like this:

a*a*a*b, 0| b*c*(a*a+1)-a*d
0, a*a+b*b| b*c-a*d

from which we can deduce the equations:

y = (b*c-a*d)/(a*a+b*b)
x = (b*c*(a*a+1)-a*d)/(a*a*a*b)

So x, y are your rotation factors, and they create the rotation matrix:

(x, -y)
(y, x)

If you have a way of doing so, please test this hypothesis, if it works, then I can extend it to three dimensions.

Share this post


Link to post
Share on other sites
I made a mistake, the values of x and y have to be normalized for this to work.

So it isn''t perfect, two sqrt() operations are necessary:

// before creating the transformation matrix
x = x / sqrt(x*x + y*y)
y = y / sqrt(x*x + y*y)

but I realitvely sure about the matrix.

George D. Filiotis
Are you in support of the ban of Dihydrogen Monoxide? You should be!

Share this post


Link to post
Share on other sites
An interesting tidbit:

In order to make a rotation in three dimensions, a plane is described by the two vectors given (v & u, we're trying to rotation from v to u).

So in the end, the previous solution would be used for a rotation in a plane, except that that plane would be described in terms of 3-element vectors, so the final transformation is 3x3 (or 3D space to 3D space).

There's another way to do it which is marginally similar, but this method would be particularly useful for object-space to world-space transforms.

Given that the object which is going to be used is represented in object-space with respect to (1, 0, 0) - meaning that it points along the x axis - and our final desired direction in world space is given by two vectors, one to describe the direction the object is pointing, and one more to describe which direction the object orients as up.

Using that information we can do three separate baseic-planar transformations to get the object pointing in the direction we want it to. Again, without the use of trig. functions.

The first rotation is in the plane (y,z) (roll), the base vector is (1, 0). We then take the y and z components of the upward orientation vector of the object, and substitute them for the components of the target planar vector and solve for the rotation matrix (as shown two posts ago).

The resultant matrix:
(m -n)
(n m)

fits into a 3D transform like so:
(1 0 0)
(0 m -n)
(0 n m)

Then we solve for the rotation in the (x,y) plane (pitch), with vectors (1, 0) and the x and y components of the final directional vector. After solving we take our planar rotation matrix:
(a -b)
(b a)

And make a 3D transform:
(a -b 0)
(b a 0)
(0 0 1)

Finally we solve for the rotation in the (x,z) plane, again using (1, 0) as our starting vector and finishing with the x and z components of our target directional vector. Solving, we get:
(p -q)
(q p)

which becomes:
(p 0 -q)
(0 1 0)
(q 0 p)

Then to finalize our transformation matrix, we multiply the three 3x3 matrices we got this far to get a final matrix:

(y-z matrix) * (x-y matrix) * (x-z matrix)
==
-First Row-
p
-b*m*p-n*q
b*n*p-m*q
-Second Row-
b
a*m
-b*n
-Third Row-
a*q
n*p-b*m*q
b*n*q+m*p

So if you pad that with another row and column with a 1 in the bottom right, you can multiply by your scale and transpose matrices, and voila! you have a Object-to-World transformation matrix...

If there's any interest, I could probably re-post all of this in one coherent section

EDIT: dumb mistake

Edited by - symphonic on February 24, 2002 3:15:44 AM

Share this post


Link to post
Share on other sites
quote:
Original post by CGameProgrammer
But the actual vector should be close to the wall''s normal, since the flower''s orientation was close to the ground normal.



Read more carefully : what I gave you is the rotation to apply to the original vector (flower on ground) to get the new vector (flower on wall).

Share this post


Link to post
Share on other sites
Oh, right, Fruny. My mistake. So you''re suggesting a method in which I find out how to rotate from the ground''s normal to the wall''s normal, and apply that rotation to the flower normal. Makes a lot of sense - for some reason I didn''t think of that. I''m still using my X/Y/Z wall-vector method because it works and I know those vectors anyway, but your way is definitely something I will have to keep in mind.

My attention span is too limited to follow Symphonic''s matrix code, I''m afraid

~CGameProgrammer( );

Share this post


Link to post
Share on other sites