Rotate object towards multiple cameras

Hi all

For a research project, I have the following problem:

A scene contains several objects which are used to visualize special data. The kind of data requires the objects to be propertly rotated towards the camera. This is done by scripts on the objects and works well.

Now, for multiview rendering (e.g. stereoscopy) I need a multiple camera setup. Is it possible to have the objects rotated towards each camera independently? I thought about something like checking in the objects scripts for which camera is rendered and do the corresponding rotation. Honestly, I doubt that the camera rendering is done each after another in a serial manner.

Any Ideas?

Thanks a lot.

Cameras render in an order defined by you (depth), and they only render the layers you ask them to (by default, everything).

You could have two layers - Camera1 and Camera2. Each camera renders exactly one of the ‘camera’ layers.

You’d need to have multiple graphics (GameObjects), as well - the first would be set to layer Camera1, and it would follow the camera assigned to display that layer - and so on for the rest of the graphics.

That means I have to multiply the objects by the number of cameras. Thats what I wanted to avoid. Wouldn’t that influence memory and runtime?

My hope was to get a solution where I can control it by scripts to keep it as generic as possible. It further means that I need some smart init scripts which do the multiplication of the object and the “connecting” to the cameras, to be able to provide “single” objects and prefab camera configurations to the user.

Thanks for the layer hint.

Oh hey I should have remembered this function earlier -

OnPreRender

You’d have to attach it to each camera, but essentially you could rotate each object before each render (if the cameras can move, that is):

class StereoCamera extends MonoBehaviour {
  /* STATIC */
  static private var stereoCameras : List.<StereoCamera>;

  static function NewStereoscopicObject( obj : Transform ) {
    for ( var sc : StereoCamera in stereoCameras ) {
      sc.objects.Add( obj );
    }
  }

  /* NONSTATIC */
  private var objects : List.<Transform>;
  private var myTx : Transform;
  
  function Awake() { 
    if ( !stereoCameras ) stereoCameras = new List.<StereoCamera>();
    stereoCameras.Add( this );
    objects = new List.<Transform>();
    myTx = transform;
  }

  function OnPreRender() {
    for ( var t : Transform in objects ) {
      t.LookAt( myTx );
    }
  }
}

Then making an objects behave stereo-ly should be as easy as:

class StereoscopicObject extends MonoBehaviour {
  function Start() {
    StereoCamera.NewStereoscopicObject( transform );
  }
}

If the stereo-y objects can be removed at runtime you’ll need to add some cleanup (List.RemoveAt / List.Remove) in the StereoCamera script, but that should hopefully get you going in the right direction.

Wow, that’s cool! Exactly what I need. This one can easily be extended to any multiple camera setup.

Works well and is pretty fast. Only problem I have not solved yet is that the objects always “look at” the other cam. I.e. objects in cam1 are rotated towards cam2 and vice versa…

Only thing to add to the camera script, for those not so familiar with scripting, is import System.Collections.Generic; at the beginning.

Thanks a lot for that solution.

That’s weird, PreRender seems like the appropriate function, but it sounds like the transform isn’t being rotated until after render has completed.

You might try some of the other OnX functions in Camera. OnPreCull looks like it’s earlier than PreRender, or you could try LookAt( Camera.current ) to see if somehow I don’t even know this is silly.

If those changes don’t work, there’s the very silliest option…

int myIndex;
static List.<Transform> order;

function OnPreRender() {
  if ( !order ) order = new List.<Transform>(); // actually, do this in awake, not here
  if ( order.Contains( this ) ) {
    // for each object
    object.LookAt( order[ (myIndex+1) % order.Count ] );
    // end for
  } else {
    order.Add( transform );
    myIndex = order.Count-1;
  }

Order the cameras by the order they render in and hope that stays consistent (it should!). Then orient the objects towards the NEXT camera in line.

How very silly.

It really makes a difference if OnPreCull() or OnPreRender() is used. The result with one is exactly the oposite as with the other one (at least in a 2 cam setup). It seems that when using OnPreRender, which I assume is called after OnPreCull, culling has already fixed the objects for rendering and any manipulation has no effect for the current frame. Obviously this makes sense from a culling point of view, because transformation influences culling results.

Thanks for your help!