Jump to content
  • Advertisement
Sign in to follow this  
Ntsc8

Sorting Isometric Objects

This topic is 4250 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

I'm working on a 3d isometric game in C++ and Direct3d and I just can't seem to figure out how to sort my isometric objects. For example: Using objects such as 1x1 Block or 2x1 block Photobucket - Video and Image Hosting Currently I have all of the objects in a std:list and I'm using sort() comparing their ZOrder variable. Currently 0,0 on the object would be the furthest south corner. This variable is made like this: ZOrder = PositionX-PositionY; And so far it seems to work perfectly fine as long as the objects are square (ie: 1x1 or 5x5) but when I make an object that is 1x2 tiles long my sorting function doesn't work very well. Any help is appreciated.

Share this post


Link to post
Share on other sites
Advertisement
In my own game I check for the lowest y value of the sprite (with the crates in your case that'd be somewhere near coords 16,0 (assuming 0,0 is the bottomleft)), if one is higher than the other I switch it.

That method has worked pretty well for me.

Share this post


Link to post
Share on other sites
Hmm well let me see if I can explain what I'm looking for.
3 seperate blocks
The picture above is 3 separate blocks colored red,green, and blue.
Using the formula: ZOrder = PositionX-PositionY; (which simply finds out which one is lower on the screen) you get something like this.
3 separate blocks
Now that works great for blocks that are only 1 unit long but what about blocks that are say 3 or 4 units long.
1x4 block and 1x1 blockPhotobucket - Video and Image Hosting

Now this is where it becomes a problem. These two blocks now have a zorder that is equal to eachother even though common sense tells us that the longer block should be in the back. Here is another example.

Photobucket - Video and Image HostingPhotobucket - Video and Image Hosting
The second image is how the game would draw it.

So I need a new formula that takes into account the length and or width of the box but I can't seem to put my finger on how that would even work.

Share this post


Link to post
Share on other sites
Avoid using larger objects. Break the large ones into single boxes, and repeat them as normal. Should get the same effect if they're made right. Might not be the answer you are looking for, and for some things might take a few special case issues to draw, but for most shouldn't work too badly.

Share this post


Link to post
Share on other sites
How about instead of just having one entry in your list for the row of green boxes, you have four entries - one for each tile occupied. Then sort the list as normal. Iterate through the list and once you have drawn an object, mark it so it doesn't get drawn again.

Share this post


Link to post
Share on other sites
Seems to me you can solve it by making sure the ones with lower x-values are always drawn before the ones with higher ones. So maybe ZOrder = PositionX * (height* of the map) - PositionY; ... or some such.

*height, like, as if it was a normal square-tiles-map; max y-value+1

Share this post


Link to post
Share on other sites
Well the only problem with that is the game is built in a 3d plane where there is no real limit to x,y,z and 0,0,0 is the middle of the screen.
Photobucket - Video and Image Hosting
The game uses only objects (no tiles) and as so I really need to make sure that my drawing order for the objects is spot on.

Confusing I know. The renderer converts those coordinates to d3dvectors.

0,0,0 on the object = D3DXVECTOR3(PositionX+PositionY, -PositionX/2+PositionY/2+PositionZ-Width/2, 0.0f );

Share this post


Link to post
Share on other sites
Ah. Yeah, need to sort some different way then, I suppse.

I have about one week of C++ experience. Not awfully familiar just that sorting function, but... From what I got from a little Google-search; the sort function compares objects using the less-than operator, right? So, the current less-than operator for them objects returns a.ZOrder < b.ZOrder or some such? If that isn't how things are done at all, then, uh, at least you know how I thought it was, so maybe the point comes across anyways :P

So:

bool operator<(const Somethingsomething& a, const Somethingsomething& b) {
if (a.PositionX != b.PositionX) return a.PositionX < b.PositionX;
return (a.PositionY > b.PositionY);
}

... so that the return-value is based on the x-coordinate, unless objects has the same x, then it's based on the y-value. I think I got the ><-things right :S

Share this post


Link to post
Share on other sites
Ok well I followed your idea and found out that for some reason you can't use more than one variable in a std:list's sorting function. Not sure why but it doesn't matter since I can just combine the to variables into one.

Figuring out the Zorder (not sure how to display code yet)
Quote:
for (std::list <_LObject*>::iterator j = Objects.begin(); j!=Objects.end();++j)
{
(*j)->ZOrder = 0;
for (std::list <_LObject*>::iterator i = Objects.begin(); i!=Objects.end();++i)
{
if ((*j)->PositionX > (*i)->PositionX || (*j)->PositionY < (*i)->PositionY)
(*j)->ZOrder++;

}
}

Sorting function looks like this
Quote:

if (o1->ZOrder < o2->ZOrder)
return true;

Seems to work great although the are a few instances in which the result seems random. I'm guessing that happens when object j has a larger X and object i has a larger Y. Still will need to do some more research.

Anyway I also need to figure out how to add a Z variable. An object that has a higher Z should be drawn last unless the other object is in front of it.
6 blocks

Share this post


Link to post
Share on other sites
Quote:
Ok well I followed your idea and found out that for some reason you can't use more than one variable in a std:list's sorting function. Not sure why but it doesn't matter since I can just combine the to variables into one.

That sounds quite odd. Tried some myself now, and pretty much managed to do what I suggested in my last post :|

And seems there's a [ source ]-tag.

bool sortingFunction(const _LObject& o1, const _LObject& o2) {
if (o1.PositionX != o2.PositionX) return o1.PositionX < o2.PositionX;
if (o1.PositionY != o2.PositionY) return o1.PositionY > o2.PositionY;
return o1.PositionZ < o2.PositionZ;
}


// sort with:
Objects.sort(sortingFunction);



I'm able to run that code 'tleast, and I'd imagine it would deal with X/Y/Z-values properly.


Also:
Quote:
if ((*j)->PositionX > (*i)->PositionX || (*j)->PositionY < (*i)->PositionY)
(*j)->ZOrder++;

That will in some cases increase ZOrder even tho j's X is lower than i's X (like you said, pretty much).

if ((*j)->PositionX != (*i)->PositionX) {
if (*j)->PositionX > (*i)->PositionX) (*j)->ZOrder++;
} else if ((*j)->Positiony != (*i)->PositionY) {
if (*j)->PositionY < (*i)->PositionY) (*j)->ZOrder++;
} else if (*j)->PositionZ > (*i)->PositionZ) (*j)->ZOrder++;



I'd much rather try'n get something like that sorting function above to work tho, and avoid all that extra iterating through the list in addition to whatever sort() does...

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

We are the game development community.

Whether you are an indie, hobbyist, AAA developer, or just trying to learn, GameDev.net is the place for you to learn, share, and connect with the games industry. Learn more About Us or sign up!

Sign me up!