[solved] How to achieve this type of camera

Hi!

Lately I’ve played the old Breath of Fire IV game for the PSP, and I really liked the way that the 3D environment and 2D sprites work together in the game. I’ve read somewhere that the game used an isometric camera, and at the first glance it seems that way:

However, when I started playing, I realised that a perspective view is actually used for the backgrounds. The perspective is subtle, but it’s there, and it makes the environments seem much more dynamic than a simple isometric cam:

However, the character sprites are perfect rectangles no matter how they are positioned in relation to the camera - there is no skewing or distortion:

I’m really curious as to how this could be achieved. Could this be a combination of a perspective camera for the 3D environment and an orthographic camera for the billboards? I’m puzzled >:(((

Are you certain characters are sprites and not 3D models, with only rotations of say… 15° allowed ?
It seems to be 3D to me, with cellshading only on characters, especially on this video:


at 7’ when the camera is rotating, the girl is facing the cam then the model is showed rotated by a fixed amount to show a 3/4 profile.
In fine, it is a 3D camera with perspective, just placed at an angle like it is used to be in 2.5d isometric games (about 30-35°).

Hey - I’m 100% sure that these are 2D pixel sprites. In fact you can see the sprites for the girl here with rotation:

I can see how they can seem 3D at first, just because of how well crafted they are.

I realise also that this is perspective camera for the 3D environments, what I’m wondering about is what camera has been used for the characters, and how the two were combined so seamlessly. Since, as I wrote, the perspective does not seem to apply to the character sprites to avoid distortion and skewing.

It’s hard to tell just by looking at the video above, but it seems like the sprite rectangle for a character is always the same size, which indicates that only the position of the sprites is affected by the camera. I think you can get this effect by applying the perspective camera to the position of the characters and then just drawing a billboarded rectangle there.

You can use SpriteBatch to do this if you calculate the depth at the transformed position (SpriteBatch lets you pass a fixed depth value) and enable depth read/write. You might run into issues with depth if characters are close to the environment. If that happens it might be better to write a custom shader that calculates a depth value according to the perspective camera rather than using a fixed value over the whole sprite.

2 Likes

Actually on the occassions when the camera zooms in or out, the size of the sprites decreases, but I guess they could simply be scaled depending on the distance from the camera.

It’s hard for me to figure out how this could have been done, and there is no info on the internet about the development of the game (well, there never is, is there). I wish people would publish books on how a given game was coded, the same way they publish artbooks etc. from these games.

I will fiddle around with it and see what I can come up with.

1 Like

I believe Bastion did the opposite, where the backgrounds were all 2D images and the characters were 3D models. And it was made with MonoGame. You may find useful reading around that.

Yeah, though from what I see Bastion just uses a normal orthographic camera for both the 2D environment and the 3D characters. Which is cool, it gets the job done, and frankly I should just go with that as well, since I already have an ortho cam set up for my game. It’s just that I really really liked the camera in Breath of Fire IV for some reason, and I’m really intrigued as to how they made it work.

On a side note - from what I’ve read, the camera work in Breath of Fire IV is the no. 1 thing that the critics bashed in the game, as being confusing and unreadable. I guess I’m just weird?

Mmmm critics are… Critics. When they have nothing to say it is badly done, they choose to bash onto something to fill the gaps.
I dont see why this cam would be more confusing or unreadable than another one. When i see so many tomb raiders and they still say its 3rd person camera is not one of the best… Maybe they should suggest their better ideas instead of criticising :wink:

1 Like

I think Jiagg already gave the right answer. That’s probably how they did it.

1.) Pick an anchor point for you character in 3D space. The point where the feet meet the ground seems like a good choice.
2.) Transform that 3D anchor point into a 2D screen position using the camera’s viewprojection matrix.
3.) Draw your sprite in 2D at this 2D anchor point.

This is how you transform a 3D world position into a 2D screen position:

Vector4 worldPos4 = new Vector4(worldPos, 1);
Vector4 screenPos4 = Vector4.Transform(worldPos4, viewProjMatrix);
Vector2 screenPos = new Vector2(screenPos4.X, screenPos4.Y) / screenPos4.W;

screenPos is -1,-1 in the bottom left corner and +1,+1 in the top right corner of the screen. If you want to do your 2D drawing in pixel coordinates, you have to further transform that to pixel space.

Vector2 pixelPos = (new Vector2(screenPos.X, -screenPos.Y) + Vector2.One) / 2 * resolution;
2 Likes

Yeah, I got this from just googling the game and it makes me sad :confused: I hadn’t seen this game before. They try something different and it gets bashed because it doesn’t do what everyone else does already. I like the aesthetic and I think they did a really great job with the sprites so it works well with the environment.

1 Like

Thanks for your comment mate - yeah, I think you and Jjagg are right on this one. I tried to do that today by using the Unproject function to get the correct screen position for the sprites. Something like this:

            Vector3 unprojected = graphics.GraphicsDevice.Viewport.Unproject(position, camera.Projection, camera.View, World());
            screenPosition = new Vector2(unprojected.X, unprojected.Y);
            rectangle = new Rectangle((int)screenPosition.X, (int)screenPosition.Y, texture.Width, texture.Height);

But something with the matrices is not clicking right, and I am getting strange results. This is the position of a billboard in 3D space:

And this is the sprite drawn at unprojected screen position:

I’m not sure, but maybe I need an additional matrix here to transform the world position somehow?

You shouldn’t be using unproject.
You’re character’s position is stored in world space, right? I.e. it has a 3D position, stored in the same space as your models’ positions are stored. You can apply your transforms to that position (just like you do to models) to get the screen position. Isn’t that what you did in the first image? Then you need to figure out scaling.

I used have a project like this and we called it 2.5 games not 3D games, where the world is 3D and all characters are just a texture of BILLBOARD from sprite sheet.

I will just use BILLBOARD in a 2.5 game type ^ _^ Y

Something like this I created from my old games

Actually, @guy120334913 I just remembered there are some factory methods in Matrix for billboarding. You might be able to leverage either Matrix.CreateConstrainedBillboard or Matrix.CreateBillboard. With the Constrained variant you can specify an axis to rotate around instead of rotating in full 3D.

I’m really curious as to how this could be achieved. Could this be a combination of a perspective camera for the 3D environment and an orthographic camera for the billboards? I’m puzzled >:(((

Looking at the lines in that screenshot it’s clearly orthographic for everything. In perspective projection there’d be progressiveness to the angles of those drawn lines. It looks to just be an orthographic projection that’s been angled down 45 degrees and left-or-right (who knows) 45 degrees. Just because it’s orthographic doesn’t mean it can’t look off into a direction other than directly down a Unit-Axis.

I’m not sure you’d ever really be able to tell just by looking at a still image. If you pull the camera back far enough and use a tight field of view, you can get very near parallel lines with a perspective projection.

You could also do manual billboarding in the shader, google for xna particle sample to see a good base for that.

Ah, I didn’t know that. I thought that this is what the unproject method was for? What would be the correct use of it?

In fact I tried to do what @markus suggested earlier, but it yielded a similar result.

Yeah, the character has a 3D position in world space. In the first image I am using a 3D plane with the sprite used as a texture, the second image was my attempt to draw a 2D sprite at the unprojected on-screen position.

I will try to use the Billboarding functions for Matrix - I wasn’t able to get it to work as I wanted the first time around, but maybe I should look into it again.

It’s to transform a point from screen space coordinates (in pixels) to world space coordinates. The XNA docs mention how to use it for mouse picking. You can use unproject to project mouse location (in screen space) to a point in world space on the near plane and one on the far plane. You can then construct a ray between these points to test which objects in the scene it intersects.

So in other words I’ve been trying to use a method that does the absolute opposite of what I wanted to do :sweat_smile:

1 Like