Esempio n. 1
0
 static float CalcAO(int side1, int side2, ref NativeArray3x3 <Block> blocks, NativeArray <BlockData> blockData, int c1, int c2, int c3)
 {
     if (side1 + side2 == 2)
     {
         return(AOMIN);
     }
     return((3.0f - side1 - side2 - GetOpacity(ref blocks, blockData, c1, c2, c3)) / 3.0f * (1.0f - AOMIN) + AOMIN);
 }
Esempio n. 2
0
    public static void LightUpdate(ref NativeArray3x3 <Light> lights, NativeList <Face> faces, NativeList <Color32> colors)
    {
        for (int i = 0; i < faces.Length; ++i)
        {
            int pos = faces[i].pos;
            int x   = pos % Chunk.SIZE;
            int y   = pos / (Chunk.SIZE * Chunk.SIZE);
            int z   = (pos % (Chunk.SIZE * Chunk.SIZE)) / Chunk.SIZE;

            //Light curLight = lights.Get(x, y, z);
            //if (GetIsLight(curLight.torch)) {
            //    colors.Add(GetColorFromLight(curLight));
            //} else {
            switch (faces[i].dir)
            {
            case Dir.west:
                colors.Add(GetColorFromLight(lights.Get(x - 1, y, z)));
                break;

            case Dir.down:
                colors.Add(GetColorFromLight(lights.Get(x, y - 1, z)));
                break;

            case Dir.south:
                colors.Add(GetColorFromLight(lights.Get(x, y, z - 1)));
                break;

            case Dir.east:
                colors.Add(GetColorFromLight(lights.Get(x + 1, y, z)));
                break;

            case Dir.up:
                colors.Add(GetColorFromLight(lights.Get(x, y + 1, z)));
                break;

            case Dir.north:
                colors.Add(GetColorFromLight(lights.Get(x, y, z + 1)));
                break;

            default:
                colors.Add(GetColorFromLight(lights.Get(x, y, z)));
                break;
            }
            //}

            // add the last color 3 more times (4 colors per face)
            Color32 lastColor = colors[colors.Length - 1];
            colors.Add(lastColor);
            colors.Add(lastColor);
            colors.Add(lastColor);
        }
    }
Esempio n. 3
0
    // not sure if i really need separate case for signs of each direction, could prob just have them together
    public void AddTileUvs(int slice, Dir dir, int x, int y, int z, ref NativeArray3x3 <Block> blocks, NativeArray <BlockData> blockData)
    {
        // tried also adding +x to X directions and +y to Ys and etc but made more tiling artifacts
        // maybe adding x*2 or something. but current setup is not bad looking... can think about tiling options
        switch (dir)
        {
        case Dir.west:
            uvs.Add(new Vector3((z) / ft, (y) / ft, slice));
            uvs.Add(new Vector3((z) / ft, (y + 1) / ft, slice));
            uvs.Add(new Vector3((z - 1) / ft, (y + 1) / ft, slice));
            uvs.Add(new Vector3((z - 1) / ft, (y) / ft, slice));
            break;

        case Dir.east:
            uvs.Add(new Vector3((z) / ft, (y) / ft, slice));
            uvs.Add(new Vector3((z) / ft, (y + 1) / ft, slice));
            uvs.Add(new Vector3((z + 1) / ft, (y + 1) / ft, slice));
            uvs.Add(new Vector3((z + 1) / ft, (y) / ft, slice));
            break;

        case Dir.up:
            uvs.Add(new Vector3((z) / ft, (x) / ft, slice));
            uvs.Add(new Vector3((z) / ft, (x + 1) / ft, slice));
            uvs.Add(new Vector3((z - 1) / ft, (x + 1) / ft, slice));
            uvs.Add(new Vector3((z - 1) / ft, (x) / ft, slice));
            break;

        case Dir.down:
            uvs.Add(new Vector3((z) / ft, (x) / ft, slice));
            uvs.Add(new Vector3((z) / ft, (x + 1) / ft, slice));
            uvs.Add(new Vector3((z + 1) / ft, (x + 1) / ft, slice));
            uvs.Add(new Vector3((z + 1) / ft, (x) / ft, slice));
            break;

        case Dir.north:
            uvs.Add(new Vector3((x) / ft, (y) / ft, slice));
            uvs.Add(new Vector3((x) / ft, (y + 1) / ft, slice));
            uvs.Add(new Vector3((x - 1) / ft, (y + 1) / ft, slice));
            uvs.Add(new Vector3((x - 1) / ft, (y) / ft, slice));
            break;

        case Dir.south:
            uvs.Add(new Vector3((x) / ft, (y) / ft, slice));
            uvs.Add(new Vector3((x) / ft, (y + 1) / ft, slice));
            uvs.Add(new Vector3((x + 1) / ft, (y + 1) / ft, slice));
            uvs.Add(new Vector3((x + 1) / ft, (y) / ft, slice));
            break;

        default:
            break;
        }
    }
Esempio n. 4
0
    public static void AddSunlightRemovals(ref NativeArray3x3 <Light> lights, NativeList <TorchLightOp> lightOps, NativeQueue <LightRemovalNode> lrbfs)
    {
        for (int loi = 0; loi < lightOps.Length; ++loi)
        {
            TorchLightOp op = lightOps[loi];

            int opx        = op.index % S;
            int opy        = op.index / (S * S);
            int opz        = (op.index % (S * S)) / S;
            int startIndex = (opx + S) + (opz + S) * W + (opy + S) * W * W;

            Light curLight = lights.Get(opx, opy, opz);
            lrbfs.Enqueue(new LightRemovalNode {
                index = startIndex, light = curLight.sun
            });
            curLight.sun = 0;
            lights.Set(opx, opy, opz, curLight);
        }
    }
Esempio n. 5
0
    public static void BuildNaive(ref NativeMeshData meshData, ref NativeArray3x3 <Block> blocks, ref NativeArray3x3 <Light> lights, NativeArray <BlockData> blockData)
    {
        for (int y = 0; y < S; y++)
        {
            for (int z = 0; z < S; z++)
            {
                for (int x = 0; x < S; x++)
                {
                    //blocks.c[x + z * S + y * S * S].GetType().AddDataNative(x, y, z, ref data, ref blocks, ref lights, faces);

                    BlockData bd = blockData[blocks.c[x + z * S + y * S * S].type];

                    if (bd.renderType > 0)
                    {
                        AddBlockFaces(x, y, z, ref meshData, ref blocks, ref lights, blockData);
                    }
                }
            }
        }
    }
Esempio n. 6
0
    // called only once all neighbors are generated
    public static void BuildStructures(Vector3i chunkBlockPos, int seed, ref NativeArray3x3 <Block> blocks)
    {
        // not sure here lol
        Random urand = new Random((uint)(chunkBlockPos.GetHashCode() + seed));

        for (int y = 0; y < Chunk.SIZE; ++y)
        {
            for (int z = 0; z < Chunk.SIZE; ++z)
            {
                for (int x = 0; x < Chunk.SIZE; ++x)
                {
                    //if (blocks.Get(x, y, z) == Blocks.AIR && blocks.Get(x, y - 1, z) == Blocks.STONE) {
                    //    blocks.Set(x, y, z, Blocks.GRASS);
                    //    blocks.Set(x, y - 1, z, Blocks.GRASS);
                    //}

                    // random chance to try to spawn tree
                    if (urand.NextFloat() < 0.01f)
                    {
                        TrySpawnGoodTree(ref blocks, urand, x, y, z);
                    }

                    // try to spawn gems
                    if (blocks.Get(x, y, z) == Blocks.AIR)
                    {
                        float gemChance = Mth.Blend(0.02f, 0.0f, y + chunkBlockPos.y, -400, -100);

                        if (urand.NextFloat() < gemChance)
                        {
                            TrySpawnGemstone(ref blocks, urand, x, y, z);
                        }
                    }
                }
            }
        }
    }
Esempio n. 7
0
    static void TrySpawnGemstone(ref NativeArray3x3 <Block> blocks, Random urand, int x, int y, int z)
    {
        //int dir = urand.NextInt(0, 6);
        int3 pos = new int3(x, y, z);
        int3 dir;
        bool stalag = urand.NextFloat() < 0.5f; // ones on ground pointing up

        if (stalag)                             // changed to just be up and down for now see how that looks
        {
            dir = new int3(0, 1, 0);
        }
        else
        {
            dir = new int3(0, -1, 0);
        }

        if (blocks.Get(x - dir.x, y - dir.y, z - dir.z) == Blocks.AIR)
        {
            return;
        }

        int len = urand.NextInt(2, 8 + (int)(math.abs(y) * 0.01f));

        len /= stalag ? 1 : 2;         // stalags should be twice as tall as stalacts (ceiling ones)
        len  = math.clamp(len, 2, 20); // make sure dont get too crazy long

        int sides, xdir, zdir;

        if (len > 2)   // if taller than this have some secondary columns with random lengths
        {
            sides = urand.NextInt(0, 4);
            xdir  = urand.NextInt(2, len - 1);  // size of secondary columns
            zdir  = urand.NextInt(2, len - 1);
        }
        else
        {
            xdir = zdir = sides = 0;
        }
        int   gemType = urand.NextInt(0, 3);
        Block gemBlock;

        if (gemType == 0)
        {
            gemBlock = Blocks.RUBY;
        }
        else if (gemType == 1)
        {
            gemBlock = Blocks.EMERALD;
        }
        else
        {
            gemBlock = Blocks.SAPPHIRE;
        }

        for (int i = 0; i < len; ++i)
        {
            int3 p = pos + dir * i;
            if (blocks.Get(p.x, p.y, p.z) != Blocks.AIR)
            {
                return;
            }
            blocks.Set(p.x, p.y, p.z, gemBlock);

            if (xdir-- > 0)
            {
                if (sides / 2 == 0)   // west
                {
                    if (blocks.Get(p.x - 1, p.y, p.z) == Blocks.AIR)
                    {
                        blocks.Set(p.x - 1, p.y, p.z, gemBlock);
                    }
                }
                else     // east
                {
                    if (blocks.Get(p.x + 1, p.y, p.z) == Blocks.AIR)
                    {
                        blocks.Set(p.x + 1, p.y, p.z, gemBlock);
                    }
                }
            }
            if (zdir-- > 0)
            {
                if (sides % 2 == 0)   // south
                {
                    if (blocks.Get(p.x, p.y, p.z - 1) == Blocks.AIR)
                    {
                        blocks.Set(p.x, p.y, p.z - 1, gemBlock);
                    }
                }
                else     // north
                {
                    if (blocks.Get(p.x, p.y, p.z + 1) == Blocks.AIR)
                    {
                        blocks.Set(p.x, p.y, p.z + 1, gemBlock);
                    }
                }
            }
        }
    }
Esempio n. 8
0
    static void TrySpawnTree(ref NativeArray3x3 <Block> blocks, Random urand, int x, int y, int z)
    {
        int width = urand.NextInt(1, 4);

        int height = 0;

        if (width == 1)
        {
            height = urand.NextInt(3, 10);
            for (int i = 0; i <= height; ++i)
            {
                Block b = blocks.Get(x, y + i, z);
                if (i == 0)
                {
                    if (b != Blocks.GRASS)
                    {
                        return;
                    }
                }
                else
                {
                    if (b != Blocks.AIR)
                    {
                        return;
                    }
                }
            }
        }
        else if (width == 2)
        {
            height = urand.NextInt(8, 20);
            for (int i = 0; i <= height; ++i)
            {
                for (int u = 0; u <= 1; ++u)
                {
                    for (int v = 0; v <= 1; ++v)
                    {
                        Block b = blocks.Get(x + u, y + i, z + v);
                        if (i == 0)
                        {
                            if (b != Blocks.GRASS)
                            {
                                return;
                            }
                        }
                        else
                        {
                            if (b != Blocks.AIR)
                            {
                                return;
                            }
                        }
                    }
                }
            }
        }
        else if (width == 3)
        {
            height = urand.NextInt(16, 30);
            for (int i = 0; i <= height; ++i)
            {
                for (int u = -1; u <= 1; ++u)
                {
                    for (int v = -1; v <= 1; ++v)
                    {
                        Block b = blocks.Get(x + u, y + i, z + v);
                        if (i == 0)
                        {
                            if (b != Blocks.GRASS)
                            {
                                return;
                            }
                        }
                        else
                        {
                            if (b != Blocks.AIR)
                            {
                                return;
                            }
                        }
                    }
                }
            }
        }

        for (int i = 1; i <= height + 1; ++i)
        {
            float f  = (height - i);
            float hf = (float)i / height;
            hf  = 1.0f - hf;
            hf *= hf;
            int s = (int)(f * hf);
            if (s <= 0)
            {
                s = 1;
            }
            s += urand.NextInt(-1, 2);
            int us = -s;
            int vs = -s;
            if (width == 3)
            {
                us -= 1;
                vs -= 1;
            }

            for (int u = us; u <= s + width - 1; ++u)
            {
                for (int v = vs; v <= s + width - 1; ++v)
                {
                    // spawn trunk if near center
                    if (width == 1 && u == 0 && v == 0 ||
                        width == 2 && (u >= 0 && u <= 1) && (v >= 0 && v <= 1) ||
                        width == 3 && (u >= -1 && u <= 1) && (v >= -1 && v <= 1))
                    {
                        blocks.Set(x + u, y + i, z + v, Blocks.PINE);
                    }
                    else if (i >= width * 2 && i % 2 == 0 || i > height - 1)     // otherwise leaves
                    {
                        if (blocks.Get(x + u, y + i, z + v) == Blocks.AIR)
                        {
                            blocks.Set(x + u, y + i, z + v, Blocks.PINELEAF);
                        }
                    }
                }
            }
        }
    }
Esempio n. 9
0
    // this is a pine tree routine
    static void TrySpawnGoodTree(ref NativeArray3x3 <Block> blocks, Random urand, int x, int y, int z)
    {
        float width = urand.NextFloat(0.5f, 2f);

        int height = 0;

        height = (int)(28 * width / 2.0f) + urand.NextInt(-3, 3);
        math.clamp(height, 5, 29);

        // make sure space is kinda clear for tree height at least
        int wi = (int)width + 1;

        for (int u = -wi; u <= wi; ++u)
        {
            for (int v = -wi; v <= wi; ++v)
            {
                if (math.lengthsq(new float2(u, v)) < wi * wi)
                {
                    if (blocks.Get(x + u, y, z + v) != Blocks.GRASS)
                    {
                        return;
                    }
                }
            }
        }
        for (int i = 1; i <= height; ++i)
        {
            if (blocks.Get(x, y + i, z) != Blocks.AIR)
            {
                return;
            }
        }

        int nextLeafLevel = urand.NextInt(3, 5);

        for (int i = 1; i <= height; ++i)
        {
            float hp       = (float)i / height;
            float curWidth = math.lerp(width, width / 2.0f, hp);
            float leafEdge = 0.0f;

            //bool leafLayer = (i >= 3 && i % 2 == 0) || i >= height;
            bool leafLayer = i == nextLeafLevel || i == height;
            if (leafLayer)
            {
                leafEdge = math.lerp(width * 4.0f, 1.5f, Mth.QuadraticEaseOut(hp));
                float r = urand.NextFloat();
                if (r < 0.1f)
                {
                    nextLeafLevel += 1;
                }
                else if (r < 0.75f || height < 20)
                {
                    nextLeafLevel += 2;
                }
                else     // taller trees have small chance of large gaps in leaves
                {
                    nextLeafLevel += 3;
                }
                if (i == height)
                {
                    leafEdge = 1.0f;
                }
                else if (urand.NextFloat() < .2f)
                {
                    leafEdge++;
                }
            }
            int cwi = (int)(curWidth + leafEdge) + 1;

            for (int u = -cwi; u <= cwi; ++u)
            {
                for (int v = -cwi; v <= cwi; ++v)
                {
                    float len = math.lengthsq(new float2(u, v));
                    if (len < curWidth * curWidth)
                    {
                        blocks.Set(x + u, y + i, z + v, Blocks.PINE);
                    }
                    else if (leafLayer && len < (curWidth + leafEdge) * (curWidth + leafEdge))
                    {
                        if (blocks.Get(x + u, y + i, z + v) == Blocks.AIR)
                        {
                            blocks.Set(x + u, y + i, z + v, Blocks.PINELEAF);
                        }
                    }
                }
            }
        }

        // add leaves to the top
        int topper = height > 20 ? 2 : 1;

        for (int i = height + 1; i < height + 1 + topper; ++i)
        {
            if (blocks.Get(x, y + i, z) == Blocks.AIR)
            {
                blocks.Set(x, y + i, z, Blocks.PINELEAF);
            }
        }
    }
Esempio n. 10
0
    public static void ProcessSunlight(ref NativeArray3x3 <Light> lights, ref NativeArray3x3 <Block> blocks, NativeArray <BlockData> blockData,
                                       NativeQueue <int> lbfs, NativeQueue <int> lbfs_U, NativeQueue <LightRemovalNode> lrbfs, NativeQueue <LightRemovalNode> lrbfs_U)
    {
        // not sure if going to have sunlightops... the ordering might get boned up on quick place delete operations, but way more efficient this way
        //for (int oi = 0; oi < ops.Length;) {
        //    // check to see what type of operation first op is
        //    bool isProp = ops[oi].val != 0;
        //    // queue up each matching operation type until you hit end or mismatch
        //    while (oi < ops.Length) {
        //        SunLightOp op = ops[oi];
        //        if ((op.val != 0) != isProp) {
        //            break; // this ops type is different from first in run
        //        }
        //        int opx = op.index % S;
        //        int opy = op.index / (S * S);
        //        int opz = (op.index % (S * S)) / S;
        //        int startIndex = (opx + S) + (opz + S) * W + (opy + S) * W * W;

        //        Light curLight = lights.Get(opx, opy, opz);
        //        if (isProp) {
        //            // set the new light value here
        //            Light newLight = curLight;
        //            newLight.sun = op.val;
        //            lights.Set(opx, opy, opz, newLight);

        //            // if the new sun value is same or less than current dont need to progagate
        //            // this might not happen with sunlight but left check anyways
        //            if (op.val <= curLight.sun) {
        //                continue;
        //            }
        //        } else {
        //            lrbfs.Enqueue(new LightRemovalNode { index = startIndex, light = curLight.sun });
        //            curLight.sun = 0;
        //            lights.Set(opx, opy, opz, curLight);
        //        }

        //        oi++;
        //    }

        //if (!isProp) {
        while (lrbfs.Count > 0)
        {
            LightRemovalNode node = lrbfs.Dequeue();

            // extract coords from index
            int x = node.index % W - S;
            int y = node.index / (W * W) - S;
            int z = (node.index % (W * W)) / W - S;

            byte oneLess = (byte)(node.light - 1); // each time reduce light by one

            Light light = lights.Get(x - 1, y, z);
            if (light.sun != 0)   // WEST
            {
                int index = x - 1 + S + (z + S) * W + (y + S) * W * W;
                if (light.sun < node.light)
                {
                    light.sun = 0;
                    lights.Set(x - 1, y, z, light);
                    lrbfs.Enqueue(new LightRemovalNode {
                        index = index, light = oneLess
                    });
                }
                else     // add to propagate queue so can fill gaps left behind by removal
                {
                    lbfs.Enqueue(index);
                }
            }

            light = lights.Get(x, y - 1, z);
            if (light.sun != 0)   // DOWN
            {
                int index = x + S + (z + S) * W + (y - 1 + S) * W * W;
                if (light.sun < node.light || node.light == MAX_LIGHT)
                {
                    light.sun = 0;
                    lights.Set(x, y - 1, z, light);
                    byte lv = node.light == MAX_LIGHT ? MAX_LIGHT : oneLess;
                    lrbfs.Enqueue(new LightRemovalNode {
                        index = index, light = lv
                    });
                }
                else     // add to propagate queue so can fill gaps left behind by removal
                {
                    lbfs.Enqueue(index);
                }
            }

            light = lights.Get(x, y, z - 1);
            if (light.sun != 0)   // SOUTH
            {
                int index = x + S + (z - 1 + S) * W + (y + S) * W * W;
                if (light.sun < node.light)
                {
                    light.sun = 0;
                    lights.Set(x, y, z - 1, light);
                    lrbfs.Enqueue(new LightRemovalNode {
                        index = index, light = oneLess
                    });
                }
                else     // add to propagate queue so can fill gaps left behind by removal
                {
                    lbfs.Enqueue(index);
                }
            }

            light = lights.Get(x + 1, y, z);
            if (light.sun != 0)   // EAST
            {
                int index = x + 1 + S + (z + S) * W + (y + S) * W * W;
                if (light.sun < node.light)
                {
                    light.sun = 0;
                    lights.Set(x + 1, y, z, light);
                    lrbfs.Enqueue(new LightRemovalNode {
                        index = index, light = oneLess
                    });
                }
                else     // add to propagate queue so can fill gaps left behind by removal
                {
                    lbfs.Enqueue(index);
                }
            }

            light = lights.Get(x, y + 1, z);
            if (light.sun != 0)   // UP
            {
                int index = x + S + (z + S) * W + (y + 1 + S) * W * W;
                if (light.sun < node.light)
                {
                    light.sun = 0;
                    lights.Set(x, y + 1, z, light);
                    lrbfs.Enqueue(new LightRemovalNode {
                        index = index, light = oneLess
                    });
                }
                else     // add to propagate queue so can fill gaps left behind by removal
                {
                    lbfs.Enqueue(index);
                }
            }

            light = lights.Get(x, y, z + 1);
            if (light.sun != 0)   // NORTH
            {
                int index = x + S + (z + 1 + S) * W + (y + S) * W * W;
                if (light.sun < node.light)
                {
                    light.sun = 0;
                    lights.Set(x, y, z + 1, light);
                    lrbfs.Enqueue(new LightRemovalNode {
                        index = index, light = oneLess
                    });
                }
                else     // add to propagate queue so can fill gaps left behind by removal
                {
                    lbfs.Enqueue(index);
                }
            }
        }

        // propagate (either way)
        while (lbfs.Count > 0)
        {
            int index = lbfs.Dequeue();

            // extract coords from index
            int x = index % W - S;
            int y = index / (W * W) - S;
            int z = (index % (W * W)) / W - S;

            // get light level at this node
            int sunLight = lights.Get(x, y, z).sun;

            // check each neighbor blocks light reduction value
            // if neighbor light level is 2 or more levels less than this node, set them to this light-1 and add to queue
            // also add additional light reduction value
            byte LR = blockData[blocks.Get(x - 1, y, z).type].lightReduction;
            if (LR < sunLight)   // WEST
            {
                Light light = lights.Get(x - 1, y, z);
                if (light.sun + 2 + LR <= sunLight)
                {
                    light.sun = (byte)(sunLight - 1 - LR);
                    lights.Set(x - 1, y, z, light);
                    lbfs.Enqueue(x - 1 + S + (z + S) * W + (y + S) * W * W);
                }
            }
            LR = blockData[blocks.Get(x, y - 1, z).type].lightReduction;
            if (LR < sunLight)   // DOWN
            {
                Light light = lights.Get(x, y - 1, z);
                if (light.sun + 2 + LR <= sunLight)
                {
                    if (sunLight == MAX_LIGHT)   // if at maxlight dont reduce by 1 each time
                    {
                        light.sun = (byte)(sunLight - LR);
                    }
                    else
                    {
                        light.sun = (byte)(sunLight - 1 - LR);
                    }
                    lights.Set(x, y - 1, z, light);
                    if (y <= -31)
                    {
                        lbfs_U.Enqueue(x + S + (z + S) * W + (32 + S) * W * W); // add to unfinished queue and shift index to be proper for downdown chunk
                    }
                    else
                    {
                        lbfs.Enqueue(x + S + (z + S) * W + (y - 1 + S) * W * W);
                    }
                }
            }
            LR = blockData[blocks.Get(x, y, z - 1).type].lightReduction;
            if (LR < sunLight)   // SOUTH
            {
                Light light = lights.Get(x, y, z - 1);
                if (light.sun + 2 + LR <= sunLight)
                {
                    light.sun = (byte)(sunLight - 1 - LR);
                    lights.Set(x, y, z - 1, light);
                    lbfs.Enqueue(x + S + (z - 1 + S) * W + (y + S) * W * W);
                }
            }
            LR = blockData[blocks.Get(x + 1, y, z).type].lightReduction;
            if (LR < sunLight)   // EAST
            {
                Light light = lights.Get(x + 1, y, z);
                if (light.sun + 2 + LR <= sunLight)
                {
                    light.sun = (byte)(sunLight - 1 - LR);
                    lights.Set(x + 1, y, z, light);
                    lbfs.Enqueue(x + 1 + S + (z + S) * W + (y + S) * W * W);
                }
            }
            LR = blockData[blocks.Get(x, y + 1, z).type].lightReduction;
            if (LR < sunLight)   // UP
            {
                Light light = lights.Get(x, y + 1, z);
                if (light.sun + 2 + LR <= sunLight)
                {
                    light.sun = (byte)(sunLight - 1 - LR);
                    lights.Set(x, y + 1, z, light);
                    lbfs.Enqueue(x + S + (z + S) * W + (y + 1 + S) * W * W);
                }
            }
            LR = blockData[blocks.Get(x, y, z + 1).type].lightReduction;
            if (LR < sunLight)   // NORTH
            {
                Light light = lights.Get(x, y, z + 1);
                if (light.sun + 2 + LR <= sunLight)
                {
                    light.sun = (byte)(sunLight - 1 - LR);
                    lights.Set(x, y, z + 1, light);
                    lbfs.Enqueue(x + S + (z + 1 + S) * W + (y + S) * W * W);
                }
            }
        }
    }
Esempio n. 11
0
    public static void ProcessTorchLightOpsOptimal(ref NativeArray3x3 <Light> lights, ref NativeArray3x3 <Block> blocks, NativeArray <BlockData> blockData, NativeList <TorchLightOp> ops, NativeQueue <int> lbfs, NativeQueue <LightRemovalNode> lrbfs)
    {
        lights.flags = 0;

        // set blocks at torchlightops to have correct is light flag set
        for (int opIndex = 0; opIndex < ops.Length; ++opIndex)
        {
            TorchLightOp op      = ops[opIndex];
            int          opx     = op.index % S;
            int          opy     = op.index / (S * S);
            int          opz     = (op.index % (S * S)) / S;
            Light        opLight = lights.Get(opx, opy, opz);
            opLight.torch = SetIsLight(opLight.torch, op.val > 0);
            lights.Set(opx, opy, opz, opLight);
        }

        // loop over each color channel of torch light
        for (int cIndex = 0; cIndex < 3; cIndex++)
        {
            for (int oi = 0; oi < ops.Length;)
            {
                // check to see what type of operation first op is
                bool isProp = GetChannel(ops[oi].val, cIndex) != 0;
                // queue up each matching operation type until you hit end or mismatch
                while (oi < ops.Length)
                {
                    TorchLightOp op        = ops[oi];
                    int          opChannel = GetChannel(op.val, cIndex);
                    if ((opChannel != 0) != isProp)
                    {
                        break; // this ops type is different from first in run
                    }
                    int opx        = op.index % S;
                    int opy        = op.index / (S * S);
                    int opz        = (op.index % (S * S)) / S;
                    int startIndex = (opx + S) + (opz + S) * W + (opy + S) * W * W;

                    Light curLight   = lights.Get(opx, opy, opz);
                    int   curChannel = GetChannel(curLight.torch, cIndex);
                    if (isProp)
                    {
                        // set the new light value here
                        Light newLight = curLight;
                        newLight.torch = SetChannel(newLight.torch, cIndex, opChannel);
                        lights.Set(opx, opy, opz, newLight);

                        // if the new ops channel value is same as current light channel then add to propagate
                        if (opChannel > curChannel)
                        {
                            lbfs.Enqueue(startIndex);
                        }
                    }
                    else
                    {
                        lrbfs.Enqueue(new LightRemovalNode {
                            index = startIndex, light = (byte)curChannel
                        });
                        curLight.torch = SetChannel(curLight.torch, cIndex, 0);
                        lights.Set(opx, opy, opz, curLight);
                    }

                    oi++;
                }

                if (!isProp)
                {
                    while (lrbfs.Count > 0)
                    {
                        LightRemovalNode node = lrbfs.Dequeue();

                        // extract coords from index
                        int x = node.index % W - S;
                        int y = node.index / (W * W) - S;
                        int z = (node.index % (W * W)) / W - S;

                        byte oneLess = (byte)(node.light - 1); // each time reduce light by one

                        //ushort westLight = light.Get(x - 1, y, z).torch;
                        Light westLight   = lights.Get(x - 1, y, z);
                        byte  westChannel = (byte)GetChannel(westLight.torch, cIndex);
                        if (westChannel != 0)
                        {
                            int index = x - 1 + S + (z + S) * W + (y + S) * W * W;
                            if (westChannel < node.light)
                            {
                                if (!GetIsLight(westLight.torch))
                                {
                                    westLight.torch = SetChannel(westLight.torch, cIndex, 0);
                                    lights.Set(x - 1, y, z, westLight);
                                }
                                else     // if this node is a light, dont override value, but still add a removal node as if you did, then add to repropagate to fill it back in
                                {
                                    lbfs.Enqueue(index);
                                }
                                lrbfs.Enqueue(new LightRemovalNode {
                                    index = index, light = oneLess
                                });
                            }
                            else     // add to propagate queue so can fill gaps left behind by removal
                            {
                                lbfs.Enqueue(index);
                            }
                        }

                        Light downLight   = lights.Get(x, y - 1, z);
                        byte  downChannel = (byte)GetChannel(downLight.torch, cIndex);
                        if (downChannel != 0)
                        {
                            int index = x + S + (z + S) * W + (y - 1 + S) * W * W;
                            if (downChannel < node.light)
                            {
                                if (!GetIsLight(downLight.torch))
                                {
                                    downLight.torch = SetChannel(downLight.torch, cIndex, 0);
                                    lights.Set(x, y - 1, z, downLight);
                                }
                                else
                                {
                                    lbfs.Enqueue(index);
                                }
                                lrbfs.Enqueue(new LightRemovalNode {
                                    index = index, light = oneLess
                                });
                            }
                            else     // add to propagate queue so can fill gaps left behind by removal
                            {
                                lbfs.Enqueue(index);
                            }
                        }

                        Light southLight   = lights.Get(x, y, z - 1);
                        byte  southChannel = (byte)GetChannel(southLight.torch, cIndex);
                        if (southChannel != 0)
                        {
                            int index = x + S + (z - 1 + S) * W + (y + S) * W * W;
                            if (southChannel < node.light)
                            {
                                if (!GetIsLight(southLight.torch))
                                {
                                    southLight.torch = SetChannel(southLight.torch, cIndex, 0);
                                    lights.Set(x, y, z - 1, southLight);
                                }
                                else
                                {
                                    lbfs.Enqueue(index);
                                }
                                lrbfs.Enqueue(new LightRemovalNode {
                                    index = index, light = oneLess
                                });
                            }
                            else     // add to propagate queue so can fill gaps left behind by removal
                            {
                                lbfs.Enqueue(index);
                            }
                        }

                        Light eastLight   = lights.Get(x + 1, y, z);
                        byte  eastChannel = (byte)GetChannel(eastLight.torch, cIndex);
                        if (eastChannel != 0)
                        {
                            int index = x + 1 + S + (z + S) * W + (y + S) * W * W;
                            if (eastChannel < node.light)
                            {
                                if (!GetIsLight(eastLight.torch))
                                {
                                    eastLight.torch = SetChannel(eastLight.torch, cIndex, 0);
                                    lights.Set(x + 1, y, z, eastLight);
                                }
                                else
                                {
                                    lbfs.Enqueue(index);
                                }
                                lrbfs.Enqueue(new LightRemovalNode {
                                    index = index, light = oneLess
                                });
                            }
                            else     // add to propagate queue so can fill gaps left behind by removal
                            {
                                lbfs.Enqueue(index);
                            }
                        }

                        Light upLight   = lights.Get(x, y + 1, z);
                        byte  upChannel = (byte)GetChannel(upLight.torch, cIndex);
                        if (upChannel != 0)
                        {
                            int index = x + S + (z + S) * W + (y + 1 + S) * W * W;
                            if (upChannel < node.light)
                            {
                                if (!GetIsLight(upLight.torch))
                                {
                                    upLight.torch = SetChannel(upLight.torch, cIndex, 0);
                                    lights.Set(x, y + 1, z, upLight);
                                }
                                else
                                {
                                    lbfs.Enqueue(index);
                                }
                                lrbfs.Enqueue(new LightRemovalNode {
                                    index = index, light = oneLess
                                });
                            }
                            else     // add to propagate queue so can fill gaps left behind by removal
                            {
                                lbfs.Enqueue(index);
                            }
                        }

                        Light northLight   = lights.Get(x, y, z + 1);
                        byte  northChannel = (byte)GetChannel(northLight.torch, cIndex);
                        if (northChannel != 0)
                        {
                            int index = x + S + (z + 1 + S) * W + (y + S) * W * W;
                            if (northChannel < node.light)
                            {
                                if (!GetIsLight(northLight.torch))
                                {
                                    northLight.torch = SetChannel(northLight.torch, cIndex, 0);
                                    lights.Set(x, y, z + 1, northLight);
                                }
                                else
                                {
                                    lbfs.Enqueue(index);
                                }
                                lrbfs.Enqueue(new LightRemovalNode {
                                    index = index, light = oneLess
                                });
                            }
                            else     // add to propagate queue so can fill gaps left behind by removal
                            {
                                lbfs.Enqueue(index);
                            }
                        }
                    }
                }

                // propagate either way
                while (lbfs.Count > 0)
                {
                    int index = lbfs.Dequeue();

                    // extract coords from index
                    int x = index % W - S;
                    int y = index / (W * W) - S;
                    int z = (index % (W * W)) / W - S;

                    // get light level at this node
                    int mChan = GetChannel(lights.Get(x, y, z).torch, cIndex);

                    //if(mChan == 0) { // can happen frequently when batching together light removals
                    //    continue;
                    //}

                    // check each neighbor blocks light reduction value
                    // if neighbor light level is 2 or more levels less than this node, set them to this light-1 and add to queue
                    // also add additional light reduction value
                    byte LR = blockData[blocks.Get(x - 1, y, z).type].lightReduction;
                    if (LR < mChan)   // WEST
                    {
                        Light light = lights.Get(x - 1, y, z);
                        if (GetChannel(light.torch, cIndex) + 2 + LR <= mChan)
                        {
                            light.torch = SetChannel(light.torch, cIndex, mChan - 1 - LR);
                            lights.Set(x - 1, y, z, light);
                            lbfs.Enqueue(x - 1 + S + (z + S) * W + (y + S) * W * W);
                        }
                    }
                    LR = blockData[blocks.Get(x, y - 1, z).type].lightReduction;
                    if (LR < mChan)   // DOWN
                    {
                        Light light = lights.Get(x, y - 1, z);
                        if (GetChannel(light.torch, cIndex) + 2 + LR <= mChan)
                        {
                            light.torch = SetChannel(light.torch, cIndex, mChan - 1 - LR);
                            lights.Set(x, y - 1, z, light);
                            lbfs.Enqueue(x + S + (z + S) * W + (y - 1 + S) * W * W);
                        }
                    }
                    LR = blockData[blocks.Get(x, y, z - 1).type].lightReduction;
                    if (LR < mChan)   // SOUTH
                    {
                        Light light = lights.Get(x, y, z - 1);
                        if (GetChannel(light.torch, cIndex) + 2 + LR <= mChan)
                        {
                            light.torch = SetChannel(light.torch, cIndex, mChan - 1 - LR);
                            lights.Set(x, y, z - 1, light);
                            lbfs.Enqueue(x + S + (z - 1 + S) * W + (y + S) * W * W);
                        }
                    }
                    LR = blockData[blocks.Get(x + 1, y, z).type].lightReduction;
                    if (LR < mChan)   // EAST
                    {
                        Light light = lights.Get(x + 1, y, z);
                        if (GetChannel(light.torch, cIndex) + 2 + LR <= mChan)
                        {
                            light.torch = SetChannel(light.torch, cIndex, mChan - 1 - LR);
                            lights.Set(x + 1, y, z, light);
                            lbfs.Enqueue(x + 1 + S + (z + S) * W + (y + S) * W * W);
                        }
                    }
                    LR = blockData[blocks.Get(x, y + 1, z).type].lightReduction;
                    if (LR < mChan)   // UP
                    {
                        Light light = lights.Get(x, y + 1, z);
                        if (GetChannel(light.torch, cIndex) + 2 + LR <= mChan)
                        {
                            light.torch = SetChannel(light.torch, cIndex, mChan - 1 - LR);
                            lights.Set(x, y + 1, z, light);
                            lbfs.Enqueue(x + S + (z + S) * W + (y + 1 + S) * W * W);
                        }
                    }
                    LR = blockData[blocks.Get(x, y, z + 1).type].lightReduction;
                    if (LR < mChan)   // NORTH
                    {
                        Light light = lights.Get(x, y, z + 1);
                        if (GetChannel(light.torch, cIndex) + 2 + LR <= mChan)
                        {
                            light.torch = SetChannel(light.torch, cIndex, mChan - 1 - LR);
                            lights.Set(x, y, z + 1, light);
                            lbfs.Enqueue(x + S + (z + 1 + S) * W + (y + S) * W * W);
                        }
                    }
                }
            }
        }
    }
Esempio n. 12
0
    //public const int VOXEL_SIZE = 1;
    //https://github.com/roboleary/GreedyMesh/blob/master/src/mygame/Main.java
    //https://github.com/darkedge/starlight/blob/master/starlight/starlight_game.cpp

    public static void BuildGreedyCollider(ref NativeArray3x3 <Block> blocks, NativeList <Vector3> vertices, NativeList <int> triangles, NativeArray <BlockData> blockData)
    {
        void AddQuadTrianglesGreedy(bool clockwise)
        {
            if (!clockwise)
            {
                triangles.Add(vertices.Length - 2);  // 2
                triangles.Add(vertices.Length - 4);  // 0
                triangles.Add(vertices.Length - 3);  // 1

                triangles.Add(vertices.Length - 3);  // 1
                triangles.Add(vertices.Length - 1);  // 3
                triangles.Add(vertices.Length - 2);  // 2
            }
            else
            {
                triangles.Add(vertices.Length - 2);  // 2
                triangles.Add(vertices.Length - 1);  // 3
                triangles.Add(vertices.Length - 3);  // 1

                triangles.Add(vertices.Length - 3);  // 1
                triangles.Add(vertices.Length - 4);  // 0
                triangles.Add(vertices.Length - 2);  // 2
            }
        }

        // setup variables for algo
        int i, j, k, l, w, h, d1, d2, n = 0;
        Dir side = Dir.south;

        int[] x  = new int[] { 0, 0, 0 };
        int[] q  = new int[] { 0, 0, 0 };
        int[] du = new int[] { 0, 0, 0 };
        int[] dv = new int[] { 0, 0, 0 };

        // slice will contain groups of matching blocks as we proceed through chunk in 6 directions, onces for each face
        Block[] slice = new Block[Chunk.CHUNK_WIDTH * Chunk.CHUNK_HEIGHT];

        int[] maxDim = new int[] { Chunk.CHUNK_WIDTH, Chunk.CHUNK_HEIGHT, Chunk.CHUNK_WIDTH };

        // sweep over six dimensions
        for (int dim = 0; dim < 6; ++dim)
        {
            int d0 = dim % 3;
            d1 = (dim + 1) % 3; // u
            d2 = (dim + 2) % 3; // v
            // when going thru z dimension, make x d1 and y d2 so makes more sense for uvs
            if (d0 == 2)
            {
                d1 = 1;
                d2 = 0;
            }

            int  bf       = dim / 3 * 2 - 1; // -1 -1 -1 +1 +1 +1
            bool backFace = bf < 0;

            x[0] = 0;
            x[1] = 0;
            x[2] = 0;

            // set the direction vector from dimension
            q[0]  = 0;
            q[1]  = 0;
            q[2]  = 0;
            q[d0] = 1;

            side = (Dir)dim;

            // move through dimension from front to back
            for (x[d0] = -1; x[d0] < maxDim[d0];)
            {
                // compute mask (which is a slice)
                n = 0;
                for (x[d2] = 0; x[d2] < maxDim[d2]; x[d2]++)
                {
                    for (x[d1] = 0; x[d1] < maxDim[d1]; x[d1]++)
                    {
                        // the second part of the ors are to make sure you dont add collision data for other chunk block faces on your borders
                        Block block1 = (backFace || x[d0] >= 0) ? blocks.Get(x[0], x[1], x[2]) : Blocks.AIR; // block were at
                        Block block2 = (!backFace || x[d0] < S - 1) ? blocks.Get(x[0] + q[0], x[1] + q[1], x[2] + q[2]) : Blocks.AIR;
                        slice[n++] = BlockData.ColliderSolid(blockData, block1) && BlockData.ColliderSolid(blockData, block2) ? Blocks.AIR : backFace ? block2 : block1;

                        // saving this for when porting back to meshing
                        //slice[n++] = block1.IsSolid(side) && block2.IsSolid(Dirs.Opp(side)) ?
                        //    Blocks.AIR : backFace ? block2 : block1;
                    }
                }

                // i think the current dimension we are slicing thru is incremented here so the blocks
                // will have the correct placement coordinate
                x[d0]++;

                // generate mesh for the mask
                n = 0;
                for (j = 0; j < maxDim[d2]; ++j)
                {
                    for (i = 0; i < maxDim[d1];)
                    {
                        if (!BlockData.ColliderSolid(blockData, slice[n]))
                        {
                            ++i;
                            ++n;
                            continue;
                        }

                        // normal equality check can split on type and more like AO and stuff later if want to change this back
                        // just need to change this below line and the line like 8 lines down

                        // compute width
                        for (w = 1; i + w < maxDim[d1] && BlockData.ColliderSolid(blockData, slice[n + w]) == BlockData.ColliderSolid(blockData, slice[n]); ++w)
                        {
                        }

                        // compute height
                        bool done = false;
                        for (h = 1; j + h < maxDim[d2]; ++h)
                        {
                            for (k = 0; k < w; ++k)
                            {
                                if (BlockData.ColliderSolid(blockData, slice[n + k + h * maxDim[d1]]) != BlockData.ColliderSolid(blockData, slice[n]))
                                {
                                    done = true;
                                    break;
                                }
                            }
                            if (done)
                            {
                                break;
                            }
                        }

                        x[d1] = i;
                        x[d2] = j;

                        du[0]  = 0;
                        du[1]  = 0;
                        du[2]  = 0;
                        du[d1] = w;

                        dv[0]  = 0;
                        dv[1]  = 0;
                        dv[2]  = 0;
                        dv[d2] = h;

                        int     s        = (int)side;
                        Vector3 botLeft  = new Vector3(x[0], x[1], x[2]) + MeshUtils.padOffset[s][0];
                        Vector3 botRight = new Vector3(x[0] + dv[0], x[1] + dv[1], x[2] + dv[2]) + MeshUtils.padOffset[s][1];
                        Vector3 topLeft  = new Vector3(x[0] + du[0], x[1] + du[1], x[2] + du[2]) + MeshUtils.padOffset[s][2];
                        Vector3 topRight = new Vector3(x[0] + du[0] + dv[0], x[1] + du[1] + dv[1], x[2] + du[2] + dv[2]) + MeshUtils.padOffset[s][3];

                        botLeft  /= Chunk.BPU;
                        topLeft  /= Chunk.BPU;
                        topRight /= Chunk.BPU;
                        botRight /= Chunk.BPU;

                        vertices.Add(botLeft);
                        vertices.Add(botRight);
                        vertices.Add(topLeft);
                        vertices.Add(topRight);

                        AddQuadTrianglesGreedy(d0 == 2 ? backFace : !backFace);

                        // zero out the quad in the mask
                        for (l = 0; l < h; ++l)
                        {
                            for (k = 0; k < w; ++k)
                            {
                                slice[n + k + l * maxDim[d1]] = Blocks.AIR;
                            }
                        }

                        // increment counters and continue
                        i += w;
                        n += w;
                    }
                }
            }
        }
    }
Esempio n. 13
0
 static int GetOpacity(ref NativeArray3x3 <Block> blocks, NativeArray <BlockData> blockData, int x, int y, int z)
 {
     return(BlockData.RenderSolid(blockData, blocks.Get(x, y, z), Dir.none) ? 1 : 0); // dir.none for now since all blocks are either transparent or not
 }
Esempio n. 14
0
    static void AddUVs(int x, int y, int z, ref NativeMeshData data, ref NativeArray3x3 <Block> blocks, NativeArray <BlockData> blockData, Dir dir, bool isLight)
    {
        // calculate uv1s, xy is uv coordinates, z is texture type
        BlockData bd = blockData[blocks.Get(x, y, z).type];

        if (bd.renderType == 1)   // normal texture
        {
            if (bd.texture < 0)   // dynamic, depends on nearby blocks
            {
                data.AddFaceUVs(GetTextureIndex(dir, x, y, z, ref blocks));
            }
            else
            {
                data.AddFaceUVs(bd.texture);
            }
        }
        else if (bd.renderType == 2) // using tiling textures
        {
            if (bd.texture < 0)      // dynamic, depends on nearby blocks
            {
                int texture = GetTileTextureIndex(dir, x, y, z, ref blocks);
                data.AddTileUvs(texture, dir, x, y, z, ref blocks, blockData);
            }
            else
            {
                data.AddTileUvs(bd.texture, dir, x, y, z, ref blocks, blockData);
            }
        }

        // now add uv2s, x is tiletype and y is ambient occlusion (z is unused for now)
        Vector3 uv2_0, uv2_1, uv2_2, uv2_3;

        uv2_0   = uv2_1 = uv2_2 = uv2_3 = default;
        uv2_0.x = uv2_1.x = uv2_2.x = uv2_3.x = bd.renderType == 1 ? 0.5f : 1.5f;
        if (isLight)
        {
            uv2_0.y = uv2_1.y = uv2_2.y = uv2_3.y = 1.0f; // dont add ao on the faces of lights, looks weird
        }
        else
        {
            switch (dir)
            {
            case Dir.west: {
                int up    = GetOpacity(ref blocks, blockData, x - 1, y + 1, z);
                int down  = GetOpacity(ref blocks, blockData, x - 1, y - 1, z);
                int north = GetOpacity(ref blocks, blockData, x - 1, y, z + 1);
                int south = GetOpacity(ref blocks, blockData, x - 1, y, z - 1);
                uv2_0.y = CalcAO(down, north, ref blocks, blockData, x - 1, y - 1, z + 1);
                uv2_1.y = CalcAO(up, north, ref blocks, blockData, x - 1, y + 1, z + 1);
                uv2_2.y = CalcAO(up, south, ref blocks, blockData, x - 1, y + 1, z - 1);
                uv2_3.y = CalcAO(down, south, ref blocks, blockData, x - 1, y - 1, z - 1);
            }
            break;

            case Dir.down: {
                int north = GetOpacity(ref blocks, blockData, x, y - 1, z + 1);
                int south = GetOpacity(ref blocks, blockData, x, y - 1, z - 1);
                int east  = GetOpacity(ref blocks, blockData, x + 1, y - 1, z);
                int west  = GetOpacity(ref blocks, blockData, x - 1, y - 1, z);
                uv2_0.y = CalcAO(south, west, ref blocks, blockData, x - 1, y - 1, z - 1);
                uv2_1.y = CalcAO(south, east, ref blocks, blockData, x + 1, y - 1, z - 1);
                uv2_2.y = CalcAO(north, east, ref blocks, blockData, x + 1, y - 1, z + 1);
                uv2_3.y = CalcAO(north, west, ref blocks, blockData, x - 1, y - 1, z + 1);
            }
            break;

            case Dir.south: {
                int up   = GetOpacity(ref blocks, blockData, x, y + 1, z - 1);
                int down = GetOpacity(ref blocks, blockData, x, y - 1, z - 1);
                int east = GetOpacity(ref blocks, blockData, x + 1, y, z - 1);
                int west = GetOpacity(ref blocks, blockData, x - 1, y, z - 1);
                uv2_0.y = CalcAO(down, west, ref blocks, blockData, x - 1, y - 1, z - 1);
                uv2_1.y = CalcAO(up, west, ref blocks, blockData, x - 1, y + 1, z - 1);
                uv2_2.y = CalcAO(up, east, ref blocks, blockData, x + 1, y + 1, z - 1);
                uv2_3.y = CalcAO(down, east, ref blocks, blockData, x + 1, y - 1, z - 1);
            }
            break;

            case Dir.east: {
                int up    = GetOpacity(ref blocks, blockData, x + 1, y + 1, z);
                int down  = GetOpacity(ref blocks, blockData, x + 1, y - 1, z);
                int north = GetOpacity(ref blocks, blockData, x + 1, y, z + 1);
                int south = GetOpacity(ref blocks, blockData, x + 1, y, z - 1);
                uv2_0.y = CalcAO(down, south, ref blocks, blockData, x + 1, y - 1, z - 1);
                uv2_1.y = CalcAO(up, south, ref blocks, blockData, x + 1, y + 1, z - 1);
                uv2_2.y = CalcAO(up, north, ref blocks, blockData, x + 1, y + 1, z + 1);
                uv2_3.y = CalcAO(down, north, ref blocks, blockData, x + 1, y - 1, z + 1);
            }
            break;

            case Dir.up: {
                int north = GetOpacity(ref blocks, blockData, x, y + 1, z + 1);
                int south = GetOpacity(ref blocks, blockData, x, y + 1, z - 1);
                int east  = GetOpacity(ref blocks, blockData, x + 1, y + 1, z);
                int west  = GetOpacity(ref blocks, blockData, x - 1, y + 1, z);
                uv2_0.y = CalcAO(north, west, ref blocks, blockData, x - 1, y + 1, z + 1);
                uv2_1.y = CalcAO(north, east, ref blocks, blockData, x + 1, y + 1, z + 1);
                uv2_2.y = CalcAO(south, east, ref blocks, blockData, x + 1, y + 1, z - 1);
                uv2_3.y = CalcAO(south, west, ref blocks, blockData, x - 1, y + 1, z - 1);
            }
            break;

            case Dir.north: {
                int up   = GetOpacity(ref blocks, blockData, x, y + 1, z + 1);
                int down = GetOpacity(ref blocks, blockData, x, y - 1, z + 1);
                int east = GetOpacity(ref blocks, blockData, x + 1, y, z + 1);
                int west = GetOpacity(ref blocks, blockData, x - 1, y, z + 1);
                uv2_0.y = CalcAO(down, east, ref blocks, blockData, x + 1, y - 1, z + 1);
                uv2_1.y = CalcAO(up, east, ref blocks, blockData, x + 1, y + 1, z + 1);
                uv2_2.y = CalcAO(up, west, ref blocks, blockData, x - 1, y + 1, z + 1);
                uv2_3.y = CalcAO(down, west, ref blocks, blockData, x - 1, y - 1, z + 1);
            }
            break;

            default:
                break;
            }
        }

        data.uv2s.Add(uv2_0);
        data.uv2s.Add(uv2_1);
        data.uv2s.Add(uv2_2);
        data.uv2s.Add(uv2_3);

        // do anisotropy flip
        if (uv2_0.y + uv2_2.y > uv2_1.y + uv2_3.y)
        {
            data.AddQuadTriangles();
        }
        else
        {
            data.AddFlippedQuadTriangles();
        }
    }
Esempio n. 15
0
    static void AddBlockFaces(int x, int y, int z, ref NativeMeshData data, ref NativeArray3x3 <Block> blocks, ref NativeArray3x3 <Light> lights, NativeArray <BlockData> blockData)
    {
        bool isLight = LightCalculator.GetIsLight(lights.Get(x, y, z).torch);

        if (!BlockData.RenderSolid(blockData, blocks.Get(x - 1, y, z), Dir.east))
        {
            AddWestFace(x, y, z, ref data);
            AddUVs(x, y, z, ref data, ref blocks, blockData, Dir.west, isLight);
            data.AddFaceColor(LightCalculator.GetColorFromLight(lights.Get(x - 1, y, z)));
            data.AddFaceNormal(Dirs.norm3f[Dirs.WEST]);
            data.faces.Add(new Face {
                pos = (ushort)(x + z * Chunk.SIZE + y * Chunk.SIZE * Chunk.SIZE), dir = Dir.west
            });
        }
        if (!BlockData.RenderSolid(blockData, blocks.Get(x, y - 1, z), Dir.up))
        {
            AddDownFace(x, y, z, ref data);
            AddUVs(x, y, z, ref data, ref blocks, blockData, Dir.down, isLight);
            data.AddFaceColor(LightCalculator.GetColorFromLight(lights.Get(x, y - 1, z)));
            data.AddFaceNormal(Dirs.norm3f[Dirs.DOWN]);
            data.faces.Add(new Face {
                pos = (ushort)(x + z * Chunk.SIZE + y * Chunk.SIZE * Chunk.SIZE), dir = Dir.down
            });
        }
        if (!BlockData.RenderSolid(blockData, blocks.Get(x, y, z - 1), Dir.north))
        {
            AddSouthFace(x, y, z, ref data);
            AddUVs(x, y, z, ref data, ref blocks, blockData, Dir.south, isLight);
            data.AddFaceColor(LightCalculator.GetColorFromLight(lights.Get(x, y, z - 1)));
            data.AddFaceNormal(Dirs.norm3f[Dirs.SOUTH]);
            data.faces.Add(new Face {
                pos = (ushort)(x + z * Chunk.SIZE + y * Chunk.SIZE * Chunk.SIZE), dir = Dir.south
            });
        }
        if (!BlockData.RenderSolid(blockData, blocks.Get(x + 1, y, z), Dir.west))
        {
            AddEastFace(x, y, z, ref data);
            AddUVs(x, y, z, ref data, ref blocks, blockData, Dir.east, isLight);
            data.AddFaceColor(LightCalculator.GetColorFromLight(lights.Get(x + 1, y, z)));
            data.AddFaceNormal(Dirs.norm3f[Dirs.EAST]);
            data.faces.Add(new Face {
                pos = (ushort)(x + z * Chunk.SIZE + y * Chunk.SIZE * Chunk.SIZE), dir = Dir.east
            });
        }
        if (!BlockData.RenderSolid(blockData, blocks.Get(x, y + 1, z), Dir.down))
        {
            AddUpFace(x, y, z, ref data);
            AddUVs(x, y, z, ref data, ref blocks, blockData, Dir.up, isLight);
            data.AddFaceColor(LightCalculator.GetColorFromLight(lights.Get(x, y + 1, z)));
            data.AddFaceNormal(Dirs.norm3f[Dirs.UP]);
            data.faces.Add(new Face {
                pos = (ushort)(x + z * Chunk.SIZE + y * Chunk.SIZE * Chunk.SIZE), dir = Dir.up
            });
        }
        if (!BlockData.RenderSolid(blockData, blocks.Get(x, y, z + 1), Dir.south))
        {
            AddNorthFace(x, y, z, ref data);
            AddUVs(x, y, z, ref data, ref blocks, blockData, Dir.north, isLight);
            data.AddFaceColor(LightCalculator.GetColorFromLight(lights.Get(x, y, z + 1)));
            data.AddFaceNormal(Dirs.norm3f[Dirs.NORTH]);
            data.faces.Add(new Face {
                pos = (ushort)(x + z * Chunk.SIZE + y * Chunk.SIZE * Chunk.SIZE), dir = Dir.north
            });
        }
    }
Esempio n. 16
0
    static int GetTextureIndex(Dir dir, int x, int y, int z, ref NativeArray3x3 <Block> blocks)
    {
        Block b = blocks.Get(x, y, z);

        if (b == Blocks.GRASS)
        {
            switch (dir)
            {
            case Dir.up:
                return(2);

            case Dir.down:
                return(1);
            }

            if (blocks.Get(x, y + 1, z) != Blocks.AIR)
            {
                return(1);
            }

            switch (dir)
            {
            case Dir.west:
                if (blocks.Get(x - 1, y - 1, z) == Blocks.GRASS)
                {
                    return(2);
                }
                break;

            case Dir.east:
                if (blocks.Get(x + 1, y - 1, z) == Blocks.GRASS)
                {
                    return(2);
                }
                break;

            case Dir.south:
                if (blocks.Get(x, y - 1, z - 1) == Blocks.GRASS)
                {
                    return(2);
                }
                break;

            case Dir.north:
                if (blocks.Get(x, y - 1, z + 1) == Blocks.GRASS)
                {
                    return(2);
                }
                break;
            }

            return(3);
        }
        else if (b == Blocks.PINE)
        {
            switch (dir)
            {
            case Dir.up:
            case Dir.down:
                return(5);

            default:
                return(4);
            }
        }

        return(-1); // shouldnt ever reach this point
    }