Question

I am creating large scale worlds using 16*16*16 voxel chunks which are stacked up to 32*32*32 in dimensions and I have hit a bit of a Bump in the road so to speak.

I want to create large structures that span 20+*20+*20+ chunks in volume which are created from procedurally generated structures as well as using templates for some of the content. Now I have an issue. The visual render range is up to 32*32*32 chunks and while I have up to maybe 40*40*40 chunks held in memory at a time when possible.

The structures can be anything like towns, dungeons and roads. I was thinking something like perlin worms for roads and just lay them over the terrain in the x,z and then analyze the path for bridges etc..

The structures and collection of structures need to be pre-generated before the player is within visual range or work more like perlin noise does for heightmaps (best solution). (to avoid the players seeing the generator at work). They also need to be consistent with the world seed every time.

I have thought about this a bit and have 2 possible solutions.

1) Generate the structures based on a point of origin for the structure generator. This causes several issues though as even if I generate from the center of the structure, the structures can easily cross into the potential visual range of the player.

2) Pre-Generate "unreachable" chunks and then page them in and out in order to generate the structures using the above method. This also seems rather unnecessary.

Both methods need to analyze the terrain in large quantities for a valid location to spawn the structures.

I was hoping somebody might have a more organic solution or even just a simpler solution that doesn't require me to "Look" so far ahead.

Thank you in advance.

EDIT:

I had an idea for dungeon generation in which I generate point clouds/nodes for rooms. Steps:

1) When the generator finds a "node" it creates an x, y and z size to create a box basing it from the originator point of the room** (centre or corner of the room) and the room type.

**x,y,z relative to 0,0,0 worldspace calculated like so new Vector3((chunkX*16)+voxelX,(chunkY*16)+voxelY,(chunkZ*16)+voxelZ)

2) Once a room size is calculated, check for overlaps and if one is found do one of several things. If the room overlap is high up lower it down till either the roof or the floor are flush. If the roof is flush build a stairs up to the room and remove the walls that intersect.

3) Look Down, North and East for a room maybe with a small cone and attempt to create a hallway between them.

This would probably work somewhat, especially if the center of the dungeon is the main hall/boss room.

This would be different for towns, cities, and surface dungeons. Still seems a little choppy though. Any ideas?

Was it helpful?

Solution

I faced a similar problem for a Minecraft mod I am writing. I want to have a number of overlapping "empires" which each create structures. But I don't want the structures to step on each other.

So, for this, I broke the world into arbitrary sized tiles. (Compare to your 32x32x32 regions.) I also came up with a "radius of influence". This is how far from the center point that it could create structures. Each tile had an instance of a provider class assigned to it with a unique seed.

Two methods on this class were provided for structure generation.

First, was a function that would return where it wanted to create structures. But only to the resolution of chunks. (Compare to your 16x16x16 block sets.) Each provider class instance had a priority, so in the case of two providers trying to rezz a structure in the same chunks, the higher priority one would win.

The second function would be passed a world instance, and one of the data items returned by the first function and would be asked to actually create it.

Everything pieces together like this:

We get a request to resolve a certain chunk of the world. We work out the provider for the tile the chunk is in, and then all the providers for all the tiles that are within the maximum radius of that tile. We now have every provider that could influence this chunk. We call the first function on each of them, if they haven't been called already, and register what chunks each of them has claimed into a global map.

At this point, we've consulted everything that could have an influence on this chunk. We then ask that registry if someone has claimed this chunk. If so, we call back into that provider (method #2) with the chunk and the world instance and get it to draw the bits for this part of its structure.

Does that give you enough of an idea for a general approach to your problem?

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top