PDA

View Full Version : Continuous World / World Wrapping



MicahBrening
02-19-2007, 08:01 PM
Hello,

I'm unable to figure out the actual term for what it is I am seeking to do. The best I can say is that anyone who has played Lords of Magic has seen it. The ability to scroll over land and never hit an edge. I am aware this was done with DirectDraw, and I know it can be done with something like SDL.

Is there a way to use OpenGL to render terrain, and then just controlling the camera be able to move along without hitting the edge of the world?

An idea I had was to render the terrain at a slight curve, enough so that the land curves to the other side, making an actual globe. But there must be an easier way to achieve what I have in mind.

Any ideas? Need me to better explain what I'm after? Too difficult to do for a newbie?

Thanks!
Micah

jide
02-20-2007, 12:49 AM
I guess you should do the trick any old game consoles like Super NES used: tiling. You can just add a portion of the opposite side, wide enough so that when you move the camera you see all the things. Then, once the camera is fully inside that extra portion, then move the camera to the opposite side. Do the same things for all sides and corners. This should do the trick.

MicahBrening
02-20-2007, 04:54 AM
I did not think of that option. That's a very good idea. The only problem I can see with that is that if something happens on one side of the map, it must be shown on that side, as well as on the added portion in case the camera is looking at that added portion, so that they do not miss the action. But I guess that all that needs done is to program a mirroring function that is run after/during each update.

Thanks for the tip!
If there are any other ideas or code examples of this idea, I'd love to see them.
Thanks again.

jide
02-20-2007, 05:10 AM
Why not simply render those new portions translated from their original position ? I did not ever done that thought, so maybe it's more easy to tell than to do..

Cyranose
02-20-2007, 08:17 AM
The name you're looking for is "toroidal scrolling." A sphere isn't the best model for it. With spheres, you can walk "straight," making only 3 right turns and still wind up at your starting location.

A better model is the torus (hence the name toroidal), where you're like an ant on the surface. You can safely treat that 2D surface as a uniform and cyclic 2D grid.

You could perhaps build your world as a big torus, or you could simply tile your scene into chunks and either reposition the camera or those chunks to keep movement continuous and without end. In the latter case, what you're doing is essentially treating those chunks as being flat sections of the torus that you toroidally scroll.

Imagine that torus as a balloon, but with the air taken out--such that you can't tell it was ever a curved surface. Now "roll" that surface like a 2D treadmill in X and Y so your POV is always centered (the horizon at equal distance around you).

Now imagine doing that with big chunks of terrain instead, discarding parts of the world you can't see or are "under you, upside down." And that's essentially what the tiling solution is trying to emulate.

MicahBrening
02-20-2007, 02:36 PM
Jide:
That is a good idea. I did tinker a little with that, but just a little. The problem I found was that I had to run a function each render to pull that info, just causing several more function calls then I wanted to do. I was hoping there was a simple way of setting up an opengl object, and then just use the camera for movement. But I guess your idea is still an option.

Cyranose:
I haven't actually heard of toroidal scrolling, but it sounds good to me. This sounds like something I should investigate in to. Do you by any chance know of any examples or tutorials on this method? There is always google, but you seem to know what you are talking about and might have an inside scoop on a good article.

All in all, I am wanting to use the 3D ability of opengl so that my lack of art skills doesn't kill my project. From what I've seen, a simple grass and water texture used with good terrain morphing and lighting looks as good as prerendered terrain.

Thanks again for the posts. I'm starting to get ideas to try, but if anyone has some links to some source code, tutorials, or examples of sorts, that would be greatly welcome.

Stuart McDonald
02-20-2007, 08:49 PM
If your world is a cube then you can do this with multiple render passes. Here's the comments from some code I wrote that should explain it. (collision box simply means the enitre world in this context)

I don't know what type of view you are wanting (mine was first person), but idea idea can be adapted.


// This renders the world in such a way that a "wrap around"
// effect is created. i.e. the entire world is within the
// collision box. If the player is sitting at the front side
// of the box looking straight ahead (down the Z axis) then
// the two renders need to be made; one from the players
// actual position (this is always done) and a second from
// the players positon moved backwards so they are outside
// of the box looking in at the backside.
//
// e.g. The diagram below shows the collison box from above.
// The player is at '^' looking forwards. The '\/' shows their
// field of view (FoV). They should be able to see 'x' because
// the world (and their vision) is "wrap around"
// _______
// \ /
// ---\---/---
// | \ / |
// | ^ |
// | |
// | x |
// -----------
// The first render will show the world contained in
//
// \---/
// \ /
// ^
// By moving the player backwards by the depth of the world
// (height of the box below because the view is from above)
// and rendering again 'x' will be seen i.e.
// -----------
// | |
// | _______ |
// | \ / |
// | \x / |
// ----\-/----
// ^
// This must be done for any part of the FoV that is outside
// of the box i.e. "wrap round" the players position so that
// the FoV part becomes inside the box.
//
// The 4 corners of the FoV frustum backplane (i.e. the
// rectangle which defines the furthest they can see) are used
// to check if any part of their FoV is outside. The points
// are rotated and checked against the sides of the box.
So if the FoV is off the left (so they can see part of the world to their right) then you have two renders. One with the camera in the normal positon, then another with it moved to the right by the width of the world.

Things build up obviously e.g. if the FoV is off the left, top and front of the world then you move the camera right (render), down (render), back (render), right and down (render), right and down and back (render), down and back (render) etc.

For the worst case I think you can get 18 renders , though it depends on the size of the box and the field of view (FoV).

What's cool is if you make the FoV distance bigger than your box you can actually see the back of your head :)

--STU!

MicahBrening
02-22-2007, 02:27 PM
Stuart: I cannot say I fully understand this solution. Your saying that rather than render the world as a sphere, render it as a box?

Please forgive me, I'm still new to 3D graphic programming and their tricks.

plasmonster
02-23-2007, 12:22 PM
I think the crux of Stuart's idea (please correct me if I'm wrong) is to wrap the camera in each of the 4 axial directions and render the scene, taking into account the current FOV and z range to limit the tiling required in each direction, which could obviously repeat if the view distance is beyond a tile size (think tiling texture here).

Anyone remember the game Starsiege? They made great use of a similar effect in that game.

Stuart McDonald
02-23-2007, 12:36 PM
I'll try again...

Imagine the empty space in which your world exists is a box. The middle of the empty space is 0,0,0 and if you move right (along the positive X axis) then your position goes 1,0,0 then 2,0,0 etc (well it can obviously be a non whole number e.g. 1.1231)

That's just how most 3D worlds are done, they don't use any clever spherical rendering etc. Normally something stops you getting to the "edge" of the world e.g. the ground stops you going down, you can't fly to any height, there might be mountains or a river or buildings at the sides.

What you want however (I think) is if you keep walking (say) East you eventually end up back where you started. So if the width of your world (west to east i.e. X axis) is (say) 1000 then the left (west) edge of your world is at X position -500 and the right edge of your world is at +500 (ok so that's actually 1001 wide). If you move right at position 500 your position becomes -500.

Hopefully that all makes sense.

Now if you did all that and just render your world in the normal way then if you were standing at (say) the east edge of the world looking east i.e. you are at position 500,0,0 looking down the X-axis, you would be looking into empty space (since nothing in the world has an X-coord larger than 500 so there would be nothing to draw).

(If you moved right your position would become -500 and suddenly all the world from the West edge would appear).

But when you are standing at the East edge looking east you want to see the objects, ground etc which are at the far west (left) edge of the world e.g. the objects/ground/etc at X-positions -500 to -100 (assuming you can 400 units into the distance, the values are obviously just examples).

That's what I describe above. To do this you need to render your world from multiple positions. The diagram shows the world looking straight down from above, so North is the top edge of the world. The player is standing near the North edge (say 0,0,+400 assuming the Z increases as you move North) and looking North.

You render the world from the players position and then render it again from their position moved backwards (South) by the depth of the world (so 0,0,+400-1000 = 0,0,-600). So the first render has all the world that is directly in front (i.e. the world up to the North edge) then a load of empty space. The second render has a load of empty space (since you are at -600) and then the world (grass/objects/etc) at the South edge.

When both these bits are put on top of each other (you render both without clearing the screen) they fit together so the player doesn't see an edge. If they continue to walk North then when they reach 0,0,+500 (the North edge) their position will change to 0,0,-500. At that point you only need to do one render since their field of view (everything they can see) doesn't cross an edge of the box.

You often need to do more than 2 renders though. e.g. if I am standing near the North-West corner and looking North then I need to see some of the world that is at the East edge as well as some of the world at the South edge. The 18 renders I mention is only if you have a fully wrap around world e.g. a space simulator. If you have ground then things are simpler because you can't look down and see what's above you (or vice versa).

Now obviously you need to design your world so that the edges fit together seamlessly (the same way that a seamless texture can be placed next to itself without the edge being visible) e.g. if your ground at the North edge was all at the same height (say 100) then the height of the South edge would also need to be 100. Otherwise the two edges wouldn't line up.

--STU!

MicahBrening
02-23-2007, 08:41 PM
Stu: Thank you for your reply. That time did make a lot more sense. The downside I see is that I was hoping to call all the opengl functions needed to build the world, and then call a simple camera moving function (I guess like the GLUlookat) to move around seamlessly. I guess that is not possible. This is a very good idea you are presenting to me though.

I'm curious as to how this would be implimented. I'm assuming I could still build the whole world into an object, and then just translate the parts that need to be moved into the field of view. Or is it more tricky than that?

Another thing is that you seem to be coming at this with a view towards a first person style render. I'm hoping for a type of isometric (I think that is the correct term) view. I want an overworld, looking down, but perhaps at enough of an angle that height is easier noticed. So all I am ever seeing is the ground (or water), never the sky or anything of that sort (but it really would be interesting to add that as a feature (or a bug)

But really, looking down shouldn't be a difference in the way you are telling me. The most renders I'll have to do is four NE looking at the SW corner. Not bad as long as I can figure out how to do it.

Thanks for all the advice. Obviously if there are any code samples that can be shared to point me in the right direction, or just simply some commands to look into that would get this done fairly easy, please do let me know. If not, again, thank you for the advice!

Stuart McDonald
02-23-2007, 09:55 PM
I'm not sure you fully understand. You build your world any way you want. You don't need to translate parts or build the world into an object. The only things you need to do are

1) Your coordinates wrap whenever they cross the edge or the world. i.e. when you change the position of any moving object you need to wrap it's position e.g. newX = (X + moveAmount) modulus maxX
2) You do multiple renders i.e. call your code which renders the world given a camera position. Change the camera position (as described above), call the render code again and so on (as described above). You don't change the position of any objects, you don't do anything special in your code. All you are doing is drawing the world from multiple camera positions and when those parts are put shown on the screen they fit together.

Other than that there are no restrictions. e.g. I could take the Quake engine, add these two things and I could then create maps which were wrap around.

Yes I have been talking about first person, but it makes no difference if it was isometric. The technique doesn't care how the world is built or rendered.

The only code I have is to work out all the different renders i.e. it works out which edges of the box my field of view crosses. That will only complicate things more since all it does is

View crosses LEFT, TOP and FRONT of box
Therefore
Move camera DOWN and render
Move camera RIGHT and render
Move camera BACK and render
Move camera DOWN+RIGHT and render
Move camera BACK+RIGHT and render
Move camera DOWN+BACK and render
Move camera DOWN+BACK+RIGHT and render
etc.

It is also more complicated than you need because you don't have full (space simulator style) wrap around.

Ok, lets try this....

Imagine your world is a 2D flat sheet seen from above. It is 12x6 in size and the size you can see (i.e. your field of view) is 5x3 (again, the values are irrelevant. This is purely for illustration) and the player is always in the middle of the screen.

Given that here's how the world looks if the player is standing at (f,2)


abcdefghijkl
0
1 xxxxx
2 xxPxx
3 xxxxx
4
5
Whe 'P' = the player, and 'x' = the part of the world that will be visible on the screen i.e. the bits you need to draw.

Now if the player is standing at (f,0)


abcdefghijkl
0 xxPxx
1 xxxxx
2
3
4
5 xxxxx
i.e. you need to do two renders one from the players position (f,0) which would show whatever is in the box with corners (d,0),(h,1) i.e.


abcdefghijkl
0 xxxxx
1 xxxxx
The screen will therefore look like


bbbbb
xxxxx
xxxxx
Where 'b' is blank space


For the second render you move the camera down by the height of the world (6) so (f, 0+6) => (f,6) i.e.


abcdefghijkl
0
1
2
3
4
5 xxxxx
6 xxPxx
7 xxxxx
Now since nothing in the world has a coordinate larger than 5 nothing is drawn for area (d,6),(h,7). So that render shows


xxxxx
bbbbb
bbbbb
When you overlay that render with the first render you get a complete screen showing the wrap around world.

If the player moves up then you wrap their coordinate i.e. they move from (f,0) to (f,5).

Now if the player is standing at (a,0) then you need to do four renders i.e.


abcdefghijkl
0Pxx xx
1xxx xx
2
3
4
5xxx xx
So you render the world from positions (a,0), (m,0), (a,6) and (m,6).

I don't think I can explain it any more clearly than that. All you are doing is drawing the world from different positions (you do understand that the world stays still and the camera moves, it's a common problem that people think they need to translate all their object positions rather than move the camera).

--STU!

MicahBrening
02-24-2007, 08:22 AM
Ah! That does make a lot more sense! I do understand what needs to be done. Which means I can start playing with some basic functions to figure out how to accomplish it.

One thing I am not certain on is that you said all you have to do is move the camera, and not translate objects. But I seem to remember reading that opengl always looks at 0,0,0 and that the glulookat function just translates the objects in that space to the 0,0,0 coord. But then, I'm too new to know for sure.

The only opengl I've really worked with was using the ortho functions, so I still have quite a bit to learn. But I do believe that gives me a good direction. Thank you!

Stuart McDonald
02-24-2007, 06:46 PM
What I meant was you don't need to do any translation etc that you wouldn't normally do i.e. this technique only needs the wrap round coords and the multiple renders.

Good luck.
STU!