• Create Account

### #ActualJTippetts

Posted 17 August 2012 - 07:10 AM

1) The "funky value" for the foreshortening of the unit cube was calculated as (0.5/cos(30)) / (sqrt(2)). I don't really have time to do a diagram, but maybe a description will do. The vertical walls in the tile sprite are 0.5 times as tall on-screen as the top of the tile. The sprite is being viewed at an angle of 30 degrees. Doing a little trig, you can see that if the tile top is considered 1 unit in size on-screen (it's not, but for the purposes of the math it is) then the foreshortening factor to use to make a unit-size cube half that size in screen space would be 0.5 / cos(30). Now, since the tile top is actually being viewed diagonally, it's size is actually sqrt(2), so we need to divide (0.5 / cos(30)) / sqrt(2) to get the final foreshortening factor. Scale a tile-sized cube by this factor vertically, and it should match the sprite tile pattern.

(This kind of weird math is the most difficult part of tranforming 2D to 3D isometric. You just need to get a sheet of paper and draw some diagrams of exactly what is happening, as far as the interaction of a camera at 30 degrees / 45 degrees is concerned. Once you wrap your head around it, the rest is easy peasy.)

2) Not necessarily. I just have my mobs keep track of their world coordinate. There are 16 world units per tile. So a tile world 10x10 tiles in size in X and Z would be 160x160 units in size. To find the tile any given mob is in, you just divide his world coordinate by 16. Now, I usually do use a spatial grid structure to track mobs, but that is typically for visibility determination.

3) No, all you have to do is scale the ortho_width and ortho_height values when constructing your projection matrix by 1/zoomfactor. So if you want a zoom of 2, just scale by 0.5. To make it easy, you could just alter the applyCamera function:

void CIso::applyCamera(float zoomfactor)
{
GLint viewport[4];
glGetIntegerv( GL_VIEWPORT, viewport );

glMatrixMode(GL_PROJECTION);
float aspect=(float)viewport[3]/(float)viewport[2];
float screen_tiles=(float)viewport[2] / (float)tile_pixel_width_;
float ortho_width=screen_tiles*(float)tile_world_size_*1.414213562373f * (1.0f/zoomfactor);  // Scale the horizontal by zoomfactor
float ortho_height=ortho_width * aspect;
glOrtho(-ortho_width/2,ortho_width/2,-ortho_height/2,ortho_height/2,0.0f, 1000.0f);

glMatrixMode(GL_MODELVIEW);
glTranslatef(0,0,-100);
glRotatef(30,1,0,0);
glRotatef(-45.0f,0,1,0);
glTranslatef(-x_,0, -z_);
}


That'll let you zoom in or out to whatever level you desire, any time you desire. No resizing the GL viewport is necessary.

### #1JTippetts

Posted 17 August 2012 - 07:10 AM

1) The "funky value" for the foreshortening of the unit cube was calculated as [/b](0.5/cos(30)) / (sqrt(2))[/b]. I don't really have time to do a diagram, but maybe a description will do. The vertical walls in the tile sprite are 0.5 times as tall on-screen as the top of the tile. The sprite is being viewed at an angle of 30 degrees. Doing a little trig, you can see that if the tile top is considered 1 unit in size on-screen (it's not, but for the purposes of the math it is) then the foreshortening factor to use to make a unit-size cube half that size in screen space would be 0.5 / cos(30). Now, since the tile top is actually being viewed diagonally, it's size is actually sqrt(2), so we need to divide (0.5 / cos(30)) / sqrt(2) to get the final foreshortening factor. Scale a tile-sized cube by this factor vertically, and it should match the sprite tile pattern.

(This kind of weird math is the most difficult part of tranforming 2D to 3D isometric. You just need to get a sheet of paper and draw some diagrams of exactly what is happening, as far as the interaction of a camera at 30 degrees / 45 degrees is concerned. Once you wrap your head around it, the rest is easy peasy.)

2) Not necessarily. I just have my mobs keep track of their world coordinate. There are 16 world units per tile. So a tile world 10x10 tiles in size in X and Z would be 160x160 units in size. To find the tile any given mob is in, you just divide his world coordinate by 16. Now, I usually do use a spatial grid structure to track mobs, but that is typically for visibility determination.

3) No, all you have to do is scale the ortho_width and ortho_height values when constructing your projection matrix by 1/zoomfactor. So if you want a zoom of 2, just scale by 0.5. To make it easy, you could just alter the applyCamera function:

void CIso::applyCamera(float zoomfactor)
{
GLint viewport[4];
glGetIntegerv( GL_VIEWPORT, viewport );

glMatrixMode(GL_PROJECTION);
float aspect=(float)viewport[3]/(float)viewport[2];
float screen_tiles=(float)viewport[2] / (float)tile_pixel_width_;
float ortho_width=screen_tiles*(float)tile_world_size_*1.414213562373f * (1.0f/zoomfactor);  // Scale the horizontal by zoomfactor
float ortho_height=ortho_width * aspect;
glOrtho(-ortho_width/2,ortho_width/2,-ortho_height/2,ortho_height/2,0.0f, 1000.0f);

glMatrixMode(GL_MODELVIEW);