Rotating bilboard only on one local axis

So I’m making a table that has four billoard legs. Each one of this legs should be detachable and have it’s own box collider. That’s why I make the billboard planes child of the “physical” legs.

Now I need to make the LegPlanes billboard objects look at the camera, but rotate only on one axis.
I did something like this:

void RotateToCamera()
    {
//rotating leg billboard with leg parent
         Plane.transform.rotation=transform.rotation;
//taking it's local rotation in this state
        float xRot=Plane.transform.localEulerAngles.x;
        float yRot=Plane.transform.localEulerAngles.y;
        float zRot=Plane.transform.localEulerAngles.z;

//now rotating billboard with the camera
 Plane.transform.forward=Camera.main.transform.forward;

//setting new local rotation on all axises. if object can rotate in certain axis
//(AxisCanRot variable) it's getting local value from leg parent, if can't rotate
// on certain axis it takes local rotation affected by camera position     
float quatX; float quatY; float quatZ;
        if(xAxisCanRot){quatX=xRot;}else{quatX=Plane.transform.localEulerAngles.x}
        if(yAxisCanRot){quatY=yRot;}else{quatY=Plane.transform.localEulerAngles.y}
        if(zAxisCanRot){quatZ=zRot;}else{quatZ=Plane.transform.localEulerAngles.z}

//now I put them all together as a new local rotation 
Plane.transform.localRotation=Quaternion.Euler(quatX,quatY,quatZ);
    }

In this code im having xAxisCanRot and yAxisCanRot true, and zAxisCanRot false, so legs will only rotate around local z axis.

It all seems to work, Im rotating camera around chair and it works as intended, but when I knock over the chair and legs are upside-down or sideways there are some weird bugs.
The legs rool no longer follows the camera, but kinda other way round.

Is there a way to do this right? Maybe it’s because legs are child to another parent, but I detached them and still they are acting the same

Don’t futz with Euler angles. They are terrible.

So the fundamental algorithm should be this:

  1. convert camera’s position into coordinates local to “chair0Leg0”, using transform.InverseTransformPoint. From this point on, chair0Leg0 is the space in which all of our logic will operate.
  2. “flatten” this converted position by setting its Y to 0
  3. Set chair0Leg0Plane.localRotation to Quaternion.LookRotation(flattenedCamera)

That should pretty much be it. Let me know if any of these steps needs further clarification.

1 Like

That really kinda work, I put

Vector3 newCamPos=transform.InverseTransformPoint(Camera.main.transform.position);
        newCamPos.z=0;
        Plane.transform.localRotation=Quaternion.LookRotation(newCamPos)*Quaternion.Euler(0,90,90);

at the end I have to add this Quaternion because my legs were shifted (the texture exactly)

I get something promising, only weird thing is that every half of rotation the plane is upside down, like immedietly:

this shift occurs almost exactly when legs are in certain rotation even if i dont change camera, just rotate table by itself it still happens

Can you log your newCamPos and see where the “flip” point is? I assume it’s going to be when it crosses 0 on either X or Z. If so, you could workaround the issue by adding a 80 rotation if the X or Z is in that state. I’m not sure what the actual mathematical issue would be.

1 Like

That was the case, thanks :slight_smile: If newCamPos.x was more than 0, I change this additional Vector x to 180 and all works :slight_smile: