void InitMeshJobsPool()
        {
                        #if UNITY_WEBGL
            meshJobs = new MeshJobData[384];
                        #else
            meshJobs = new MeshJobData[(isMobilePlatform || !effectiveUseGeometryShaders) ? 256 : MESH_JOBS_POOL_SIZE];
                        #endif
            meshJobMeshLastIndex                = -1;
            meshJobMeshDataGenerationIndex      = -1;
            meshJobMeshDataGenerationReadyIndex = -1;
            meshJobMeshUploadIndex              = -1;
            int initialCapacity = effectiveUseGeometryShaders ? 2048 : 15000;
            for (int k = 0; k < meshJobs.Length; k++)
            {
                meshJobs [k].vertices = GetList <Vector3> (initialCapacity);
                meshJobs [k].uv0      = GetList <Vector4> (initialCapacity);
                meshJobs [k].colors   = GetList <Color32> (enableTinting ? initialCapacity : 4);
                meshJobs [k].buffers  = new MeshJobBuffer[MAX_MATERIALS_PER_CHUNK];
                if (effectiveUseGeometryShaders)
                {
                    meshJobs [k].uv2 = GetList <Vector4> (initialCapacity);
                }
                else
                {
                    meshJobs [k].normals = GetList <Vector3> (initialCapacity);
                    for (int j = 0; j < MAX_MATERIALS_PER_CHUNK; j++)
                    {
                        meshJobs [k].buffers [j].indices = new List <int> ();
                    }
                }
                if (enableColliders)
                {
                    meshJobs [k].colliderVertices = GetList <Vector3> (2700);
                    meshJobs [k].colliderIndices  = GetList <int> (4000);
                }
                if (enableNavMesh)
                {
                    meshJobs [k].navMeshVertices = GetList <Vector3> (2700);
                    meshJobs [k].navMeshIndices  = GetList <int> (4000);
                }
                meshJobs [k].mivs = new FastList <ModelInVoxel> ();
            }

            if (effectiveUseGeometryShaders)
            {
                tempGeoIndices = new FastFixedBuffer <int> [MAX_MATERIALS_PER_CHUNK];
                for (int k = 0; k < MAX_MATERIALS_PER_CHUNK; k++)
                {
                    tempGeoIndices [k] = new FastFixedBuffer <int> (16 * 16 * 16);
                }
            }
        }
Exemple #2
0
        /// <summary>
        /// Uses geometry-shader-based materials and mesh to render the chunk
        /// </summary>
        void GenerateMeshData_Geo(int jobIndex)
        {
            VoxelChunk chunk = meshJobs [jobIndex].chunk;

            tempChunkVertices    = meshJobs [jobIndex].vertices;
            tempChunkUV0         = meshJobs [jobIndex].uv0;
            tempChunkUV2         = meshJobs [jobIndex].uv2;
            tempChunkColors32    = meshJobs [jobIndex].colors;
            meshColliderVertices = meshJobs [jobIndex].colliderVertices;
            meshColliderIndices  = meshJobs [jobIndex].colliderIndices;
            navMeshVertices      = meshJobs [jobIndex].navMeshVertices;
            navMeshIndices       = meshJobs [jobIndex].navMeshIndices;
            mivs = meshJobs [jobIndex].mivs;

            tempChunkVertices.Clear();
            tempChunkUV0.Clear();
            tempChunkColors32.Clear();
            if (enableColliders)
            {
                meshColliderIndices.Clear();
                meshColliderVertices.Clear();
                if (enableNavMesh)
                {
                    navMeshIndices.Clear();
                    navMeshVertices.Clear();
                }
            }
            mivs.Clear();

            Voxel[] voxels = chunk.voxels;
            Vector4 uvAux, uv2Aux;

            tempChunkUV2.Clear();

            int          chunkUVIndex    = -1;
            int          chunkVoxelCount = 0;
            Color32      tintColor       = Misc.color32White;
            Vector3      pos             = Misc.vector3zero;
            ModelInVoxel miv             = new ModelInVoxel();

            const int V_ONE_Y_ROW = 18 * 18;
            const int V_ONE_Z_ROW = 18;

            int voxelIndex     = 0;
            int voxelSignature = 1;

            for (int y = 0; y < 16; y++)
            {
                int vy = (y + 1) * 18 * 18;
                for (int z = 0; z < 16; z++)
                {
                    int vyz = vy + (z + 1) * 18;
                    for (int x = 0; x < 16; x++, voxelIndex++)
                    {
                        voxels [voxelIndex].lightMesh = voxels [voxelIndex].light;
                        if (voxels [voxelIndex].hasContent != 1)
                        {
                            continue;
                        }

                        int vxyz = vyz + x + 1;

                        int     vindex = vxyz - 1;
                        Voxel[] chunk_middle_middle_left = chunk9 [virtualChunk [vindex].chunk9Index];
                        int     middle_middle_left       = virtualChunk [vindex].voxelIndex;

                        vindex = vxyz + 1;
                        Voxel[] chunk_middle_middle_right = chunk9 [virtualChunk [vindex].chunk9Index];
                        int     middle_middle_right       = virtualChunk [vindex].voxelIndex;

                        vindex = vxyz + V_ONE_Y_ROW;
                        Voxel[] chunk_top_middle_middle = chunk9 [virtualChunk [vindex].chunk9Index];
                        int     top_middle_middle       = virtualChunk [vindex].voxelIndex;

                        vindex = vxyz - V_ONE_Y_ROW;
                        Voxel[] chunk_bottom_middle_middle = chunk9 [virtualChunk [vindex].chunk9Index];
                        int     bottom_middle_middle       = virtualChunk [vindex].voxelIndex;

                        vindex = vxyz + V_ONE_Z_ROW;
                        Voxel[] chunk_middle_forward_middle = chunk9 [virtualChunk [vindex].chunk9Index];
                        int     middle_forward_middle       = virtualChunk [vindex].voxelIndex;

                        vindex = vxyz - V_ONE_Z_ROW;
                        Voxel[] chunk_middle_back_middle = chunk9 [virtualChunk [vindex].chunk9Index];
                        int     middle_back_middle       = virtualChunk [vindex].voxelIndex;

                        // If voxel is surrounded by material, don't render
                        int v1u = chunk_top_middle_middle [top_middle_middle].opaque;
                        int v1f = chunk_middle_forward_middle [middle_forward_middle].opaque;
                        int v1b = chunk_middle_back_middle [middle_back_middle].opaque;
                        int v1l = chunk_middle_middle_left [middle_middle_left].opaque;
                        int v1r = chunk_middle_middle_right [middle_middle_right].opaque;
                        int v1d = chunk_bottom_middle_middle [bottom_middle_middle].opaque;
                        if (v1u + v1f + v1b + v1l + v1r + v1d == 90)                         // 90 = 15 * 6
                        {
                            continue;
                        }

                        // top
                        vindex = vxyz + V_ONE_Y_ROW + V_ONE_Z_ROW - 1;
                        Voxel[] chunk_top_forward_left = chunk9 [virtualChunk [vindex].chunk9Index];
                        int     top_forward_left       = virtualChunk [vindex].voxelIndex;

                        vindex++;
                        Voxel[] chunk_top_forward_middle = chunk9 [virtualChunk [vindex].chunk9Index];
                        int     top_forward_middle       = virtualChunk [vindex].voxelIndex;

                        vindex++;
                        Voxel[] chunk_top_forward_right = chunk9 [virtualChunk [vindex].chunk9Index];
                        int     top_forward_right       = virtualChunk [vindex].voxelIndex;

                        vindex = vxyz + V_ONE_Y_ROW - 1;
                        Voxel[] chunk_top_middle_left = chunk9 [virtualChunk [vindex].chunk9Index];
                        int     top_middle_left       = virtualChunk [vindex].voxelIndex;

                        vindex += 2;
                        Voxel[] chunk_top_middle_right = chunk9 [virtualChunk [vindex].chunk9Index];
                        int     top_middle_right       = virtualChunk [vindex].voxelIndex;

                        vindex = vxyz + V_ONE_Y_ROW - V_ONE_Z_ROW - 1;
                        Voxel[] chunk_top_back_left = chunk9 [virtualChunk [vindex].chunk9Index];
                        int     top_back_left       = virtualChunk [vindex].voxelIndex;

                        vindex++;
                        Voxel[] chunk_top_back_middle = chunk9 [virtualChunk [vindex].chunk9Index];
                        int     top_back_middle       = virtualChunk [vindex].voxelIndex;

                        vindex++;
                        Voxel[] chunk_top_back_right = chunk9 [virtualChunk [vindex].chunk9Index];
                        int     top_back_right       = virtualChunk [vindex].voxelIndex;

                        // middle
                        vindex = vxyz + V_ONE_Z_ROW - 1;
                        Voxel[] chunk_middle_forward_left = chunk9 [virtualChunk [vindex].chunk9Index];
                        int     middle_forward_left       = virtualChunk [vindex].voxelIndex;

                        vindex += 2;
                        Voxel[] chunk_middle_forward_right = chunk9 [virtualChunk [vindex].chunk9Index];
                        int     middle_forward_right       = virtualChunk [vindex].voxelIndex;

                        vindex = vxyz - V_ONE_Z_ROW - 1;
                        Voxel[] chunk_middle_back_left = chunk9 [virtualChunk [vindex].chunk9Index];
                        int     middle_back_left       = virtualChunk [vindex].voxelIndex;

                        vindex += 2;
                        Voxel[] chunk_middle_back_right = chunk9 [virtualChunk [vindex].chunk9Index];
                        int     middle_back_right       = virtualChunk [vindex].voxelIndex;

                        // bottom
                        vindex = vxyz - V_ONE_Y_ROW + V_ONE_Z_ROW - 1;
                        Voxel[] chunk_bottom_forward_left = chunk9 [virtualChunk [vindex].chunk9Index];
                        int     bottom_forward_left       = virtualChunk [vindex].voxelIndex;

                        vindex++;
                        Voxel[] chunk_bottom_forward_middle = chunk9 [virtualChunk [vindex].chunk9Index];
                        int     bottom_forward_middle       = virtualChunk [vindex].voxelIndex;

                        vindex++;
                        Voxel[] chunk_bottom_forward_right = chunk9 [virtualChunk [vindex].chunk9Index];
                        int     bottom_forward_right       = virtualChunk [vindex].voxelIndex;

                        vindex = vxyz - V_ONE_Y_ROW - 1;
                        Voxel[] chunk_bottom_middle_left = chunk9 [virtualChunk [vindex].chunk9Index];
                        int     bottom_middle_left       = virtualChunk [vindex].voxelIndex;

                        vindex += 2;
                        Voxel[] chunk_bottom_middle_right = chunk9 [virtualChunk [vindex].chunk9Index];
                        int     bottom_middle_right       = virtualChunk [vindex].voxelIndex;

                        vindex = vxyz - V_ONE_Y_ROW - V_ONE_Z_ROW - 1;
                        Voxel[] chunk_bottom_back_left = chunk9 [virtualChunk [vindex].chunk9Index];
                        int     bottom_back_left       = virtualChunk [vindex].voxelIndex;

                        vindex++;
                        Voxel[] chunk_bottom_back_middle = chunk9 [virtualChunk [vindex].chunk9Index];
                        int     bottom_back_middle       = virtualChunk [vindex].voxelIndex;

                        vindex++;
                        Voxel[] chunk_bottom_back_right = chunk9 [virtualChunk [vindex].chunk9Index];
                        int     bottom_back_right       = virtualChunk [vindex].voxelIndex;


                        pos.y = y - 7.5f;
                        pos.z = z - 7.5f;
                        pos.x = x - 7.5f;

                        voxelSignature += voxelIndex;
                        chunkVoxelCount++;

                        VoxelDefinition       type    = voxelDefinitions [voxels [voxelIndex].typeIndex];
                        FastFixedBuffer <int> indices = tempGeoIndices[type.materialBufferIndex];

                        uvAux.x = type.textureIndexSide;
                        uvAux.y = type.textureIndexTop;
                        uvAux.z = type.textureIndexBottom;
                        uvAux.w = 0;

                        int occlusionX = 0;
                        int occlusionY = 0;
                        int occlusionZ = 0;
                        int occlusionW = 0;
                        int occ        = 0;

                        RenderType rt = type.renderType;
                        switch (rt)
                        {
                        case RenderType.Water:
                        {
                            ++chunkUVIndex;
                            indices.Add(chunkUVIndex);

                            uvAux.w = voxels [voxelIndex].light / 15f;

                            int hf = chunk_middle_forward_middle [middle_forward_middle].GetWaterLevel();
                            int hb = chunk_middle_back_middle [middle_back_middle].GetWaterLevel();
                            int hr = chunk_middle_middle_right [middle_middle_right].GetWaterLevel();
                            int hl = chunk_middle_middle_left [middle_middle_left].GetWaterLevel();

                            // compute water neighbours and account for foam
                            // back
                            occ = chunk_middle_back_middle [middle_back_middle].hasContent;
                            if (occ == 1)
                            {
                                // occlusionX bit = 0 means that face is visible
                                occlusionX |= 1;
                                if (hb == 0)
                                {
                                    occlusionY |= 1;
                                }
                            }

                            // front
                            occ = chunk_middle_forward_middle [middle_forward_middle].hasContent;
                            if (occ == 1)
                            {
                                occlusionX |= (1 << 1);
                                if (hf == 0)
                                {
                                    occlusionY |= 2;
                                }
                            }

                            int wh = voxels [voxelIndex].GetWaterLevel();
                            int th = chunk_top_middle_middle [top_middle_middle].GetWaterLevel();

                            // top (hide only if water level is full or voxel on top is water)
                            if (wh == 15 || th > 0)
                            {
                                occlusionX += ((chunk_top_middle_middle [top_middle_middle].hasContent & 1) << 2);
                            }

                            // down
                            occlusionX += ((chunk_bottom_middle_middle [bottom_middle_middle].hasContent & 1) << 3);

                            // left
                            occ = chunk_middle_middle_left [middle_middle_left].hasContent;
                            if (occ == 1)
                            {
                                occlusionX |= (1 << 4);
                                if (hl == 0)
                                {
                                    occlusionY |= 4;
                                }
                            }
                            // right
                            occ = chunk_middle_middle_right [middle_middle_right].hasContent;
                            if (occ == 1)
                            {
                                occlusionX += (1 << 5);
                                if (hr == 0)
                                {
                                    occlusionY |= 8;
                                }
                            }

                            // If there's water on top, full size
                            if (th > 0)
                            {
                                occlusionW  = 15 + (15 << 4) + (15 << 8) + (15 << 12);                          // full height
                                occlusionY += (1 << 8) + (1 << 10);                                             // neutral/no flow
                            }
                            else
                            {
                                // Get corners heights
                                int hfr = chunk_middle_forward_right [middle_forward_right].GetWaterLevel();
                                int hbr = chunk_middle_back_right [middle_back_right].GetWaterLevel();
                                int hbl = chunk_middle_back_left [middle_back_left].GetWaterLevel();
                                int hfl = chunk_middle_forward_left [middle_forward_left].GetWaterLevel();

                                // corner foam
                                if (type.showFoam)
                                {
                                    if (hbl == 0)
                                    {
                                        occlusionY |= chunk_middle_back_left [middle_back_left].hasContent << 4;
                                    }
                                    if (hfl == 0)
                                    {
                                        occlusionY |= chunk_middle_forward_left [middle_forward_left].hasContent << 5;
                                    }
                                    if (hfr == 0)
                                    {
                                        occlusionY |= chunk_middle_forward_right [middle_forward_right].hasContent << 6;
                                    }
                                    if (hbr == 0)
                                    {
                                        occlusionY |= chunk_middle_back_right [middle_back_right].hasContent << 7;
                                    }
                                }

                                int tf  = chunk_top_forward_middle [top_forward_middle].GetWaterLevel();
                                int tfr = chunk_top_forward_right [top_forward_right].GetWaterLevel();
                                int tr  = chunk_top_middle_right [top_middle_right].GetWaterLevel();
                                int tbr = chunk_top_back_right [top_back_right].GetWaterLevel();
                                int tb  = chunk_top_back_middle [top_back_middle].GetWaterLevel();
                                int tbl = chunk_top_back_left [top_back_left].GetWaterLevel();
                                int tl  = chunk_top_middle_left [top_middle_left].GetWaterLevel();
                                int tfl = chunk_top_forward_left [top_forward_left].GetWaterLevel();

                                // forward right corner
                                if (tf * hf + tfr * hfr + tr * hr > 0)
                                {
                                    hfr = 15;
                                }
                                else
                                {
                                    hfr = wh > hfr ? wh : hfr;
                                    if (hf > hfr)
                                    {
                                        hfr = hf;
                                    }
                                    if (hr > hfr)
                                    {
                                        hfr = hr;
                                    }
                                }
                                // bottom right corner
                                if (tr * hr + tbr * hbr + tb * hb > 0)
                                {
                                    hbr = 15;
                                }
                                else
                                {
                                    hbr = wh > hbr ? wh : hbr;
                                    if (hr > hbr)
                                    {
                                        hbr = hr;
                                    }
                                    if (hb > hbr)
                                    {
                                        hbr = hb;
                                    }
                                }
                                // bottom left corner
                                if (tb * hb + tbl * hbl + tl * hl > 0)
                                {
                                    hbl = 15;
                                }
                                else
                                {
                                    hbl = wh > hbl ? wh : hbl;
                                    if (hb > hbl)
                                    {
                                        hbl = hb;
                                    }
                                    if (hl > hbl)
                                    {
                                        hbl = hl;
                                    }
                                }
                                // forward left corner
                                if (tl * hl + tfl * hfl + tf * hf > 0)
                                {
                                    hfl = 15;
                                }
                                else
                                {
                                    hfl = wh > hfl ? wh : hfl;
                                    if (hl > hfl)
                                    {
                                        hfl = hl;
                                    }
                                    if (hf > hfl)
                                    {
                                        hfl = hf;
                                    }
                                }
                                occlusionW = hfr + (hbr << 4) + (hbl << 8) + (hfl << 12);

                                // flow
                                int fx = hfr + hbr - hfl - hbl;
                                if (fx > 0)
                                {
                                    fx = 2;
                                }
                                else if (fx < 0)
                                {
                                    fx = 0;
                                }
                                else
                                {
                                    fx = 1;
                                }
                                int fz = hfl + hfr - hbl - hbr;
                                if (fz > 0)
                                {
                                    fz = 2;
                                }
                                else if (fz < 0)
                                {
                                    fz = 0;
                                }
                                else
                                {
                                    fz = 1;
                                }

                                occlusionY += (fx << 8) + (fz << 10);
                            }

                            if (!type.showFoam)
                            {
                                occlusionY &= 0xFF00;
                            }
                            pos.y -= 0.5f;
                            tempChunkVertices.Add(pos);
                        }
                        break;

                        case RenderType.CutoutCross:
                        {
                            ++chunkUVIndex;
                            indices.Add(chunkUVIndex);
                            uvAux.w = voxels [voxelIndex].light / 15f;
                            Vector3 aux    = pos;
                            float   random = WorldRand.GetValue(pos);
                            uvAux.w *= 1f + (random - 0.45f) * type.colorVariation;                                     // * (1f + random * 0.3f;  // adds color variation
                            pos.x   += random * 0.5f - 0.25f;
                            aux.x   += 1f;
                            random   = WorldRand.GetValue(aux);
                            pos.z   += random * 0.5f - 0.25f;
                            pos.y   -= random * 0.1f;
                            tempChunkVertices.Add(pos);
                        }
                        break;

                        case RenderType.OpaqueNoAO:
                            ++chunkUVIndex;
                            tempChunkVertices.Add(pos);

                            v1b     = (v1b + 1) >> 4;                           // substitutes a comparisson with FULL_OPAQUE (15)
                            v1f     = (v1f + 1) >> 4;
                            v1u     = (v1u + 1) >> 4;
                            v1d     = (v1d + 1) >> 4;
                            v1l     = (v1l + 1) >> 4;
                            v1r     = (v1r + 1) >> 4;
                            uvAux.w = v1b + (v1f << 1) + (v1u << 2) + (v1d << 3) + (v1l << 4) + (v1r << 5);
                            indices.Add(chunkUVIndex);
                            break;

                        case RenderType.Transp6tex:
                        {
                            ++chunkUVIndex;
                            indices.Add(chunkUVIndex);
                            int rotation = voxels [voxelIndex].GetTextureRotation();
                            uvAux   = type.textureSideIndices [rotation].xyzw;
                            uvAux.w = voxels [voxelIndex].light;

                            // Avoid overlapping faces of same glass material
                            int typeIndex = voxels [voxelIndex].typeIndex;

                            // back
                            if (v1b == FULL_OPAQUE || chunk_middle_back_middle [middle_back_middle].typeIndex == typeIndex)
                            {
                                // occlusionX bit = 0 means that face is visible
                                occlusionX |= 1;
                            }

                            // front
                            if (v1f == FULL_OPAQUE || chunk_middle_forward_middle [middle_forward_middle].typeIndex == typeIndex)
                            {
                                occlusionX |= 2;
                            }

                            // up
                            if (v1u == FULL_OPAQUE || chunk_top_middle_middle [top_middle_middle].typeIndex == typeIndex)
                            {
                                occlusionX |= 4;
                            }

                            // down
                            if (v1d == FULL_OPAQUE || chunk_bottom_middle_middle [bottom_middle_middle].typeIndex == typeIndex)
                            {
                                occlusionX |= 8;
                            }

                            // left
                            if (v1l == FULL_OPAQUE || chunk_middle_middle_left [middle_middle_left].typeIndex == typeIndex)
                            {
                                occlusionX |= 16;
                            }
                            // right
                            if (v1r == FULL_OPAQUE || chunk_middle_middle_right [middle_middle_right].typeIndex == typeIndex)
                            {
                                occlusionX |= 32;
                            }
                            tempChunkVertices.Add(pos);

                            // Pass custom alpha
                            occlusionY = (int)(255 * type.alpha);

                            // Add collider data
                            if (enableColliders)
                            {
                                if (v1b == 0)
                                {
                                    greedyCollider.AddQuad(FaceDirection.Back, x, y, z);
                                }
                                if (v1f == 0)
                                {
                                    greedyCollider.AddQuad(FaceDirection.Forward, x, y, z);
                                }
                                if (v1u == 0)
                                {
                                    greedyCollider.AddQuad(FaceDirection.Top, x, z, y);
                                }
                                if (v1d == 0)
                                {
                                    greedyCollider.AddQuad(FaceDirection.Bottom, x, z, y);
                                }
                                if (v1l == 0)
                                {
                                    greedyCollider.AddQuad(FaceDirection.Left, z, y, x);
                                }
                                if (v1r == 0)
                                {
                                    greedyCollider.AddQuad(FaceDirection.Right, z, y, x);
                                }
                                if (enableNavMesh && type.navigatable)
                                {
                                    if (v1b == 0)
                                    {
                                        greedyNavMesh.AddQuad(FaceDirection.Back, x, y, z);
                                    }
                                    if (v1f == 0)
                                    {
                                        greedyNavMesh.AddQuad(FaceDirection.Forward, x, y, z);
                                    }
                                    if (v1u == 0)
                                    {
                                        greedyNavMesh.AddQuad(FaceDirection.Top, x, z, y);
                                    }
                                    if (v1l == 0)
                                    {
                                        greedyNavMesh.AddQuad(FaceDirection.Left, z, y, x);
                                    }
                                    if (v1r == 0)
                                    {
                                        greedyNavMesh.AddQuad(FaceDirection.Right, z, y, x);
                                    }
                                }
                            }
                        }
                        break;

                        default:                         //case RenderType.Custom:
                            miv.voxelIndex = voxelIndex;
                            miv.vd         = type;
                            mivs.Add(miv);
                            continue;

                        case RenderType.Empty:
                        {
                            v1b = (v1b + 1) >> 4;                                       // substitutes a comparison with FULL_OPAQUE (15)
                            v1f = (v1f + 1) >> 4;
                            v1u = (v1u + 1) >> 4;
                            v1d = (v1d + 1) >> 4;
                            v1l = (v1l + 1) >> 4;
                            v1r = (v1r + 1) >> 4;

                            // Add collider data
                            if (enableColliders)
                            {
                                if (v1b == 0)
                                {
                                    greedyCollider.AddQuad(FaceDirection.Back, x, y, z);
                                }
                                if (v1f == 0)
                                {
                                    greedyCollider.AddQuad(FaceDirection.Forward, x, y, z);
                                }
                                if (v1u == 0)
                                {
                                    greedyCollider.AddQuad(FaceDirection.Top, x, z, y);
                                }
                                if (v1d == 0)
                                {
                                    greedyCollider.AddQuad(FaceDirection.Bottom, x, z, y);
                                }
                                if (v1l == 0)
                                {
                                    greedyCollider.AddQuad(FaceDirection.Left, z, y, x);
                                }
                                if (v1r == 0)
                                {
                                    greedyCollider.AddQuad(FaceDirection.Right, z, y, x);
                                }
                                if (enableNavMesh && type.navigatable)
                                {
                                    if (v1b == 0)
                                    {
                                        greedyNavMesh.AddQuad(FaceDirection.Back, x, y, z);
                                    }
                                    if (v1f == 0)
                                    {
                                        greedyNavMesh.AddQuad(FaceDirection.Forward, x, y, z);
                                    }
                                    if (v1u == 0)
                                    {
                                        greedyNavMesh.AddQuad(FaceDirection.Top, x, z, y);
                                    }
                                    if (v1l == 0)
                                    {
                                        greedyNavMesh.AddQuad(FaceDirection.Left, z, y, x);
                                    }
                                    if (v1r == 0)
                                    {
                                        greedyNavMesh.AddQuad(FaceDirection.Right, z, y, x);
                                    }
                                }
                            }
                        }
                            continue;                             // loop

                        case RenderType.Opaque:
                        case RenderType.Opaque6tex:
                        case RenderType.Cutout:                         // Opaque & Cutout
                            ++chunkUVIndex;
                            tempChunkVertices.Add(pos);

                            if (rt == RenderType.Cutout)
                            {
                                indices.Add(chunkUVIndex);
                            }
                            else
                            {
                                indices.Add(chunkUVIndex);
                                int rotation = voxels [voxelIndex].GetTextureRotation();
                                uvAux = type.textureSideIndices [rotation].xyzw;
                            }

                            if (denseTrees && rt == RenderType.Cutout)
                            {
                                uvAux.w = 0;
                            }
                            else
                            {
                                v1b     = (v1b + 1) >> 4;                               // substitutes a comparisson with FULL_OPAQUE (15)
                                v1f     = (v1f + 1) >> 4;
                                v1u     = (v1u + 1) >> 4;
                                v1d     = (v1d + 1) >> 4;
                                v1l     = (v1l + 1) >> 4;
                                v1r     = (v1r + 1) >> 4;
                                uvAux.w = v1b + (v1f << 1) + (v1u << 2) + (v1d << 3) + (v1l << 4) + (v1r << 5);

                                // Add collider data
                                if (enableColliders && rt != RenderType.Cutout)
                                {
                                    if (v1b == 0)
                                    {
                                        greedyCollider.AddQuad(FaceDirection.Back, x, y, z);
                                    }
                                    if (v1f == 0)
                                    {
                                        greedyCollider.AddQuad(FaceDirection.Forward, x, y, z);
                                    }
                                    if (v1u == 0)
                                    {
                                        greedyCollider.AddQuad(FaceDirection.Top, x, z, y);
                                    }
                                    if (v1d == 0)
                                    {
                                        greedyCollider.AddQuad(FaceDirection.Bottom, x, z, y);
                                    }
                                    if (v1l == 0)
                                    {
                                        greedyCollider.AddQuad(FaceDirection.Left, z, y, x);
                                    }
                                    if (v1r == 0)
                                    {
                                        greedyCollider.AddQuad(FaceDirection.Right, z, y, x);
                                    }
                                    if (enableNavMesh && type.navigatable)
                                    {
                                        if (v1b == 0)
                                        {
                                            greedyNavMesh.AddQuad(FaceDirection.Back, x, y, z);
                                        }
                                        if (v1f == 0)
                                        {
                                            greedyNavMesh.AddQuad(FaceDirection.Forward, x, y, z);
                                        }
                                        if (v1u == 0)
                                        {
                                            greedyNavMesh.AddQuad(FaceDirection.Top, x, z, y);
                                        }
                                        if (v1l == 0)
                                        {
                                            greedyNavMesh.AddQuad(FaceDirection.Left, z, y, x);
                                        }
                                        if (v1r == 0)
                                        {
                                            greedyNavMesh.AddQuad(FaceDirection.Right, z, y, x);
                                        }
                                    }
                                }
                            }
                            if (rt == RenderType.Cutout)
                            {
                                // Add color variation
                                float random = WorldRand.GetValue(pos);
                                int   r      = (int)(255f * (1f + (random - 0.45f) * type.colorVariation));
                                uvAux.w += (r << 6);
                                if (type.windAnimation)
                                {
                                    uvAux.w += 65536;                                     //1 << 16;
                                }
                            }

                            int lu = chunk_top_middle_middle [top_middle_middle].light;
                            int ll = chunk_middle_middle_left [middle_middle_left].light;
                            int lf = chunk_middle_forward_middle [middle_forward_middle].light;
                            int lr = chunk_middle_middle_right [middle_middle_right].light;
                            int lb = chunk_middle_back_middle [middle_back_middle].light;
                            int ld = chunk_bottom_middle_middle [bottom_middle_middle].light;

                                                                                        #if UNITY_EDITOR
                            if (enableSmoothLighting && !draftModeActive)
                            {
                                                                #else
                            if (enableSmoothLighting)
                            {
                                                                #endif
                                int v2r  = chunk_top_middle_right [top_middle_right].light;
                                int v2br = chunk_top_back_right [top_back_right].light;
                                int v2b  = chunk_top_back_middle [top_back_middle].light;
                                int v2bl = chunk_top_back_left [top_back_left].light;
                                int v2l  = chunk_top_middle_left [top_middle_left].light;
                                int v2fl = chunk_top_forward_left [top_forward_left].light;
                                int v2f  = chunk_top_forward_middle [top_forward_middle].light;
                                int v2fr = chunk_top_forward_right [top_forward_right].light;

                                int v1fr = chunk_middle_forward_right [middle_forward_right].light;
                                int v1br = chunk_middle_back_right [middle_back_right].light;
                                int v1bl = chunk_middle_back_left [middle_back_left].light;
                                int v1fl = chunk_middle_forward_left [middle_forward_left].light;

                                int v0r  = chunk_bottom_middle_right [bottom_middle_right].light;
                                int v0br = chunk_bottom_back_right [bottom_back_right].light;
                                int v0b  = chunk_bottom_back_middle [bottom_back_middle].light;
                                int v0bl = chunk_bottom_back_left [bottom_back_left].light;
                                int v0l  = chunk_bottom_middle_left [bottom_middle_left].light;
                                int v0fl = chunk_bottom_forward_left [bottom_forward_left].light;
                                int v0f  = chunk_bottom_forward_middle [bottom_forward_middle].light;
                                int v0fr = chunk_bottom_forward_right [bottom_forward_right].light;

                                // Backwards face
                                // Vertex 0
                                occ         = ((lb + v0b + v0bl + v1bl) >> 2);
                                occlusionX += occ;
                                // Vertex 1
                                occ         = ((lb + v0b + v0br + v1br) >> 2);
                                occlusionX += occ << 4;
                                // Vertex 2
                                occ         = ((lb + v1bl + v2bl + v2b) >> 2);
                                occlusionX += occ << 8;
                                // Vertex 3
                                occ         = ((lb + v2b + v2br + v1br) >> 2);
                                occlusionX += occ << 12;

                                // Forward face
                                // Vertex 5
                                occ         = ((lf + v0f + v0fr + v1fr) >> 2);
                                occlusionX += occ << 16;
                                // Vertex 4
                                occ         = ((lf + v0f + v0fl + v1fl) >> 2);
                                occlusionX += occ << 20;
                                // Vertex 6
                                occ         = ((lf + v1fr + v2fr + v2f) >> 2);
                                occlusionY += occ;
                                // Vertex 7
                                occ         = ((lf + v2f + v2fl + v1fl) >> 2);
                                occlusionY += occ << 4;

                                // Top face
                                // Vertex 2
                                occ         = ((lu + v2b + v2bl + v2l) >> 2);
                                occlusionY += occ << 8;
                                // Vertex 3
                                occ         = ((lu + v2b + v2br + v2r) >> 2);
                                occlusionY += occ << 12;
                                // Vertex 7
                                occ         = ((lu + v2l + v2fl + v2f)) >> 2;
                                occlusionY += occ << 16;
                                // Vertex 6
                                occ         = ((lu + v2r + v2fr + v2f) >> 2);
                                occlusionY += occ << 20;

                                // Left face
                                // Vertex 0
                                occ         = ((ll + v1bl + v0l + v0bl) >> 2);
                                occlusionZ += occ;
                                // Vertex 4
                                occ         = ((ll + v1fl + v0l + v0fl) >> 2);
                                occlusionZ += occ << 4;
                                // Vertex 2
                                occ         = ((ll + v2l + v2bl + v1bl) >> 2);
                                occlusionZ += occ << 8;
                                // Vertex 7
                                occ         = ((ll + v2l + v2fl + v1fl) >> 2);
                                occlusionZ += occ << 12;

                                // Right face
                                // Vertex 1
                                occ         = ((lr + v1br + v0r + v0br) >> 2);
                                occlusionZ += occ << 16;
                                // Vertex 5
                                occ         = ((lr + v1fr + v0r + v0fr) >> 2);
                                occlusionZ += occ << 20;
                                // Vertex 3
                                occ         = ((lr + v2r + v2br + v1br) >> 2);
                                occlusionW += occ;
                                // Vertex 6
                                occ         = ((lr + v2r + v2fr + v1fr) >> 2);
                                occlusionW += occ << 4;

                                // Bottom face
                                // Vertex 0
                                occ         = ((ld + v0b + v0l + v0bl) >> 2);
                                occlusionW += occ << 8;
                                // Vertex 1
                                occ         = ((ld + v0b + v0r + v0br) >> 2);
                                occlusionW += occ << 12;
                                // Vertex 4
                                occ         = ((ld + v0f + v0l + v0fl) >> 2);
                                occlusionW += occ << 16;
                                // Vertex 5
                                occ         = ((ld + v0f + v0r + v0fr) >> 2);
                                occlusionW += occ << 20;
                            }
                            else
                            {
                                occlusionX  = lb;                                // back
                                occlusionX += lf << 4;                           // forward
                                occlusionX += lu << 8;                           // top
                                occlusionX += ll << 12;                          // // left
                                occlusionX += lr << 16;                          // right
                                occlusionX += ld << 20;                          // bottom
                            }
                            break;
                        }
                        tempChunkUV0.Add(uvAux);
                        uv2Aux.x = occlusionX;
                        uv2Aux.y = occlusionY;
                        uv2Aux.z = occlusionZ;
                        uv2Aux.w = occlusionW;
                        tempChunkUV2.Add(uv2Aux);

                        if (enableTinting)
                        {
                            tintColor.r = voxels [voxelIndex].red;
                            tintColor.g = voxels [voxelIndex].green;
                            tintColor.b = voxels [voxelIndex].blue;
                            tempChunkColors32.Add(tintColor);
                        }
                    }
                }
            }

            meshJobs [jobIndex].chunk = chunk;

            // chunkVoxelCount includes MIVs
            int nonMivsCount = chunkUVIndex + 1;
            meshJobs [jobIndex].totalVisibleVoxels = nonMivsCount;

            if (chunkVoxelCount == 0)
            {
                return;
            }

            if (voxelSignature != chunk.voxelSignature)
            {
                chunk.needsColliderRebuild = true;
            }
            chunk.voxelSignature = voxelSignature;

            if (enableColliders)
            {
                if (chunk.needsColliderRebuild)
                {
                    greedyCollider.FlushTriangles(meshColliderVertices, meshColliderIndices);
                    if (enableNavMesh)
                    {
                        greedyNavMesh.FlushTriangles(navMeshVertices, navMeshIndices);
                    }
                }
                else
                {
                    greedyCollider.Clear();
                    greedyNavMesh.Clear();
                }
            }

            // job index 0 lists are used as generic buffers but we need to convert them to array to use SetIndices API :(
            int subMeshCount = 0;
            for (int k = 0; k < MAX_MATERIALS_PER_CHUNK; k++)
            {
                if (tempGeoIndices [k].count > 0)
                {
                    subMeshCount++;
                    meshJobs [jobIndex].buffers [k].indicesArray = tempGeoIndices [k].ToArray();
                    meshJobs [jobIndex].buffers [k].indicesCount = meshJobs [jobIndex].buffers [k].indicesArray.Length;
                }
            }
            meshJobs [jobIndex].subMeshCount = subMeshCount;

            meshJobs [jobIndex].colliderVertices = meshColliderVertices;
            meshJobs [jobIndex].colliderIndices  = meshColliderIndices;

            meshJobs [jobIndex].navMeshVertices = navMeshVertices;
            meshJobs [jobIndex].navMeshIndices  = navMeshIndices;

            meshJobs [jobIndex].mivs = mivs;
        }
    }