Dynamic objects in Isometric Map Drawing algorythms

Started by
12 comments, last by JTippetts 11 years, 8 months ago
Thank you very much JTippetts, this example is awesome.
I want to make a similar isometric engine, but I am not on the same level as you guys. Can you clarify stuff a bit for me?

Tile and funky value
Looking at the tiles you used, it looks like the tile primitive is 0.5 of the width. And the funky value is 0.5 in perspective of 30° angle. Am I on the right path here?
I tried to reproduce your calculation, but I haven't managed to do so yet, can you describe the formula?

World Unit
As I understood, your world is rasterized in world units, one tile consists of 16*16 units. You wrote that an actor traversing the tile needs 16 steps. So a mob in your engine would keep track of the mobs unit he is currently in, right?

Zooming
If you would implement zooming, it looks like you would need to reinit OpenGL to a different resolution.This seems a bit cumbersome, is there an other solution?
Project: Project
Setting fire to these damn cows one entry at a time!
Advertisement
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);
glLoadIdentity();
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);
glLoadIdentity();
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.
You still will need to sort the alpha blended sprites right? I mean, sprites behind a tile will need to be clipped(partially) by the front tile, but the blending need to occur to the tiles behind the sprites..Isnt true?
Doesnt that mean that the entire map will need to be sorted anyway? At least if you want a "pilled cubes" kind of isometric game.

One problem Im trying to figure out (in 2D) is when the height of a object is greater then an entire floor, I mean, if you draw the first floor (the one with a 2 floor height object on it) and than you draw the second floor, the second floor objects will clip the tall object even if behind it. I though I have solved it by drawing all the floors of each tile ( instead of traversing floor/row/col, Im traversing row/col/floor, check the image on the op, theres 2 floor tall objects), this really solved for the map itself (static) but for moving objects it does not work, since the object will be clipped by tiles on front rows(on the same floor), its "feet" will be cliped by the "losang" right bellow it, on the front row, before it jumps to the next row (you know, when its transiting between tiles). One may think a solution is to not have objects taller than a floor, but them..your character can not jump? inadmissible!

Neither I can understand what I described, heres a pic:
isocubicfloorissue2.png
The tall cube is being cliped by the tile on the floor above, cause the top floors are drawed later.
isomovingfloorissue.png
Here I solve the first problem, by drawing all floors of a tile first..the object is on the second floor, but its clipped by the one on the floor bellow, cause the front rows are drawed later now..

Resuming, the problem is solving transitions, if you solve transitions on width, you ruin on height, if you solve on height (y), you ruin on width.

I cant visualize if this problem will be solved on 3D, you still need alpha blending and sorting right?

How engines solve problem like this (kinda off topic):
alphablendcullingissue.png
Lets say the sprite is a smoke particle, how you do the blending of the smoke with the heightfield behind it, without having the smoke showing on front of the height field part on front of it?
You only need to sort if you actually do alpha blending, with partial transparency. If you just do alpha testing, where a pixel is either fully opaque or fully transparent, you do not need to sort. Typically, I do not see pixel art Iso games use partial transparency. The above demo uses full transparency and draws front to back to take advantage of early depth rejection to reduce overdrawn.

For sprites like smoke that must use partial transparency you can sort those sprites alone and draw them in a pass after the world is drawn. Depth testing will reject any pixels that do not pass the depth test.

This topic is closed to new replies.

Advertisement