Пример #1
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);
        }
    }
Пример #2
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);
                        }
                    }
                }
            }
        }
    }