Change camera pivot point (SOLVED)

Hey guys, I’m stuck again. I have added @Bjorn_Ritzl’s custom render script to lock my aspect ratio regardless of the window size. Worked! Then I added a camera to my scene and positioned it: This should be the eye- & look_at position of this camera.

Here’s my project setup

Unfortunately the origin of the render view and the origin of the camera are both at lower left corner of the window. I need a way to change camera’s pivot point on which it centers itself. The fallowing sketch shows a red rect, which is the current window position when running the game. I need the yellow option!

I know I could change render.set_projection(vmath.matrix4_orthographic()) inside my render script, BUT I think there is also another way, since the @render: listens for a message "set_view_projection" which should set a matrix center for the current viewport…

I try to create my own look_at_matrix and send it to the render script, whenever I want to change camera’s pivot point.

Unfortunately this seems not to work. Here is what my CameraController script does:

2 Likes

You could calculate a projection yourself in a go and send it to the render script. But easiest is probably to just alter the projection in render script. The camera component sends the messages to the render script automatically.

local w = render.get_width()
local h = render.get_height()
local proj = vmath.matrix4_orthographic(- w / 2, w / 2, -h / 2, h / 2, -1000, 1000)
render.set_projection(proj)
1 Like

Thank you. I did it that way and it worked. But would you be so kind to post the code to set the matrix from inside a game object?

The camera component sends the messages to the render script automatically.

Is that the reason, that I get this error: ERROR:SCRIPT: game/renderer/CameraController.script:7: Field id not specified in table
when I try to do msg.post("@render:", "set_view_projection", {view = ...})?

The camera component never got the love it deserves, just like the surrounding areas, like “set_view_projection”. This is what you need to do:

msg.post("@render:", "set_view_projection", {id = hash("my_camera"), view = my_view, projection = vmath.matrix()})

This is what the camera component does, set_view_projection is a “system” message that needs to be fully specified. Not by design, but by accidental implementation. :wink:

2 Likes

I haven’t tried what you are doing but if you want to manually set the view and projection you should not acquire camera focus. When you do that the camera will send view and projection each frame.

I believe id is a number sent by the camera, probably to allow for muliple cameras (in the future). Try
setting id to 0 or 1. (I haven’t tested).

EDIT: Oh, see Ragnar’s post avove!

2 Likes

Ahhh, I see. Now I understand better whats going on. Thank you both!

1 Like

Actually, you could have logic in your render script that deals with separate cameras to, for instance, render a split screen view. Just check the id field of the incoming message. You can also send custom messages to the render script with any name, not just “set_view_projection”.

1 Like

@sicher Sounds interesting - I’d like to try, but wouldn’t I need two predicates which I render separately then? (Sorry second day with defold :sweat:)
As I understand it from the docs, I could set two cameras to acquire_camera_focus, but the latest overrides the first (I assume because by default they send the same id?). How would I manage then drawing both with different projection matrices?

One camera will overwrite the other since the default render script does not take the id into account in on_message(). What you need to do is to save the view and projection for the cameras separately and then use them and draw all predicates twice, one for each camera.

Oh man, this is so confusing… @sicher The message_id send from both camera’s seem to be the same… here’s the output from my render_script

Both camera’s have acquire_camera_focus and so they are automatically dispatched to my render_script. I only printed out what I got and the output was repeating the same message_id over and over. Am I doing something wrong again?

If I was to set id,view and projection manually as shown by @Ragnar_Svensson then I seem not to be able to compute my values, as I can not get_window_width() and …height() inside a component. Therefore, I would need to use a lua module, which sounds to me like a hack, to be honest.

Hmmm, you print message_id and not message.id.

Btw, It is not impossible that the camera component sets the id field to somehing generic and not its real id. @Ragnar_Svensson do you know?

oh, yes, I tested both. Neither one is working though (at least for me)

1 Like

Yes, confirmed that the camera code is idotic and hard coded, every camera sets the id to hash(“game”). You can still send the message yourself and specify the id-field to anything you want though.

2 Likes

id doesn’t even really matter for current implementation of camera components because older cameras don’t even get to send their information. I just tested to confirm if it was that it’s the last message render gets that sticks, or if older cameras other than the one with the most recent focus. So current documentation is correct, and having multiple camera components wouldn’t matter even if id was being sent properly.

Solved in 1.2.164