Nocktion / TransUnity

A rework of my old transvoxel implementation with lot of improvements.
17 stars 4 forks source link

Help request #1

Open taori opened 3 years ago

taori commented 3 years ago

Hello there. Thanks for making this project.

I was wondering if you could help enlighten me on some part of the code: I am trying to make some alteration on the ground so i can have different patches of elements instead of just a grass one but it seems that my whole concept of the casecode logic is flawed.

I have read the original pdf document and concluded from that, that a chunk is divided into cells and each of those cells has edges. which enclose the voxel atoms depending on whether there is an element at this position (any value but zero) or not (value zero)

I was thinking that the sample values currently provided are just randomly generated values to mimic different voxel atom elements instead of having an underlying meaning but that appears to be wrong?

The code in question is this:

                byte caseCode = (byte)((density[0] >> 7 & 1)
                                | (density[1] >> 6 & 2)
                                | (density[2] >> 5 & 4)
                                | (density[3] >> 4 & 8)
                                | (density[4] >> 3 & 16)
                                | (density[5] >> 2 & 32)
                                | (density[6] >> 1 & 64)
                                | (density[7] & 128));

My own code is this:

(if i replace the != 0 part with a filter i could then generate meshes for individual elements, iron, copper etc)

                byte caseCode = (byte)((density[0] != 0 ? 1 : 0)
                                | (density[1] != 0 ? 2 : 0)
                                | (density[2] != 0 ? 4 : 0)
                                | (density[3] != 0 ? 8 : 0)
                                | (density[4] != 0 ? 16 : 0)
                                | (density[5] != 0 ? 32 : 0)
                                | (density[6] != 0 ? 64 : 0)
                                | (density[7] != 0 ? 128 : 0));

My thought was that the density array is nothing but an array of positional information about whether the edge of a cell voxel contains something or not.

I know this isn't your problem but i was wondering if you could perhaps share some of your knowledge on this with me.

Best regards Andreas

Nocktion commented 3 years ago

Hello Andreas,

You are right about the part that the density values represent cells and it gives us information if the cell is solid (has something in it) or empty. Now the caseCode is calculated using a binary operation and it is only responsible for the mesh itself, but not the texturing. The algorithm decides based on the caseCode, where to create triangles.

For texturing I used a UV map, which unfortunately is not the most beautiful solution, but it works, I'm planning to implement triplanar shading however.

To add multiple textures in my code you will need to create a texture atlas. And map the UVs to the vertices.

uvs.Add(uvOffset[vcase]);// uvBase + uvOffset[vcase]);

vcase = (byte)(vcase == 3 ? 0 : vcase + 1);

Currently this is in the Polygonization.cs, this is the code responsible for UV mapping. Now you will have to modify it a little bit.

  1. Change the static offset variable according to the size of your atlas (eg.: there are 2x2 textures then the offset is 1/2, if it's 4x4 then the offset is 1/4)
  2. The above code changes like this:
    uvs.Add(uvBase + uvOffset[vcase]);
    vcase = (byte)(vcase == 3 ? 0 : vcase + 1);
  3. The last thing you need is the uvBase. The UV base is the location of your texture on the atlas. You can see how the uvBases are calculated on the picture below. Note that the coordinates need to be scaled in between 0 and 1. So if you use a 4x4 atlas you would number them like: (0f, 0f), (0.25f, 0f), (0.5f, 0f), (0.75f, 0f), etc

The uvBase is the normalized coordinate of the bottom left corner of the texture of your choice inside the atlas. The way you store uvBases is actually up to you. I used to store them inside every cell as two bytes (x and y) for performance reasons. And on initialization I just assigned the texture coordinates to the cells.

exampleAtlas

I hope this solves your problem, but if not feel free to ask, I'm more than happy to help. Also I'm planning to push a little update with some performance changes and multi texture support in the near future.

taori commented 3 years ago

Thanks for your explanation. It really did help me yes! Now it is time to try implement it after some further changes. This transvoxel stuff sure is a difficult read. haha.

Thanks again!

taori commented 3 years ago

So i think i have figured out why it isn't working properly for my algorithm. i was looking at this project and another project for guidance. but while yours also has the transvoxel tables too, it does not actually use them but instead uses the ordinary marching cube algorithm