#### IanCSc

##### Member

I don't quite have the firmest grasp on this math just yet, but this was a huge help.

I'm currently trying to create something that looks somewhat similar to Octopath Traveler, but FAR less complex.

If I had started this as a 3D project, I'd be billboarding the sprites, but times change, feature creep happens. So now I'm attempting to overlay my existing (basically feature-complete) 2D gameplay engine over some 3D backgrounds.

The main thing I need to do is figure out how to move the 2D camera the same observed distance that the 3D camera has traveled, preferably regardless of the size of the 3D projection or position of the camera (in case I'd like to make adjustments to the viewing angle on the fly, etc.)

This is what I've got, which is a very hacky version of what I'd like to pull off:

In this case, I'm moving the 2d object in the opposite direction of the 3D camera, but I used trial and error to get it to look (almost) right.

PerspectiveChange

Code:

```
///pos3d_get_screen_pos(x, y, z)
var pos = matrix_transform_vertex(global.mat_world_view_projection, loader3D_obj.xto, loader3D_obj.yto, 0);
pos[0] = (1 + (pos[0] / (pos[2] + 1))) * 0.5 * 960;
pos[1] = (1 - (pos[1] / (pos[2] + 1))) * 0.5 * 640;
var old = matrix_transform_vertex(global.mat_world_view_projection, loader3D_obj.xto_old, loader3D_obj.yto_old, 0);
old[0] = (1 + (old[0] / (old[2] + 1))) * 0.5 * 960;
old[1] = (1 - (old[1] / (old[2] + 1))) * 0.5 * 640;
var new;
new[1] = pos[1] - old[1];
new[0] = pos[0] - old[0];
return new;
```

Code:

```
new = PerspectiveChange();
x += new[0]*4.5;
```

**but that's the number I'd be trying to find presumably.**

I'm confident I can figure this out, but I'm definitely a little out of my depth.

Thanks so much for any insight.

@Noah Copeland have you got the thing you were doing working yet? if not I've got this script here:

Code:`///pos3d_get_screen_pos(x, y, z) var pos = matrix_transform_vertex( matrix_multiply(matrix_get(matrix_world), matrix_multiply(matrix_get(matrix_view), matrix_get(matrix_projection))), argument0, argument1, argument2); pos[0] = (1 + (pos[0] / (pos[2] + 1))) * 0.5 * global.screen_width pos[1] = (1 - (pos[1] / (pos[2] + 1))) * 0.5 * global.screen_height return pos`

It takes the xyz in world space of a certain object then performs the same stuff that the shader does then returns the position. You can also use the z coordinate to set the depth while drawing the sprite, which should solve any depth sorting problems. It's intended that you draw the sprites in a 2d view\projection, basically filling the screen like

d3d_set_projection_ortho(0, 0, global.ViewWidth, ViewHeight 0);

Are you using gms1.4? this is the version of the script for that:

If you use this several times, which you will be, it's always better if you precalculate the matrix and save it to a global uniform, just after the 3d view and projection is set:Code:`///pos3d_get_screen_pos(x, y, z) matrix_set(matrix_world, matrix_multiply(matrix_get(matrix_world), matrix_multiply(matrix_get(matrix_view), matrix_get(matrix_projection)))) var pos = d3d_transform_vertex(argument0, argument1, argument2); pos[0] = (1 + (pos[0] / (pos[2] + 1))) * 0.5 * global.screen_width pos[1] = (1 - (pos[1] / (pos[2] + 1))) * 0.5 * global.screen_height d3d_transform_set_identity() return pos`

Then you can set that at the start of the script instead, or even better, set it before the script, then execute the script several times. And always remember to d3d_transform_set_identity() afterwardsCode:`global.mat_world_view_projection = matrix_multiply(matrix_get(matrix_world), matrix_multiply(matrix_get(matrix_view), matrix_get(matrix_projection)))`