Reversed isometric transformations

A few people asked me how to get isometric (3d) coordinates from the mouse click (2d).

The answer is: you have to assume that one of the x, y or z coordinates is fixed.

The original tutorial: http://kirupa.com/developer/actionscript/isometric_transforms.htm

Original equations:

xFla = (x-z)*Math.cos(0.46365) + xOrigin
yFla = yOrigin - y - (x+z)*Math.sin(0.46365)

Legend:

xOrigin, yOrigin - on screen coordinates of the isometric (0, 0, 0)
x, y, z - isometric coordinates
xFla, yFla - on screen coordinates transformed from isometric coordinates


You have to assume which coordinate will be fixed before transforming your equations. So, let’s assume that y is fixed, because it represents the “height” of the room.

(For instance, with fixing the y = 0 we are clicking on the room floor. By setting y = 400 we are clicking on the surface 400 units above the floor. By fixing x = 0 or z = 0, we do clicking on walls.)

Now we have:

y = fixed
x, z -> variables

Transformation:

xFla - xOrigin = (x-z)*Math.cos(0.46365)
yFla + y - yOrigin = - (x+z)*Math.sin(0.46365)

(xFla - xOrigin)/Math.cos(0.46365) = (x - z)
(yFla + y - yOrigin)/Math.sin(0.46365) = - (x + z)

(xFla - xOrigin)/Math.cos(0.46365) = x - z
(yFla + y - yOrigin)/Math.sin(0.46365) = - x - z

  1. sum these equations to get z
  2. substract them to get x

  1. sum
    (xFla - xOrigin)/Math.cos(0.46365) + (yFla + y - yOrigin)/Math.sin(0.46365) = -2z
    z = - ((xFla - xOrigin)/Math.cos(0.46365) + (yFla + y - yOrigin)/Math.sin(0.46365))/2

  2. substract
    (xFla - xOrigin)/Math.cos(0.46365) - (yFla + y - yOrigin)/Math.sin(0.46365) = 2x
    x = ((xFla - xOrigin)/Math.cos(0.46365) - (yFla + y - yOrigin)/Math.sin(0.46365))/2


Flash functions:

// transforms screen xFla,yFla coordinates into x isometric 3d coordinate, assuming that y is fixed
x = function (xFla, yFla, y) { 
return ((xFla - xOrigin)/Math.cos(0.46365) - (yFla + y - yOrigin)/Math.sin(0.46365))/2
}; 

// transforms screen xFla,yFla coordinates into z isometric 3d coordinate, assuming that y is fixed
z = function (xFla, yFla, y) { 
return (- ((xFla - xOrigin)/Math.cos(0.46365) + (yFla + y - yOrigin)/Math.sin(0.46365)))/2
}; 

So, using these 2 equations and putting xFla, yFla and y you get the remaining x and z Isometric coordinates.
xFla and yFla received from the mouse click and y coordinate is fixed (e.g. y = 0 -> room floor) or received from another controller (e.g. keyboard UP/DOWN sets the y).

Tip: when changing the y coordinate with UP/DOWN cursor keys, you could animate some semi-transparent “floor-shaped” surface moving up&down in the room and give a feedback to the user.

Of course, you should optimize these equations by replacing values like Math.sin(0.46365) with calculated ones, so it won’t be calculated on every onEnterFrame event…

Optimized:

// transforms screen xFla,yFla coordinates into x isometric 3d coordinate, assuming that y is fixed
x = function (xFla, yFla, y) { 
return ((xFla - xOrigin)/0.89443 - (yFla + y - yOrigin)/0.44721)/2
}; 

// transforms screen xFla,yFla coordinates into z isometric 3d coordinate, assuming that y is fixed
z = function (xFla, yFla, y) { 
return (- ((xFla - xOrigin)/0.89443 + (yFla + y - yOrigin)/0.44721))/2
};

Hey Danko,

I started some days ago playing around with isometrics – got quite fare with some other algo using sinY, cosX and cosY. Worked pretty well including rotating the coord-system, but I struggled by defining the mouse position. Now I’m using your draft and wondered if you have any idea how to implement the rotation part?

regards -comkee

Can you be more specific pls?