Can I create a Terrain from an image in memory?

Started by
21 comments, last by Azrael 23 years, 11 months ago
When a terrain is created you actually use 3 images to form it. heightfield, tilefield (which forms an image after all), and shadowfield (as I call it) which has the color of each vertex in the grid. the question is PRLoadTerrain loads this from disk images (.pcx) can I do the same from images that are already loaded in memory?
Advertisement
You can load them in and then change the heightfield data afterwards. This would let you page in new heightfield data for a bigger world, but doesn''t work well unless you''re using the older tiled texture system

Author of Power Render (http:/www.powerrender.com)
Chris! Im so glad you answered this...
Where is this data located once is loaded? is it imposible to do this with the new system?

Let me tell you what I want to do, I want to make a really infinite terrain system, when you reach the end of one you load and render another one, now since I dont want to render two terrains at the same time, I want to create a Tween, that is I want to mix the images of terrain 1 and terrain 2 and get a tween then replace the current terrain and render it,

to do this I want to mix the upper half of terrain one images with lower half of terrain 2 images(if character is facing north) is this possible?

Btw congratulations on your work I just saw Unreal tournament screenshots at e3 coverage and they are the best looking ones in the ps2, I think you really handled vey well the aliasing problem !



Edited by - Azrael on May 15, 2000 12:32:49 PM
Hi Az,
I think what Chris is trying to explain is this.
The 128x128 heightfield is stored in the landscape data structure, and can easily be modified in real time.

one option is to load a 2048x2048 greyscale heightfield into a seperate buffer, and as your character nears the edge of the 128x128, do the usual Entity Coordinate fix on him, and read in a new 128x128 chunk from the heightfield buffer.

ie given visdist 20.

Normal Load Terrain.
Create large terrain buffer
Load full terrain into large buffer

Replace 128x128 in Terrain Struct with chunk from large buffer, depending on where you start.

if char walks north and gets within 20 of the edge of the 128x128 then physically shift him back to the center of the map, and read in a new 128x128 chunk, centered around your physical location on the 2048x2048 map.

Sorry, this is pretty difficult to explain, just try and keep in mind you will be working with 2 coordinate sets, one within the standard PR Terrain Structure & the major one within the 2048x2048 world.
With some clever programming, it should be OK to use the new terrain stuff, just have to remember your JPG will end up being tiled over the large map, and pre-generation of shadows would be impossible.

Cheers
Darrin




I follow you, to figure out where you at on the greyscale (color bitmap if you want a more granular heightfield, possibly using one of the color indexs as a texture indicator, say use the Red component) is reload the current terrain data set once your visibility gets D distance from going outside the current terrain data set.

Something like the following:

assume Player.x is the player''s X position in the world (2048x2048 map)
assume Player.y is the player''s Y position in the world (2048x2048 map)
assume D is the distance threshhold at which you want to reload/replace the current terrain data
assume V is the visibility distance

To calculate the starting terrain data set:

X_startupper = Player.x-(128/2) // don''t forget to check bounds
Y_startupper = Player.y-(128/2) // ditto
X_endlower = Player.x+(128/2) // ditto
Y_endlower = Plater.y+(128/2)

// just fill in the rows and columns from 0 to 127, the data set is a know size

To determine when to reload/reset the terrain data set:

if (( (Player.x - V - D) < X_startupper )// ( (Player.y - V - D) < Y_startupper ) // ( (Player.x + V + D) > X_endlower) // ( (Player.y + V + D) > Y_endlower) )
{
// reload/restet terrain data set, just use the fromulas above
}

I am probably off by one somewhere , but you should get the idea. D is an arbritrary number, and you''ll have to play around with it to optimize the process.
Naturally, as your terrain grows larger, it's storage requirements shoot up. This means that you really don't want to store a big huge terrain in memory... ;]

An 8-bit palettized BMP file (2048x2048) is around 4 MB in size, and you really don't want to go below that color-depth unless you want your heightmap to either look bad, or be limited to relatively flat areas. (24-bit is around 12 mb in storage, btw)

This is where the paging of terrain data from disk comes in...there are lots of techniques and certainly lots of problems. Two things you can do are to keep all the "sectors" around the one the camera is in loaded, and as the character crosses a boundary, you load the sectors around the new one the camera is in. The problem with this one is...what if the player is running along the border, perhaps hopping onto either side? You'll end up with severe disk-paging ugliness. Another idea would be to subdivide the current sector into quadrants, and based upon which one the camera is in, load the two sectors adjacent to it. Similar problem in that the user might be going back-and-forth across the quadrant boundaries...only in this case, while you're loading less data per-paging, there is the event that they happen to go boundary hopping at the origin of the 4 quadrants, meaning you can get really bad paging problems.

There are a couple ideas to combat this that I can think of sitting here...

1) a sector-cache, much like a texture cache that a texture-manager would use; so if they DO go boundary-hopping, you have it in your MRU cache, ready for loading.

2) similarly, you could use lazy-loading; that is, queue the loading, but only actually do it when the system can load the data it without a severe performance hit (ie, you're already loading some other data). this would probably require a file handling subsystem that can monitor such activity, and determine such things automatically. naturally you'll need the option to force-load it if the camera is about to see the sector, but it isn't loaded. ;]

I would think that these techniques lend themselves to smaller terrain sizes, as paging 5mb files isn't that good of an idea... ;]

Now, all this is in consideration for super-huge terrain data, but I suppose it would be alright to load a single 2048^2 heightfield, and sample from it... but that wouldn't be "infinite". ;]

Edited by - revolver on May 16, 2000 4:05:12 PM
Creativity is a bloody nuisance and an evil curse that will see to it that you die from stress and alcohol abuse at a very early age, that you piss off all your friends, break appointments, show up late, and have this strange bohemian urge (you know that decadent laid-back pimp-style way of life). The truly creative people I know all live lousy lives, never have time to see you, don't take care of themselves properly, have weird tastes in women and behave badly. They don't wash and they eat disgusting stuff, they are mentally unstable and are absolutely brilliant. (k10k)
Hi Guys,
With Paging, if you page using blocks of 64x64 data for paging, in a 2x2 grid, you can restrict the page load to when you are within visible distance of the edge of a block.
This will avoid the boundary hopping, as if you get to a boundary, it will page in the adjoining block, but will not release it until you go back to within vis dist of the oposite edge.

Another Idea to consider is Pseudo Random Tesselation.
Given a starting terrain of say 128x128, you can actually scale a 32x32 section into the 128x128 Terrain Struct, using a fractal algorithm to fill in the missing data.
If you use a Random Number Lookup, you could probably index it via the height difference between 2 samples, which would avoid the terrain actually changing over time.
You could also add a roughness factor too the random lookup, depending on the terrain type, and if given a low difference between samples, return 0 for the height dif, allowing for flat sections still.

Just some ideas.
Cheers
Darrin
Well, you could actually use Perlin noise functions to create pseudo-infinite terrain -- the only problem is the loss of artistic control, which is why I didn't touch on that. You can literally take a single 2D Perlin function, and use it to generate infinite terrain in all directions. The loss of artistic control (not utterly, but quite significantly), I would think is too great. I don't want to run around in computer generated fractal terrain; I want to be in artisticly crafted, interesting locations.

Of course, to save on storage, you could use some variant of wavelet compression on the images, but that's another topic. ;]

Now, scaling up data and then filling in data is interesting, but leaves two options: smoothing (perhaps parametrically), or false detail. I've seen both done, and while it's neat, you might not quite get what you want from an artistic perspective. If you'd like to see pictures of an engine I'm no longer working on, check out http://revolver.unrealty.net/images/orchid/ (..it uses bezier patches with a quadtree vis scheme). This engine has only as much detail as it has control points (generated randomly or from a heightmap), but these are expensive things; so while it's smooth it's not easy to get detail.

Edited by - revolver on May 16, 2000 7:53:50 PM
Creativity is a bloody nuisance and an evil curse that will see to it that you die from stress and alcohol abuse at a very early age, that you piss off all your friends, break appointments, show up late, and have this strange bohemian urge (you know that decadent laid-back pimp-style way of life). The truly creative people I know all live lousy lives, never have time to see you, don't take care of themselves properly, have weird tastes in women and behave badly. They don't wash and they eat disgusting stuff, they are mentally unstable and are absolutely brilliant. (k10k)
Hi Revolver,
How about this then,
Just use perlin noise to generate terrain outside of the general play area.
You could also insert proper had crafted "terrain patches" in the middle of the perlin noise terrain.

Cheers
Darrin
If you want rollings hills and something of a consistant terrain, you could just use sine and scale the known heights by a factor if about S. A point from the originally theorized bitmap would represent the height at point (X*S,Y*S). To find the interm points, use the point to either the left or right (probably better to use the point to the right) if the known point and average the heights, saving it in H. Just use H to scale a one (doesn''t have to be one) wave sine. To calculate the points, just divide S by 2pi, and run a series i from 0 to S, plug i it into the sine function to get the height for that point. Add X*S to i to get the x value, and y will be j+Y*S. Code snippet:

Hx = (X*S)/((X+1)*S); // X+1 is just notation for the next known point over
Hy = (Y*S)/((Y+1)*S); // dito

// to make the scaling more intuitive, you could scale after each loop iteration so that hills sloping up will slope up, etc.

for (j=0;j{
y = Hy*sin(j); // could use a lookup table
for (i=0;i {
x = Hx*sin(i); // could use a lookup table
}
}

It won''t be the most mathmatcially elogant way to do it, but it will work until you can find something better.

This topic is closed to new replies.

Advertisement