# Convert LookVector/Surface Normal to rotation

Hello!

I would like to know how to convert a LookVector / a Surface Normal to rotation.

For example, a normal of (0, 1, 0) would equal to (0, 0, 90).

Thanks !

Do you mean converting degrees to a rotation value? (Like math.rad)

If you are just interested in the z axis rotations then itâ€™d be

``````(math.cos(angle), math.sin(angle), 0) <- (0,0,math.deg(angle))

(x, y, 0) -> (0,0,math.deg(math.atan2(y, x)))
``````

Yeah, I need to convert all axises so this wonâ€™t work.

If you want a full description of a rotation you need more than one normal as an input. Also I imagine itâ€™d be easier to just use the cframes rather than orientation vectors

Iâ€™m doing a raycast so the only thing that I have is a normal. Iâ€™m trying to remake a simple version of the scan test demo which would be compatible with my phone vr module.

I need to convert normal to rotation to rotate the triangle the right way.

Not sure what scan test demo is or what triangles youâ€™re using. The normal should correspond to the up/right/look vector of the CFrame you need

A lookvector doesnâ€™t contain enough data to describe rotation and Iâ€™m not sure where youâ€™re getting the 90 Z rotation from

1 Like

Ok, so what iâ€™m essentially trying to do is like sticking a paper on a surface. In my case, I need the normal to determine which direction my paper will be facing.

Yeah look vector is not enough information

But from my knowledge there are only two methods to make up for this lack of information

One:

For more info this uses cross product with the direction vector and UpVector to generate the rest of the axises.

This is good if you donâ€™t care about the rotation along that surface normal axis letâ€™s say for a circular/cylindrical object like a blood puddle.

Second:

Getting the shortest rotation from one vector to another vector. This allows for rotation along that surface normal axis which is good for systems like a character controller.

1 Like

Just before you replied, I tried that but it didnâ€™t work which is weird.

From what Iâ€™ve read you would want to set the paperâ€™s CFrame with CFrame.fromMatrix
Something along the lines of

``````local forwardVector = RaycastResult.Normal
local upVector = Vector3.new(0, 1, 0)
local rightVector = forwardVector:Cross(upVector)
local upVector2 = rightVector:Cross(forwardVector)

Paper.CFrame = CFrame.fromMatrix(RaycastResult.Position,rightVector,upVector2)
``````

To prevent the paper from clipping into the wall it is placed on you may want to add the Normal times the thickness of the paper to the position, like this
Paper.CFrame = CFrame.fromMatrix((RaycastResult.Position+RaycastResult.Normal*Paper.Size.X),rightVector,upVector2)

Isnâ€™t there column missing Vz? Iâ€™m asking it here as I personally donâ€™t understand anything in rotation matrixes.

When left blank â€śthe third column is calculated as [vx:Cross(vy).Unit]â€ť from the documentation. Pretty sure its more efficient to let Roblox do it internally but I could be totally wrong

Tough, I tried it and it yielded the same result as using CFrame.lookAt ( which just looks to have some axis inverted ) but it sometimes didnâ€™t work at all ( setting the Y to 9999â€¦ ) and created weird artifcact where the part would disseapear randomly.

As I said, the only problem that I can see with the LookAt is that some axises are inverted.

What do you mean by axes are inverted exactly? It seems like it may be fixed by multiplying by a constant CFrame. E.g. `CFrame.LookAt(â€¦) * CFrame.Angles(math.rad(90),0,0)`

3 Likes

Could I see a snippet of your code? or maybe a more detailed explanation of what exactly you are trying to do, because Iâ€™m having no issues with what I have sent.

This is what I mean, It is changing with the normal but never the right direction.

Yeah that looks correct, just rotate it by a fixed amount afterwards. Lookvector is Z axis, but those papers donâ€™t appear to be Z forward.

1 Like

So, I managed to fix the issue by changing CFrame.Angles(math.rad(90), 0, 0) to CFrame.Angles(0, math.rad(90), 0).

In the final, it looks like this
`Part.CFrame = CFrame.lookAt(Position, Position + Normal) * CFrame.Angles(0, math.rad(90), 0)`.
The variables name are modified for simplicity.

3 Likes