How to align an object with a normal?

question

#1

I’m just trying to figure out how to rotate an object to line it up with a normal from a cast physics ray node.

I can get the normal.
I can rotate the object.

I’m just not sure how to convert the normal into a rotation for the Set Rotation node.

How could we go about this?


#2

Did you try to use look at node? Maybe you even don’t need to cast the ray


#3

Hi,

here’s how you align one vector with another using quaternions and haxe:

var v1 = new Vec4(0, 1, 0, 0);
var v2 = new Vec4(0.707, 0.707, 0, 0);

q = new Quat();
// calculate Quaternion which transforms v1 to v2
q.fromTo(v1,v2);
q.normalize();

// sanity check, transform v1 using the calculated quaterion
var v = new Vec3(v1.x, v1.y, v1.z);

n = qMult(q, v);
// result must be v2
trace(n);

I did not find a haxe method to apply the quaternion to a Vec3 so I implemented qMult as follows:

public function qMult(quat:Quat, vec:Vec3): Vec3{
     var num = quat.x * 2.0;
     var num2 = quat.y * 2.0;
     var  num3 = quat.z * 2.0;
     var num4 = quat.x * num;
     var num5 = quat.y * num2;
     var num6 = quat.z * num3;
     var num7 = quat.x * num2;
     var num8 = quat.x * num3;
     var num9 = quat.y * num3;
     var num10 = quat.w * num;
     var num11 = quat.w * num2;
     var num12 = quat.w * num3;
     var result = new Vec3();
     result.x = (1.0 - (num5 + num6)) * vec.x + (num7 - num12) * vec.y + (num8 + num11) * vec.z;
     result.y = (num7 + num12) * vec.x + (1.0 - (num4 + num6)) * vec.y + (num9 - num10) * vec.z;
     result.z = (num8 - num11) * vec.x + (num9 + num10) * vec.y + (1.0 - (num4 + num5)) * vec.z;
     return result;
 }	

source: https://answers.unity.com/questions/372371/multiply-quaternion-by-vector3-how-is-done.html


#4

Thanks for the reply. The issue with this as I understand it, is that this will make my object point to the centre of the other object, rather than aligning with it’s surface normal. That’s fine for a sphere, but not for other shapes.

EDIT: Hang on… maybe you’re on to something… I was only thinking about “Look at” in terms of looking at the terrain object coordinates… But if I used the Raycast Hit co-ordinates instead… it just… might… work…


#5

Maybe I’m misunderstanding something… but I don’t have two vectors. I’m trying to align a player’s rotation (quaternion), with the surface normal of the terrain below them (vector3).

o I’m trying to get from the vector3 I have, to a rotation (quaternion) that I can set to make the character align to the terrain.


#6

Armored_Blob:

sorry, I had read your question correctly but thought that your problem was to align to vectors. Now, I do not fully get what you want to achieve.

You have an object (your player) and it has a quaternion describing it’s rotation. You also have a terrain wiht a normal. How would you like your player to be oriented (probabaly perpendicular to the surface, but facing which direction)?


#7

Ideally, the object would rotate around its local x and y axis’ to align with the terrain surface normal while keeping the rotation around the z axis (the direction the player is facing) untouched.

I posted in Logic Nodes, because I was hoping that there was some kind of “Vectors to Rotation” type node, where you just plugged in two vectors (an align and an up/forward vector) and it output a rotation.

Maybe this needs to be done with Haxe, which is fine, or maybe this is a good case for a custom node.


#8

I think I figured it out. Try this ( I haven’t tested myself ):

So the normal is a vector that points in the direction of the normal, so adding that to the objects current location will yield a point in space that is in the direction of the normal, away from the object. Telling the object to look at that point, from its current location should point the Z axis of the object in the direction of the normal.


#9

So, in this case, both the Get Location and the Set Rotation nodes are set to the player object, and the from and to fields in Cast Physics Ray are the beginning and end points of the ray beneath the character object, right?


#10

Yep. When you leave any object selector blank in nodes, it defaults to the object that the trait is applied to.


#11

Hmmm… so I’m still getting strange behaviour from your idea above @zicklag

Here’s my node setup (Suzanne is the character):

  1. The “move” group that moves the character forwards / backwards / left / right on its local axis works fine by itself.
  2. The group casting a ray below the character to find the ground works fine. When I set up a cube, setting it’s location to the ray hit location, it correctly always places the object at the surface of the ground object under the character.
  3. The “Align to ground” group, is straight from your post above.

The weird thing is… when the normal from the ray group is plugged in to your alignment group, suddenly all movement stops completely, too. The character doesn’t move one pixel. If the normal isn’t plugged in, movement works fine. I’m at a loss to understand why… I mean, the only thing your setup sets is the rotation…


#12

Do you know if there are any errors in the console? Maybe that is the cause of the complete lack of movement?


#13

Yes, actually there is:

Uncaught exception:
                        _this1.x = hitNormalWorld.x;
                        ^
TypeError: Unable to get property 'x' of undefined or null reference
   at get (krom.js:735:4)
   at armory_logicnode_LogicNodeInput.prototype.get (krom.js:874:3)
   at get (krom.js:1425:3)
   at armory_logicnode_LogicNodeInput.prototype.get (krom.js:874:3)
   at get (krom.js:896:3)
   at armory_logicnode_LogicNodeInput.prototype.get (krom.js:874:3)
   at run (krom.js:1157:3)
   at armory_logicnode_LogicNode.prototype.runOutput (krom.js:663:6)
   at update (krom.js:1132:3)
   at iron_App.update (krom.js:2267:3)

Here’s the file itself:
look node test1.blend (981.5 KB)

Does this look like an Armory bug?


#14

It’s actually happening because, whenever you do a ray-cast that doesn’t hit anything, the hit and normal sockets are undefined which throws an exception when attempting to plug that in to any node expecting a vector.

You can try using the Is Not None node to guard for those conditions. I experimented a little, but it was still running into that exception. I’m probably missing something. I might try a little more, but that should give you a start to figuring it out.

As a general troubleshooting rule, if you ever run into crashes like this when working with nodes that say TypeError...undefined or null reference, then it means that some type of value you are trying to use is set to nothing for one reason or another, and a different node is trying to use that value when it doesn’t exist.

Technically it is just a detail of the way that the node works, but it might be something that could be improved on.