2
\$\begingroup\$

I'm trying to optimize the rendering of a collection of cubes, (based on an answer I was given to another question I asked). I understand the logic behind occlusion culling, but I'm having trouble with the code.

When I create a cube, I want to determine if that cube is touching another existing cube, and if so I don't want to generate the redundant data in my vertex or index buffers.

I'm planning on making a method that I call from my cube constructor so that everytime I create a cube, these checks are made, and neither occluded face is ever drawn.

How would I go about this?

\$\endgroup\$
  • \$\begingroup\$ I've reformatted your question to (a) remove the need to visit the original questions for context and (b) remove the code dump, which I don't feel is warranted given the nature of what you are asking (and which serves to make the question more imposing, reducing the likelyhood that you'll get a good answer). \$\endgroup\$ – user1430 Jun 28 '13 at 6:11
  • \$\begingroup\$ Also, it's best not to refer to other answers by order (as in "the first answer") because they aren't always displayed in the same order for every user. Link directly to the answer instead. I linked the answer that showed up for me as the first, and edited your question accordingly. Please adjust if that wasn't the answer you were thinking of. \$\endgroup\$ – user1430 Jun 28 '13 at 6:12
  • \$\begingroup\$ Thanks. I felt that without the code, this question would be too similar to the other question I asked. I want a more specific answer based on the code I already have because I'm having more trouble with it than I expected \$\endgroup\$ – Christian Frantz Jun 28 '13 at 6:12
  • \$\begingroup\$ Feel free to put it back if you think it would be useful (ideally at the bottom of the question). \$\endgroup\$ – user1430 Jun 28 '13 at 6:13
  • \$\begingroup\$ I'll see what kind of answer people can come up with. Hopefully I can make something out of pseudocode, but I'm not good at that lol \$\endgroup\$ – Christian Frantz Jun 28 '13 at 6:15
1
\$\begingroup\$

It sounds like you're taking a very OOP approach to this problem, when really you should be taking a more functional approach (just the approach - we're not going "all-in" here - we're basically just applying functions to buffers).

Instead of a cube class (reference type) with a constructor that gets "created", simply have a cube struct (value type) with a very small memory footprint. This could be as simple as an int that indicates what kind of cube it is. The important thing is to, like an integer, have a "zero" value that represents an empty space.

Then create an array of these. For simplicity you can use a 3D array. Later on you might want to consider a 1D array (slightly faster in .NET) and trying to read through it while touching as little memory as possible. But for now this will do - it is far better than allocating thousands of cube objects flung all over heap memory!

The position of each cube is implicitly defined by its position in the array.

Then, taking a functional approach, you transform that "cube" data into "vertex" data for a given chunk (or the whole world, if it's small enough). A method to do that transformation might have code that looks a little something like this:

for(int y = 0; y < height; y++)
{
    for(int x = 0; x < width; x++)
    {
        for(int z = 0; z < depth; z++)
        {
            if(x-1 >= 0 && cubes[x-1, y, z])
                AddFace(x, y, z, Face.Left);
            if(x+1 < width  && cubes[x+1, y, z])
                AddFace(x, y, z, Face.Right);

            if(z-1 >= 0 && cubes[x, y, z-1])
                AddFace(x, y, z, Face.Back);
            if(z+1 < depth  && cubes[x, y, z+1])
                AddFace(x, y, z, Face.Front);

            if(y-1 >= 0 && cubes[x, y-1, z])
                AddFace(x, y, z, Face.Bottom);
            if(y+1 < depth  && cubes[x, y+1, z])
                AddFace(x, y, z, Face.Top);
        }
    }
}

This takes advantage of the fact the cube data is stored in a spatially meaningful way.

I'll leave AddFace as an exercise. But basically it should append appropriate vertices and indices to a List of faces for the whole chunk. Which you'd then use to SetData() to your chunk's VertexBuffer and IndexBuffer (via ToArray()).

(As mentioned in comments in our discussion over here, you can save yourself the copying that ToArray() does by using an array directly, instead of a List, and manually managing your count and capacity. Take a look at the code in this answer)

\$\endgroup\$
  • \$\begingroup\$ Hmm so the addface method is the challenged here. I need to figure out which vertices or indices are for each face, and then save the faces as Bottom or Top. The constructor would just be something like AddFace(Vector3 Position, Face) or whatever face will be \$\endgroup\$ – Christian Frantz Jun 29 '13 at 2:09
  • \$\begingroup\$ Ok I tried and had no luck. I understand what you're saying and I know how to set the data for the buffers, but I'm confusing myself with all the veritces and indices. Should I use an enum for the faces? and set each face equal to a vertex and index? \$\endgroup\$ – Christian Frantz Jun 29 '13 at 5:05
  • \$\begingroup\$ Alright so enumerations don't work for this...is it possible to just take the values from the arrays I already have and add them into a vertex and index buffer list? \$\endgroup\$ – Christian Frantz Jun 29 '13 at 5:33
  • \$\begingroup\$ I've thought about it for a bit and I think it's a good idea to get rid of my cube and cubedrawable classes and use a struct like you said. I'd only need one class for loading my map that way \$\endgroup\$ – Christian Frantz Jun 29 '13 at 6:22
  • \$\begingroup\$ In my code I have assumed that Face is an enum, and that the AddFace method contains some kind of switch statement in it that creates the appropriate kind of face around the given position. But this method signature was only for illustration only (as was the way cubes[] is implicitly castable to boolean). You can certainly modify it to suit your needs. \$\endgroup\$ – Andrew Russell Jun 29 '13 at 7:44

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.