I have a golf ball on the ground, and from a raycast, I have the normal which gives me the slope of the ground by the ball.

I have an object which is rendered on the HUD to show that slope to the player.

I have a parent object rotated -90 degrees around X, so that the indicator's Z-axis points up. This way I can do this:

Quaternion yRot = Quaternion.Euler(0, -CameraController.Instance.CachedTransform.eulerAngles.y, 0);
Vector3 displayGroundNormal = yRot * _groundNormal;
_lieIndicator3DParentCachedTransform.rotation = Quaternion.LookRotation(displayGroundNormal);

This, as far as I can tell, takes the ground normal, rotates it around the y-axis so that it shows the proper perspective given the camera's facing. Then it tells that parent object to look in that direction, which aligns its z-axis with the rotated ground normal.

This works, except the object I have also rotates around the y-axis depending on the orientation of the camera. I thought that I was throwing that information away in the second step by keeping only a Vector3 aligned with the ground normal rotated for the camera position.

So I want this: enter image description here

Not this: enter image description here

  • \$\begingroup\$ It's not clear what you're trying to achieve. I don't understand why the camera transform is involved at all if the goal is to show the slope under the ball. Could you refactor? \$\endgroup\$ Mar 25, 2014 at 23:01
  • \$\begingroup\$ The slope under the ball depends on the location of the camera relative to the ball. If the hill slopes east, and the camera is looking east, the thing should slope away from the player. If the camera is looking west, it should slope toward the player. \$\endgroup\$
    – Almo
    Mar 26, 2014 at 3:02

1 Answer 1


Construct the normal relative to the camera:

Quaternion yRot = Quaternion.Euler(0, -CameraController.Instance.CachedTransform.eulerAngles.y, 0); Vector3 displayGroundNormal = yRot * _groundNormal;

Get the yz-plane projection of the adjusted ground normal:

Vector3 yzNormalComponents = new Vector3(0, displayGroundNormal.y, displayGroundNormal.z);

Get the angle between the yz-plane projection and the y-axis:

float zAngle = Vector3.Angle(yzNormalComponents, Vector3.up) * Mathf.Sign(displayGroundNormal.z);

Now rotate the z-axis toward the negative y-axis by that angle:

Vector3 zDir = Vector3.RotateTowards(Vector3.forward, Vector3.down, zAngle * Mathf.Deg2Rad, 3);

Use Quaternion.LookRotation to look in the calculated z direction, with the adjusted ground normal as up:

_lieIndicator3DParentCachedTransform.rotation = Quaternion.LookRotation(zDir, displayGroundNormal);


You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .