12
\$\begingroup\$

Playing around with creating minecraftish/lego world landscapes in Unity 3D (procedurally generated voxel landscapes with cubes), I'm finding that the meshes created for these landscapes take up a LOT of memory. The mesh currently only consists of vertices for visible sides of a cube. Memory usage for a complex terrain may take 6 or 7 hundred megs.

These meshes could be optimized, but I'm struggling to find a decent algorithm to do this.

The algorithm has to take into account that you don't want to "merge" blocks that are of different terrain types. I guess a really simple start might be to just process all blocks along one axis, and do extra sweeps for the other two axis.

I need to keep the mesh shape, that is no merging of vertices to the point that empty or solid space is changed. The reason is, there may be creatures/etc that still need to navigate around the mesh. So I can't just create a really low detail, distorted mesh.

Any thoughts/suggestions/tips on this?

\$\endgroup\$
2
  • 2
    \$\begingroup\$ Why are you storing vertices for a known size cube? Do it algorithmically; or use a shared vertex buffer. \$\endgroup\$ Commented Jul 31, 2011 at 21:43
  • \$\begingroup\$ Why polygonal mesh? Voxel can be rendered quite efficiently just like they are. For one voxel cube You need 3 floats (x,y,z), for 1 box You need around 8*3 floats (8 vertices), and that in case You have implicit edges and polygons. Maybe Unity is not the tool for this voxel problem. \$\endgroup\$
    – user712092
    Commented Oct 29, 2011 at 14:04

3 Answers 3

5
\$\begingroup\$

My question is:

Why would you need the mesh itself to do creature movement?

Can't you do the pathing calculation on a 3d matrix of id's?

I think Minecraft uses a 3d matrix with 4 bits pr block. It also only simulates creatures a certain radius around the player.

You could store your chunks in a oc-tree structure, where each chunk is compressed.

If you keep the compressed data in RAM you can decompress the data quite quickly when needed.

alt text

\$\endgroup\$
14
  • \$\begingroup\$ I was relying on having the mesh for built in collision detection with Unity, but there's nothing to stop me from just testing collision/pathing against a custom data structure. However, I still need to create a visible mesh for displaying the terrain, and this is what I need to optimize. \$\endgroup\$
    – JayCeeL
    Commented Nov 12, 2010 at 19:18
  • \$\begingroup\$ One other point...as you can see by the screenshot...there's not a whole lot of this terrain that is flat. The meshes are generally rough surfaces of cubes, but I think there is some room for optimizing the mesh faces/vertices. It seems like an octree would be best for data which has a lot of similiar blocks of data, instead of of "jaggy" data. Or is this not correct? \$\endgroup\$
    – JayCeeL
    Commented Nov 12, 2010 at 19:35
  • \$\begingroup\$ @Gatorfrog: Remember, empty space is a data too. if it's jaggy then sure, there will be lots of bits signalling its empty. The octree is just there for you to figure out which chunks you should decompress before you render them. Empty space will just be a bunch of zeroes. My dayjob involves working with a very sophisticated voxel rendering library. My next post will describe what they do. \$\endgroup\$
    – Nailer
    Commented Nov 12, 2010 at 19:53
  • \$\begingroup\$ The library i work with does the following: Creates chunks of data and store them in a flat file database. Each chunk has an id. Each cube consists of many chunks. For each chunk there are created a certain number of levels of detail. Where the highest level of detail has 100% of the voxels, the second highest has 25% of all the voxels and then divide by 4 all for each subsequent level. Chunks that are close to you can be visualized using the highest level of detail. \$\endgroup\$
    – Nailer
    Commented Nov 12, 2010 at 19:56
  • \$\begingroup\$ all data is shipped in a compressed form from the RAM to the VRAM where it is inflated by GPGPU compression algorithms running in CUDA. This saves a lot of memory bandwith. So: CHeck where the player is and get high level of detail chunks there, the things furthest away can easily be visualized using one of the lower LODs. \$\endgroup\$
    – Nailer
    Commented Nov 12, 2010 at 19:59
1
\$\begingroup\$

How about using an octree to store the terrain?

E.g. air = no node, all other terrain types would have a node with the terrain type.

When inserting/removing nodes, you could check if all eight children of each node on the modified tree path have the same terain type and merge them if needed. That way, big blocks of the same material would only take up one node.

\$\endgroup\$
0
\$\begingroup\$

Are you only creating the cubes for parts of the geometry the player can see? That would be my first step. Depending on the size of your terrain you don't have to have the entirety of the world loaded/drawing/visible/whatever.

\$\endgroup\$
1
  • \$\begingroup\$ I'm only creating the mesh for sides of cubes that have empty air next to them. As far as not drawing meshes that the player can't see...I thought about excluding any chunks that didn't have any visible blocks, such as underground caves or holes that led into the ground at an angle. I would definitely not be able to rely on my meshes for collision/pathing at that point, though. \$\endgroup\$
    – JayCeeL
    Commented Nov 12, 2010 at 19:21

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .