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); } } } }
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); } } } } } }