ID:154445
 
Here is a question that has been plaguing me as I work on a Multi-turf library:

I believe most 3Dish systems work on variations of the same principal: Draw stuff from back to front, so that things overlap properly, because stuff in the foreground will be drawn over stuff in the background.

The Multi library currently implements this approach by setting the drawing layer of all pieces of a multi-turf object according to where the bottom of the object is on the map. This has the same effect as described above.

This seems simple enough and works for "straight-on" graphics...but I don't understand how it applies to this situation:

Isometric, where something like a wall stretches diagonally across the map:

/
/
/
/
/
/

Now say people are standing near the middle of the wall:

/
/
/
y /x
/
/

How does a 3D system draw this such that everything overlaps correctly? You can't go by the bottom of the object necessarily...because in that case here, if you draw from back to front, the bottom of the wall might be drawn over the foot of x, even though x is standing in front of the wall.

Is the wall treated as smaller segments or something?

There is some basic principle I don't know. If someone could explain, and even better, point me to a good resource, I'd be very happy to get this off my mind! (And maybe integrate it into the library.)
Wow, you've taken on a major undertaking, Deadron.

I don't know of any rescources for this, but I have played a few isometric games enough that I think I have some insight into how they are displayed. You might try this site: http://www.geocities.com/SiliconValley/Vista/6774/ IsoIntro.html
It looks promising.

If you chop the wall into a long series of vertical columns, it should help with the problem. (If I understood what you are saying correctly.)

Perhaps if you could should a graphical representation it would be easier to understand your problem. Your text representation is very difficult to interpret.
Deadron wrote:
Here is a question that has been plaguing me as I work on a Multi-turf library:

I believe most 3Dish systems work on variations of the same principal: Draw stuff from back to front, so that things overlap properly, because stuff in the foreground will be drawn over stuff in the background.

The Multi library currently implements this approach by setting the drawing layer of all pieces of a multi-turf object according to where the bottom of the object is on the map. This has the same effect as described above.

This seems simple enough and works for "straight-on" graphics...but I don't understand how it applies to this situation:

Isometric, where something like a wall stretches diagonally across the map:

/
/
/
/
/
/

Now say people are standing near the middle of the wall:

/
/
/
y /x
/
/

How does a 3D system draw this such that everything overlaps correctly? You can't go by the bottom of the object necessarily...because in that case here, if you draw from back to front, the bottom of the wall might be drawn over the foot of x, even though x is standing in front of the wall.

Is the wall treated as smaller segments or something?

There is some basic principle I don't know. If someone could explain, and even better, point me to a good resource, I'd be very happy to get this off my mind! (And maybe integrate it into the library.)

You are thinking of the "bottom of the object" as the lower left corner on the x/y plane, but "bottom" should refer to the z plane in a 3D world. If "x is standing in front of the wall," then it it is "closer" to us on the z axis, which means it draws after the wall. If x is a multipart object, each part must be evaluated for its z distance individually. 3D engines generally do this by breaking every object into triangles, each of which has a given distance from the camera on the z axis.

Of course there is still a problem if the triangles intersect, but properly modeled objects with good collision detection should keep this from happening.

I'm not sure how much this helps you in the BYOND environment. If you are working on something this complex, I'm impressed!

/mob/skysaw
I think Skysaw's mostly right. I say mostly, because what you need is not a z-axis reference but a "virtual axis", z being the straight-up vertical. You need an x' and y'.

The wall in question is vertical; that is, it goes along the y' axis. y' is really diagonal in the true cell-based view, but for the purposes of this coordinate system it goes straight up. (x' may be straight left-to-right, or it may also be a diagonal.)

The rule about whether to draw an object first can then be a simple one. For a horizontal wall, anything farther "back" along the y' axis goes first, and anything toward the front gets drawn later. For a vertical wall, anything to the left (along x') goes first, and on the right goes later. For smaller objects, just go from back to front, and from left to right. More complex walls should be split up into horizontal and vertical segments.

There are probably a few bugs in this system, but then this sort of operation is hard to do anyway. Probably the simplest thing in BYOND would be to take all objects in the view space, split them into 1-cell chunks, and assign them a Z-order (not to be confused with location on the z axis) based on their vertical position and horizontal position, with vertical getting top priority.

Lummox JR
In response to Shadowdarke
Shadowdarke wrote:
Wow, you've taken on a major undertaking, Deadron.

Well my approach may not be as significant as you think...at the moment I'm not trying to emulate a full isometric system...just working on allowing a degree of 3D in a BYOND game. The DDT actually has a fully working system in place, and now I'm trying to make it as general as possible (the current approach uses some hacky assumptions).

I should say that Guy is doing the hard work on this...as people will see when L&D comes out.



You might try this site: http://www.geocities.com/SiliconValley/Vista/6774/ IsoIntro.html

Thanks, that's very interesting. I don't fully understand it on first reading, but it doesn't look too complicated if I put some time into understanding it. The general site is interesting too, being all about tile-based games:

http://www.geocities.com/SiliconValley/Vista/6774/ TileBased.html


Perhaps if you could should a graphical representation it would be easier to understand your problem. Your text representation is very difficult to interpret.

Good idea...I may be able to do that tonight...but lemme try for a better ASCII explanation...

The simplest way to do 3D with multi-tile objects is to use objects that are all facing forward, like so (assume each of this is 2 tiles by 2 tiles, and each letter is 4 pixels):

xxxxxxxxxxxxxxxx
x x
x x
x x
x x
x x
x x
xxxxxxxxxxxxxxxx


This is a 2x2 box sitting on the map. Given this approach, it's easy to have a 3D effect...set the drawing layer (which is effectively the z coordinate) for each portion of the multi-turf object according to where the bottom of the multi-turf object is -- the lower the bottom is on the map, the higher the drawing layer. So when one box is in front of another, they automatically draw in the correct order, with the lower box drawing over the box that is further up on the map:

xxxxxxxxxxxxxxxx
x x
x x
x x
x oooooooooooooooo
x o o
x o o
xxxxxxxxo o
o o
o o
o o
oooooooooooooooo


This is what we have working now, and it's great for standard mobs overlapping each other.

The challenge comes when your large graphics are done in fabulous isometric (damn that Guy!). The problem for me is knowing what the drawing layer (the z coordinate is) for each portion of an object that is drawn diagonally across the map. Here is a box and a wall (o) crossing it:

                o 
o
xxxxxxoxxxxxxxxx
x o x
x o x
x o x
x o x
xo x
o x
oxxxxxxxxxxxxxxxx
o
o


This illustrates my dilemma...the box should be drawn in front of the wall, because the correct z coordinate for the box has it standing in front of the wall. But the wall is one multi-turf object in the code...if I use my original approach of having the wall's layer determined by where the bottom of the wall object is, well the bottom is below the mob on the map, so the wall is drawn on top:

                o 
o
xxxxxxo
x o
x o
x o
x o
xo
o
o
o
o


And this is wrong.

So the question is, how to know what the z coordinates should be so that this incorrect situation doesn't occur?

In doing these little drawings it strikes me that there might be an answer by making the drawing layer a combination of the x and y coordinates...right now it's just based on the y coordinate (how far down the map the object is), but if the layer were reduced based on the x coordinate (the further to the left, the more it is reduced), perhaps that would make things work out...

Another possibility, as you mentioned, is finding a way to give different drawing layer to each segment of the wall, which might not be practical but I'll have to think about it more.

Normally I hate to talk about stuff before we've released it, but this is a case where my lack of programming education bites me!
In response to Lummox JR
Lummox JR wrote:
The rule about whether to draw an object first can then be a simple one. For a horizontal wall, anything farther "back" along the y' axis goes first, and anything toward the front gets drawn later. For a vertical wall, anything to the left (along x') goes first, and on the right goes later. For smaller objects, just go from back to front, and from left to right.

I think this is what I just worked out in replying to ShadowDarke...I hadn't been thinking of taking left to right into account, and it might just do the trick.


There are probably a few bugs in this system, but then this sort of operation is hard to do anyway. Probably the simplest thing in BYOND would be to take all objects in the view space, split them into 1-cell chunks, and assign them a Z-order (not to be confused with location on the z axis) based on their vertical position and horizontal position, with vertical getting top priority.

Sounds right...I'll have to play with the numbers to figure out how to make this work.

This is some of the most fun I've had in BYOND, I must say -- thinking about this graphic problem has caused me to understand a lot more about how graphics work in games.
In response to Deadron
Yes, I think your best approach would be to chop the wall (and any other isometric objects) into a series of vertical strips 1 tile wide. Then place the strips so that they line up appropriately on the map. Since your wall is at a 45 degree angle, you just move back one Y space each column to the right.

That way as the wall receeds, the Y coordinate you are associating it with moves "back" and the other object will intersect it appropropriately.


I've been fiddling with 3D views recently as well, but since I want to be able to tunnel through objects on different layers I've decided to use a system somewhat similar to Cinnom's 3D demo.

I really hate to make it a top down perspective though. (Making the terraign top down and the characters 3/4 view might be the best compromise I can work out, but that's just ugly.)

This is another case where it would be nice if we could make specific layers invisible to specific mobs.
In response to Shadowdarke
Shadowdarke wrote:
Yes, I think your best approach would be to chop the wall (and any other isometric objects) into a series of vertical strips 1 tile wide. Then place the strips so that they line up appropriately on the map. Since your wall is at a 45 degree angle, you just move back one Y space each column to the right.

I'm hoping I can do this mathematically instead of actually having to chop up walls and such into more pieces...we shall see. Actual isometric is not at a 45 degree angle I think, but a 30-something degree angle, making things not as clean as they could be.
In response to Deadron
30 degrees precisely, yes. In some cases, they use a 22.5 degree angle, but that's uncommon.
In response to Spuzzum
Spuzzum wrote:
30 degrees precisely, yes. In some cases, they use a 22.5 degree angle, but that's uncommon.

I figured out how I could determine the appropriate layer for each piece of a multi-turf isometric object.

But I also decided that I was solving problems I don't actually have right now, so I'm not going to implement that until later.

But it's good to understand how it can be done.