Creating an Isometric Camera

Update:
Orthographic projection has been fixed in the source code (Thanks Ben!) so the “True Isometric” example below should function properly in Blender 2.49 and later.

Original:
Recently, PlantPerson and I were chatting about the potential of isometric games in Blender. When Plant suggested that it might not be possible to make a proper isometric camera in Blender, I decided to take it as a challenge :slight_smile:

After about half an hour, I had produced some results that I was pleased with, but I also ran head on into a bug with the orthographic camera projection in the game engine. Anyway, I thought somebody somewhere might find this information useful, so I decided to share my findings. But first, a bit of quick background…

Defining ‘isometric’
“Isometric projection” is a strictly defined geometry term with some very specific requirements. While many games use isometric projection, it is common for games which use dimetric or trimetric or even oblique projection to be called “isometric,” which is not accurate. Sometimes the term “isometric” is also confused with the much more general term “orthographic.” Isometric projection is a special kind of axonometric orthographic projection in which, if you were to look directly at a corner formed where the three axes intersect, the measure of the angle between any two axes would be 120 degrees. The image below illustrates this principle.

http://www.blendenzo.com/Images/Tuts/Isometric-Cube120.png
A cube displayed in isometric projection

Setting Up a True Isometric Camera
To set up a true isometric camera in Blender, open a new scene and select the camera. Press the N key over the 3D Viewport in order to bring up the Transform Properties window. Now change the rotation settings as follows:

RotX: 54.736
RotY: 0.000
RotZ: 45.000

http://www.blendenzo.com/Images/Tuts/Isometric-TransformProperties.png

Now enable the “Orthographic” button in the Edit context of the Buttons Window.

http://www.blendenzo.com/Images/Tuts/Isometric-OrthoButton.png

That’s it! You now have a true isometric projection camera for use in the Blender Game Engine. (This is fixed in Blender 2.49) There is one significant bug, though. (In Blender versions prior to 2.49) If you move an orthographic camera in Blender’s Game Engine away from the origin (the point 0,0,0 in the 3D world), the camera’s scale factor changes. If you move in the negative X or positive Y direction, the scale factor will decrease (this looks like zooming in). If you move in the positive X or negative Y direction, the scale factor increases (this looks like zooming out). So a true isometric camera will only work properly in Blender’s Game Engine if you either do not move it, or if you give it an opposite scale animation to cancel out the effects of the bug. (Edit: I did make a bug report about this, BTW.) (As mentioned in the update at the top of this post, this problem is resolved in Blender 2.49 and later.)

The Next Best Thing: A Pseudo-Isometric Camera
In the Wikipedia article on orthographic perspective, there is an interesting image which demonstrates how a perspective camera becomes orthographic when given an infinite focal length and distance. Unfortunately, you cannot give a camera in Blender an infinite focal length, but you can get reasonably close by raising the lens setting to its maximum (250.0).

http://www.blendenzo.com/Images/Tuts/Isometric-PerspectiveLensSetting.png

If you intend to move your camera around, and you don’t want to mess with canceling the scale factor bug, you might find it easiest just to fake an isometric projection using this method. As you can see below, the results are very similar.

http://www.blendenzo.com/Images/Tuts/Isometric-Orthographic.png

Above: True isometric projection using an orthographic camera
Below: Pseudo-isometric projection using a perspective camera

http://www.blendenzo.com/Images/Tuts/Isometric-Perspective.png

Here are two versions of the maze demo in the pictures above, which demonstrate the two different methods:
Isometric-Orthographic.blend (220 KiB)
Isometric-Perspective.blend (220 KiB)

Enjoy!

-blendenzo

1 Like

Awsome!
I wonder how you always comes up with these thins blendenzo. =P

Hi

I have tried to create a 3D isometric game in blender, and see the same “bug” as you have described :

There is one significant bug, though. If you move an orthographic camera in Blender’s Game Engine away from the origin (the point 0,0,0 in the 3D world), the camera’s scale factor changes. If you move in the negative X or positive Y direction, the scale factor will decrease (this looks like zooming in). If you move in the positive X or negative Y direction, the scale factor increases (this looks like zooming out). So a true isometric camera will only work properly in Blender’s Game Engine if you either do not move it, or if you give it an opposite scale animation to cancel out the effects of the bug. (Edit: I did make a bug report about this, BTW.)

I hope that this bug will be corrected :-).

Thanks for this information, it’s very interesting ;).

I tried this .blend and the one you posted in the tracker, but I can not see the bug :frowning:

I wonder if it’s OS.

I’m running Windows
I know Blendenzo is running Linux
Blenderman, what are you running?

I’m on windows, it also happens to me.

Okay, than I am just blind, I’ll take a look at the blend in the tracker again.

I never realised the problem was zooming in, I ‘fixed’ the bug by moving the camera up and down on the axis as well. Its only when I rotated the camera I decided to drop ortho mode.

Love the pseudo isometric idea though.

I’m on windows Xp (and linux Ubuntu).
On windows, I have the bug (I have not tested on Linux, but I think that it will the bug too).

Thanks

Nice one Blendenzo ( as usual)!
Thank you!

In fact BGE itself is faking Orthographic cameras. You can see this in KX_KetsjiEngine.cpp:


const float ortho = 100.0;
(...)
if (orthographic) {
	lens *= ortho;
	nearfrust = (nearfrust + 1.0)*ortho;
	farfrust *= ortho;
}
(...)
if (!cam->GetCameraData()->m_perspective)
	camtrans.getOrigin()[2] *= ortho;
(...)

Instead of using glOrtho() to calculate the ortho camera distortion, it uses glFrustum/glPerspective and multiplies the camera lens by 100, and multiply the forward position by 100 as well (kind of moving the camera forward).

  • please notice here that in BGE code the camera is pointing toward the Z. That’s why getOrigin()[2] is giving us the parameter of the camera forward direction.

Yep. The code doesn’t lie. I was actually just reading about glOrtho() yesterday and beginning to suspect what you just proved. This explains why the orthographic camera in the Game Engine doesn’t always match the orthographic camera in the 3D viewport window of the editor.

Still this doesn’t explain why there is visual scaling ocurring. I ran a good number of tests yesterday, and it seems that the scaling is not actual scaling (that is, the camera itself is not scaling), but it is a visual distortion which is occurring, probably from a bad calculation. I don’t know much about all of the camera matrices, but I did notice that the modelview matrix is an identity matrix in perspective mode, but in orthographic it becomes an exact copy of the world_to_camera matrix, except that the [2][3] value is multiplied by a factor of 100.

Anyway, I’ll update the tracker with a bit more info.

(BTW, you probably know this, but all OpenGL cameras point toward the negative Z by default, which is why the BGE code is set up to treat it that way.)

Hi Everyone,
Im glad i found this thread as ive been trying to figure out why my orthographic camera was zooming in when I moved it and now i know. Ive tried your fake isometric camera blendenzo which is lots better for me but still doesnt make the scene look quite right.
I was hoping one of you may have made some progress with this? While looking through the gameengine API i found this code but cant get it to work with my camera ( all the objects disappear- maybe its just making the camera look somewhere else?) I hope the code is some use to one of you?

setProjectionMatrix(matrix)

Sets the camera’s projection matrix.

You should use normalised device coordinates for the clipping planes: left = -1.0, right = 1.0, top = 1.0, bottom = -1.0, near = cam.near, far = cam.far

Example:
import GameLogic

   def Scale(matrix, size):
           for y in range(4):
                   for x in range(4):
                           matrix[y][x] = matrix[y][x] * size[y]
           return matrix
   
   # Generate a perspective projection matrix
   def Perspective(cam):
           return [[cam.near, 0.0     ,  0.0                                  ,  0.0                                      ],
                   [0.0     , cam.near,  0.0                                  ,  0.0                                      ],
                   [0.0     , 0.0     , -(cam.far+cam.near)/(cam.far-cam.near), -2.0*cam.far*cam.near/(cam.far - cam.near)],
                   [0.0     , 0.0     , -1.0                                  ,  0.0                                      ]]
   
   # Generate an orthographic projection matrix
   # You will need to scale the camera
   def Orthographic(cam):
           return [[1.0/cam.scaling[0], 0.0               ,  0.0                   ,  0.0                                  ],
                   [0.0               , 1.0/cam.scaling[1],  0.0                   ,  0.0                                  ],
                   [0.0               , 0.0               , -2.0/(cam.far-cam.near), -(cam.far+cam.near)/(cam.far-cam.near)],
                   [0.0               , 0.0               ,  0.0                   ,  1.0                                  ]]
   
   # Generate an isometric projection matrix
   def Isometric(cam):
           return Scale([[0.707, 0.0  , 0.707, 0.0],
                         [0.408, 0.816,-0.408, 0.0],
                         [0.0  , 0.0  , 0.0  , 0.0],
                         [0.0  , 0.0  , 0.0  , 1.0]],
                         [1.0/cam.scaling[0], 1.0/cam.scaling[1], 1.0/cam.scaling[2], 1.0])
   
   co = GameLogic.getCurrentController()
   cam = co.getOwner()
   cam.setProjectionMatrix(Perspective(cam)))

Parameters:
matrix - The new projection matrix for this camera.
(type=4x4 matrix.)

*that came out bad heres the link:
http://www.blender.org/documentation/pydoc_gameengine/PyDoc-Gameengine-2.34/KX_Camera.KX_Camera-class.html#pointInsideFrustum

@glitchCORD~: real orthographic camera is already in current Blender (2.49RC2) give it a try, it may make your life easier :slight_smile:

@dfelinto: I was just typing that out, but my internet connection is slow right now, so you beat me to the post. :slight_smile:

Anyway, Ben fixed this a few weeks ago. Here’s his comment:

Fixed in SVN:

BGE: Fix Orthographic mode and viewport scaling.

  • The BGE now uses correct glOrtho projection for orthographic
    camera.
    Scale setting in camera data block represents the largest extent
    of the
    zone covered by the camera in game unit. This corresponds to
    the outer
    dotted line in the 3D view when viewing the scene through the
    camera.
  • Fix culling when using overriding camera is in orthographic
    mode.
  • Fix old culling method with orthographic camera
    (normally not used since DBVT is the default culling method)
  • Fix scaling problem with viewport:
    camera in viewport would be scaled by 3D viewport scaling.
    Viewport will now render the area within the outer dotted line
    when viewing the scene through the camera.
  • ImageRender did not take into account the aspect ratio
    settings
    in the render panel when computing the view frustrum.
    ImageRender
    will only render the area in dotted line as with viewport.
  • Disable eye correction in stereo mode for orthographic camera:
    stereo doesn’t make sense for orthographic camera, so
    orthographic
    render will only be “on screen”
    You can get a copy of the latest 2.49 release candidate here: http://download.blender.org/release/Blender2.49RC/

Thanks guys, thats great to hear, im not sure if this is the place to ask but are the RC’s stable- im using blender for my final degree show, its got to run for around 12 hours a day without crashing!

The RC’s are rather stable in my experience, though I can’t speak for your particular situation.

If you have any Python scripts, you will need to update them to match the new API in order to use the RC. Blender will output deprectaion warnings to the console telling you what to change. If you are using IPOs on dynamic objects, though, they will not work in RC1 or RC2. The issue has been resolved in the source code, but not in a public build at blender.org yet.

My record it’s to leave BGE running for 3 weeks. Including heavy script interations, dynamic population, hundreds of objects …

Before Blender 2.49 I would advice you not to close your application with your professors looking at it. Now those crashes are mere tails from our release logs.

All the best with your project.
(btw, why not open a new thread to talk about it?)

i have a related question about application. if i wanted to use this camera set up in a game, following around a character, how would i parent the camera to the player without it rotating with the character?

thanks, Elgree.

@elgreeteeto,

please open a new thread at the support forum rather than adding it to such an old post.