public void Edit <T>(IAssetData asset)
        {
            Log.T($"Editing {asset.AssetName}.",
                  _isDebugging);

            // Expand the base tilesheet if needed.
            var src      = ModEntry.Instance.Helper.Content.Load <Texture2D>(ModValues.MachinePath);
            var dest     = asset.AsImage();
            var srcRect  = new Rectangle(0, 0, 16, 32);
            var destRect = Propagator.getSourceRectForBigCraftable(ModValues.PropagatorIndex);

            if (destRect.Bottom > dest.Data.Height)
            {
                Log.D("Expanding bigCraftables tilesheet.",
                      _isDebugging);

                var original = dest.Data;
                var texture  = new Texture2D(Game1.graphics.GraphicsDevice, original.Width, destRect.Bottom);

                Log.D($"Original: {original.Width}x{original.Height}"
                      + $"\nExpanded: {texture.Width}x{texture.Height}",
                      _isDebugging);

                dest.ReplaceWith(texture);
                dest.PatchImage(original);
            }

            // Append machine sprite onto the default tilesheet.
            dest.PatchImage(src, srcRect, destRect);
        }
Exemple #2
0
        private void CreateCrack(double elementSize, XModel model, BidirectionalMesh2D <XNode, XContinuumElement2D> mesh,
                                 double jIntegralRadiusRatio)
        {
            var propagator = new Propagator(mesh, jIntegralRadiusRatio, new HomogeneousMaterialAuxiliaryStates(material),
                                            new HomogeneousSIFCalculator(material), new MaximumCircumferentialTensileStressCriterion(),
                                            new ConstantIncrement2D(1.5 * jIntegralRadiusRatio * elementSize));
            var crack = new TrackingExteriorCrackLSM(propagator);

            crack.Mesh = mesh;

            // Create enrichments
            crack.CrackBodyEnrichment = new CrackBodyEnrichment2D(crack, new SignFunctionOpposite2D());
            crack.CrackTipEnrichments = new CrackTipEnrichments2D(crack, CrackTipPosition.Single);
            //crackTip = new CrackTip2D(CrackTip2D.TipCurvePosition.CurveStart, polyline, new SingleElementEnrichment(),
            //    2.0, new HomogeneousMaterialAuxiliaryStates(globalHomogeneousMaterial),
            //    new HomogeneousSIFCalculator(globalHomogeneousMaterial));

            // Mesh geometry interaction
            var crackMouth = new CartesianPoint(beamLength, 0.5 * beamHeight);
            var crackTip   = new CartesianPoint(0.5 * beamLength, 0.5 * beamHeight);

            crack.InitializeGeometry(crackMouth, crackTip);
            crack.UpdateEnrichments(); //TODO: elements are not enriched properly.

            this.Crack      = crack;
            this.Propagator = propagator;
        }
            /// <summary>
            /// Constructs a join propagator.
            /// </summary>
            /// <param name="left">Result of propagating changes in the left input to the join</param>
            /// <param name="right">Result of propagating changes in the right input to the join</param>
            /// <param name="node">Join operator in update mapping view over which to propagate changes</param>
            /// <param name="parent">Handler of propagation for the entire update mapping view</param>
            internal JoinPropagator(ChangeNode left, ChangeNode right, DbJoinExpression node, Propagator parent)
            {
                EntityUtil.CheckArgumentNull(left, "left");
                EntityUtil.CheckArgumentNull(right, "right");
                EntityUtil.CheckArgumentNull(node, "node");
                EntityUtil.CheckArgumentNull(parent, "parent");

                m_left = left;
                m_right = right;
                m_joinExpression = node;
                m_parent = parent;

                Debug.Assert(DbExpressionKind.LeftOuterJoin == node.ExpressionKind || DbExpressionKind.InnerJoin == node.ExpressionKind, "(Update/JoinPropagagtor/JoinEvaluator) " +
                    "caller must ensure only left outer and inner joins are requested");
                // Retrieve propagation rules for the join type of the expression.
                if (DbExpressionKind.InnerJoin == m_joinExpression.ExpressionKind)
                {
                    m_insertRules = s_innerJoinInsertRules;
                    m_deleteRules = s_innerJoinDeleteRules;
                }
                else
                {
                    m_insertRules = s_leftOuterJoinInsertRules;
                    m_deleteRules = s_leftOuterJoinDeleteRules;
                }

                // Figure out key selectors involved in the equi-join (if it isn't an equi-join, we don't support it)
                JoinConditionVisitor.GetKeySelectors(node.JoinCondition, out m_leftKeySelectors, out m_rightKeySelectors);

                // Find the key selector expressions in the left and right placeholders
                m_leftPlaceholderKey = ExtractKey(m_left.Placeholder, m_leftKeySelectors, m_parent);
                m_rightPlaceholderKey = ExtractKey(m_right.Placeholder, m_rightKeySelectors, m_parent);
            }
Exemple #4
0
        private void InitializeCrack()
        {
            var         globalHomogeneousMaterial = HomogeneousElasticMaterial2D.CreateMaterialForPlaneStrain(E, v);
            IPropagator propagator = new Propagator(mesh, jIntegralRadiusOverElementSize,
                                                    new HomogeneousMaterialAuxiliaryStates(globalHomogeneousMaterial),
                                                    new HomogeneousSIFCalculator(globalHomogeneousMaterial),
                                                    new MaximumCircumferentialTensileStressCriterion(), new ConstantIncrement2D(growthLength));

            CrackMouth = new CartesianPoint(0.0, h / 2);
            var crackKink    = new CartesianPoint(a, h / 2);
            var initialCrack = new PolyLine2D(CrackMouth, crackKink);

            initialCrack.UpdateGeometry(-dTheta, da);
            //var crackTip = new CartesianPoint(a + da * Math.Cos(dTheta), h/2 - da * Math.Sin(dTheta));

            var lsmCrack = new TrackingExteriorCrackLSM(propagator, tipEnrichmentRadius, new RelativeAreaResolver(heavisideTol));

            lsmCrack.Mesh = mesh;

            // Create enrichments
            lsmCrack.CrackBodyEnrichment = new CrackBodyEnrichment2D(lsmCrack);
            lsmCrack.CrackTipEnrichments = new CrackTipEnrichments2D(lsmCrack, CrackTipPosition.Single);
            if (lsmPlotDirectory != null)
            {
                lsmCrack.EnrichmentLogger = new EnrichmentLogger(Model, lsmCrack, lsmPlotDirectory);
                lsmCrack.LevelSetLogger   = new LevelSetLogger(Model, lsmCrack, lsmPlotDirectory);
                lsmCrack.LevelSetComparer = new PreviousLevelSetComparer(lsmCrack, lsmPlotDirectory);
            }

            // Mesh geometry interaction
            lsmCrack.InitializeGeometry(initialCrack);
            //lsmCrack.UpdateGeometry(-dTheta, da);
            this.crack = lsmCrack;
        }
        public override async Task Start(CancellationToken token)
        {
            if (Propagator != null && !Propagator.Completion.IsCompleted)
            {
                throw new Exception("You must call Stop method first, as the previous run is still pending");
            }

            StartBuffering();
            var feederTask = Task.Run(async() =>
            {
                while (true)
                {
                    if (token.IsCancellationRequested)
                    {
                        break;
                    }
                    if (!InternalBuffer.TryTake(out var item))
                    {
                        Thread.Sleep(2000);
                        continue;
                    }
                    _itemAvailableEvent.Set();
                    await Propagator.SendAsync(item, token);
                }
            }, token);
            await base.Start(token);
        }
Exemple #6
0
        public void PropagateTest()
        {
            var propagator = new Propagator(Propagator.DefaultNeighborsGetter);
            var context    = new WaterContext(_map, propagator);
            var drop       = new WaterDrop(0.1);

            context.AddDrop(drop, (2, 2));
            context.PropagateWater(WaterContext.DefaultNeighborsGetter);
            var drops = context.Drops;

            Assert.Equal(4, drops.Count);
        }
Exemple #7
0
        public void MergeTest()
        {
            var propagator = new Propagator(Propagator.DefaultNeighborsGetter);
            var context    = new WaterContext(_map, propagator);
            var drop       = new WaterDrop(0.1);

            context.AddDrop(drop, (2, 2));
            context.PropagateWater(WaterContext.DefaultNeighborsGetter);
            context.PropagateWater(WaterContext.DefaultNeighborsGetter);
            var dropsBefore = context.Drops.ToDictionary(x => x.Key, x => x.Value);

            context.Merge();
            var dropsAfter = context.Drops.ToDictionary(x => x.Key, x => x.Value);

            Assert.Equal(16, dropsBefore.Count);
            Assert.Equal(9, dropsAfter.Count);
        }
Exemple #8
0
        internal void Run2(Action <string> action)
        {
            Resolution status = Propagator.Status;

            for (var retry = 0; retry < 5; retry++)
            {
                if (retry != 0)
                {
                    status = Propagator.Clear();
                }
                //if (status == Resolution.Contradiction)
                //{
                //    System.Console.WriteLine($"Found contradiction in initial conditions, retrying");
                //    continue;
                //}
                //if (config.Animate)
                if (true)
                {
                    status = RunAnimate(Model, Propagator, Dest, SampleSet.ExportOptions, action);
                }
                else
                {
                    status = Run(Propagator);
                }
                if (status == Resolution.Contradiction)
                {
                    System.Console.WriteLine($"Found contradiction, retrying");
                    continue;
                }
                break;
            }
            Directory.CreateDirectory(Path.GetDirectoryName(Dest));
            if (status == Resolution.Decided)
            {
                System.Console.WriteLine($"Writing {Dest}");
                Exporter.Export(Model, Propagator, Dest, config, SampleSet.ExportOptions);
                File.Delete(Contdest);
            }
            else
            {
                System.Console.WriteLine($"Writing {Contdest}");
                Exporter.Export(Model, Propagator, Contdest, config, SampleSet.ExportOptions);
                File.Delete(Dest);
            }
        }
        private void CreatePropagator(UtilityNetworkDefinition utilityNetworkDefinition, TraceConfiguration traceConfiguration)
        {
            const int ABCPhase = 7;

            #region Create a Propagator

            // Get a NetworkAttribute object for the Phases Normal attribute from the UtilityNetworkDefinition
            using (NetworkAttribute normalPhaseAttribute = utilityNetworkDefinition.GetNetworkAttribute("Phases Normal"))
            {
                // Create a propagator to propagate the Phases Normal attribute downstream from the source, using a Bitwise And function
                // Allow traversal to continue as long as the Phases Normal value includes any of the ABC phases
                // (represented by the constant ABCPhase)
                Propagator phasePropagator = new Propagator(normalPhaseAttribute, PropagatorFunction.BitwiseAnd, Operator.IncludesAny, ABCPhase);

                // Assign this propagator to our trace configuration
                traceConfiguration.Propagators = new List <Propagator>()
                {
                    phasePropagator
                };
            }

            #endregion
        }
        private void InitializeCrack()
        {
            IPropagator propagator;

            if (!writePropagation)
            {
                propagator = new FixedPropagator(propagationPath, null);
            }
            else
            {
                propagator = new Propagator(mesh, jIntegralRadiusOverElementSize,
                                            new HomogeneousMaterialAuxiliaryStates(globalHomogeneousMaterial),
                                            new HomogeneousSIFCalculator(globalHomogeneousMaterial),
                                            new MaximumCircumferentialTensileStressCriterion(), new ConstantIncrement2D(growthLength));
            }

            var crackMouth   = new CartesianPoint(webLeft, crackHeight);
            var crackTip     = new CartesianPoint(webLeft + crackLength, crackHeight);
            var initialCrack = new PolyLine2D(crackMouth, crackTip);
            var lsmCrack     = new TrackingExteriorCrackLSM(propagator, 0.0, new RelativeAreaResolver(heavisideTol));

            lsmCrack.Mesh = mesh;

            // Create enrichments
            lsmCrack.CrackBodyEnrichment = new CrackBodyEnrichment2D(lsmCrack);
            lsmCrack.CrackTipEnrichments = new CrackTipEnrichments2D(lsmCrack, CrackTipPosition.Single);
            if (lsmPlotDirectory != null)
            {
                lsmCrack.EnrichmentLogger = new EnrichmentLogger(Model, lsmCrack, lsmPlotDirectory);
                lsmCrack.LevelSetLogger   = new LevelSetLogger(Model, lsmCrack, lsmPlotDirectory);
                lsmCrack.LevelSetComparer = new PreviousLevelSetComparer(lsmCrack, lsmPlotDirectory);
            }

            // Mesh geometry interaction
            lsmCrack.InitializeGeometry(initialCrack);
            this.crack = lsmCrack;
        }
Exemple #11
0
        public static bool Go(Voxel voxel, Voxel.Coord center, int radius, Action <List <DynamicVoxel> > callback = null)
        {
            if (!voxel[center].Permanent)
            {
                // Break off a chunk of this voxel into a new DynamicMap.

                List <Voxel.Coord> edges = new List <Voxel.Coord>();

                Voxel.Coord ripStart = center.Move(-radius, -radius, -radius);
                Voxel.Coord ripEnd   = center.Move(radius, radius, radius);

                Dictionary <Voxel.Box, bool> permanentBoxes = new Dictionary <Voxel.Box, bool>();
                foreach (Voxel.Coord c in ripStart.CoordinatesBetween(ripEnd))
                {
                    Voxel.Box box = voxel.GetBox(c);
                    if (box != null && box.Type.Permanent)
                    {
                        permanentBoxes[box] = true;
                    }
                }

                foreach (Voxel.Box b in permanentBoxes.Keys)
                {
                    // Top and bottom
                    for (int x = b.X - 1; x <= b.X + b.Width; x++)
                    {
                        for (int z = b.Z - 1; z <= b.Z + b.Depth; z++)
                        {
                            Voxel.Coord coord = new Voxel.Coord {
                                X = x, Y = b.Y + b.Height, Z = z
                            };
                            if (coord.Between(ripStart, ripEnd))
                            {
                                edges.Add(coord);
                            }

                            coord = new Voxel.Coord {
                                X = x, Y = b.Y - 1, Z = z
                            };
                            if (coord.Between(ripStart, ripEnd))
                            {
                                edges.Add(coord);
                            }
                        }
                    }

                    // Outer shell
                    for (int y = b.Y; y < b.Y + b.Height; y++)
                    {
                        // Left and right
                        for (int z = b.Z - 1; z <= b.Z + b.Depth; z++)
                        {
                            Voxel.Coord coord = new Voxel.Coord {
                                X = b.X - 1, Y = y, Z = z
                            };
                            if (coord.Between(ripStart, ripEnd))
                            {
                                edges.Add(coord);
                            }

                            coord = new Voxel.Coord {
                                X = b.X + b.Width, Y = y, Z = z
                            };
                            if (coord.Between(ripStart, ripEnd))
                            {
                                edges.Add(coord);
                            }
                        }

                        // Backward and forward
                        for (int x = b.X; x < b.X + b.Width; x++)
                        {
                            Voxel.Coord coord = new Voxel.Coord {
                                X = x, Y = y, Z = b.Z - 1
                            };
                            if (coord.Between(ripStart, ripEnd))
                            {
                                edges.Add(coord);
                            }

                            coord = new Voxel.Coord {
                                X = x, Y = y, Z = b.Z + b.Depth
                            };
                            if (coord.Between(ripStart, ripEnd))
                            {
                                edges.Add(coord);
                            }
                        }
                    }
                }

                if (edges.Contains(center))
                {
                    return(false);
                }

                // Top and bottom
                for (int x = ripStart.X; x <= ripEnd.X; x++)
                {
                    for (int z = ripStart.Z; z <= ripEnd.Z; z++)
                    {
                        Voxel.Coord c = new Voxel.Coord {
                            X = x, Y = ripStart.Y, Z = z
                        };
                        Voxel.State s = voxel[c];
                        if (s != Voxel.States.Empty && !s.Permanent)
                        {
                            edges.Add(c);
                        }
                        c = new Voxel.Coord {
                            X = x, Y = ripEnd.Y, Z = z
                        };
                        s = voxel[c];
                        if (s != Voxel.States.Empty && !s.Permanent)
                        {
                            edges.Add(c);
                        }
                    }
                }

                // Sides
                for (int y = ripStart.Y + 1; y <= ripEnd.Y - 1; y++)
                {
                    // Left and right
                    for (int z = ripStart.Z; z <= ripEnd.Z; z++)
                    {
                        Voxel.Coord c = new Voxel.Coord {
                            X = ripStart.X, Y = y, Z = z
                        };
                        Voxel.State s = voxel[c];
                        if (s != Voxel.States.Empty && !s.Permanent)
                        {
                            edges.Add(c);
                        }
                        c = new Voxel.Coord {
                            X = ripEnd.X, Y = y, Z = z
                        };
                        s = voxel[c];
                        if (s != Voxel.States.Empty && !s.Permanent)
                        {
                            edges.Add(c);
                        }
                    }

                    // Backward and forward
                    for (int x = ripStart.X; x <= ripEnd.X; x++)
                    {
                        Voxel.Coord c = new Voxel.Coord {
                            X = x, Y = y, Z = ripStart.Z
                        };
                        Voxel.State s = voxel[c];
                        if (s != Voxel.States.Empty && !s.Permanent)
                        {
                            edges.Add(c);
                        }
                        c = new Voxel.Coord {
                            X = x, Y = y, Z = ripEnd.Z
                        };
                        s = voxel[c];
                        if (s != Voxel.States.Empty && !s.Permanent)
                        {
                            edges.Add(c);
                        }
                    }
                }

                Propagator p = WorldFactory.Instance.Get <Propagator>();
                foreach (Voxel.Coord c in edges)
                {
                    p.SparksLowPriority(voxel.GetAbsolutePosition(c), Propagator.Spark.Dangerous);
                }

                voxel.Empty(edges);

                voxel.Regenerate(callback);
                return(true);
            }
            return(false);
        }
 // extracts key values from row expression
 private static CompositeKey ExtractKey(PropagatorResult change, ReadOnlyCollection<DbExpression> keySelectors, Propagator parent)
 {
     Debug.Assert(null != change && null != keySelectors && null != parent);
     PropagatorResult[] keyValues = new PropagatorResult[keySelectors.Count];
     for (int i = 0; i < keySelectors.Count; i++)
     {
         PropagatorResult constant = Evaluator.Evaluate(keySelectors[i], change, parent);
         keyValues[i] = constant;
     }
     return new CompositeKey(keyValues);
 }
        private void InitializeCrack()
        {
            // Left crack
            // Propagator
            IPropagator leftPropagator;

            if (!writePropagation)
            {
                leftPropagator = new FixedPropagator(leftPropagationPath, null);
            }
            else
            {
                leftPropagator = new Propagator(Mesh, jIntegralRadiusOverElementSize,
                                                new HomogeneousMaterialAuxiliaryStates(globalHomogeneousMaterial),
                                                new HomogeneousSIFCalculator(globalHomogeneousMaterial),
                                                new MaximumCircumferentialTensileStressCriterion(), new ConstantIncrement2D(growthLength));
            }

            var initialLeftCrack = new PolyLine2D(new CartesianPoint(leftCrackMouthX, leftCrackMouthY),
                                                  new CartesianPoint(leftCrackTipX, leftCrackTipY));

            LeftCrack      = new TrackingExteriorCrackLSM(leftPropagator, tipEnrichmentRadius, new RelativeAreaResolver(heavisideTol));
            LeftCrack.Mesh = Mesh;

            // Create enrichments
            LeftCrack.CrackBodyEnrichment = new CrackBodyEnrichment2D(LeftCrack);
            LeftCrack.CrackTipEnrichments = new CrackTipEnrichments2D(LeftCrack, CrackTipPosition.Single);
            if (leftLsmPlotDirectory != null)
            {
                LeftCrack.EnrichmentLogger = new EnrichmentLogger(Model, LeftCrack, leftLsmPlotDirectory);
                LeftCrack.LevelSetLogger   = new LevelSetLogger(Model, LeftCrack, leftLsmPlotDirectory);
                LeftCrack.LevelSetComparer = new PreviousLevelSetComparer(LeftCrack, leftLsmPlotDirectory);
            }

            // Mesh geometry interaction
            LeftCrack.InitializeGeometry(initialLeftCrack);

            // Right crack
            // Propagator
            IPropagator rightPropagator;

            if (!writePropagation)
            {
                rightPropagator = new FixedPropagator(rightPropagationPath, null);
            }
            else
            {
                rightPropagator = new Propagator(Mesh, jIntegralRadiusOverElementSize,
                                                 new HomogeneousMaterialAuxiliaryStates(globalHomogeneousMaterial),
                                                 new HomogeneousSIFCalculator(globalHomogeneousMaterial),
                                                 new MaximumCircumferentialTensileStressCriterion(), new ConstantIncrement2D(growthLength));
            }

            var initialRightCrack = new PolyLine2D(new CartesianPoint(rightCrackMouthX, rightCrackMouthY),
                                                   new CartesianPoint(rightCrackTipX, rightCrackTipY));

            RightCrack      = new TrackingExteriorCrackLSM(rightPropagator, tipEnrichmentRadius, new RelativeAreaResolver(heavisideTol));
            RightCrack.Mesh = Mesh;

            // Create enrichments
            RightCrack.CrackBodyEnrichment = new CrackBodyEnrichment2D(RightCrack);
            RightCrack.CrackTipEnrichments = new CrackTipEnrichments2D(RightCrack, CrackTipPosition.Single);
            if (rightLsmPlotDirectory != null)
            {
                RightCrack.EnrichmentLogger = new EnrichmentLogger(Model, RightCrack, rightLsmPlotDirectory);
                RightCrack.LevelSetLogger   = new LevelSetLogger(Model, RightCrack, rightLsmPlotDirectory);
                RightCrack.LevelSetComparer = new PreviousLevelSetComparer(RightCrack, rightLsmPlotDirectory);
            }

            // Mesh geometry interaction
            RightCrack.InitializeGeometry(initialRightCrack);

            // Container for both cracks
            Crack = new MultipleCracksDisjoint(new TrackingExteriorCrackLSM[] { LeftCrack, RightCrack });
            //Crack = new MultipleCracksDisjoint(new TrackingExteriorCrackLSM[] { leftCrack });
        }
Exemple #14
0
            public override unsafe void Propagate()
            {
                // see VoxelLightChannel enum
                int channel = (int)Channel;

                // depropagate
                while (_depropQueue.TryDequeue(out var node))
                {
                    byte lightLevel = node.OriginalLight;
                    // positive direction
                    for (int axis = 0; axis < 3; axis++)
                    {
                        var neighbor = node;
                        (&neighbor.Coords.X)[axis]++;
                        if ((&neighbor.Coords.X)[axis] == VoxelChunk.SIZE)
                        {
                            var neighborChunkCoords = node.Chunk.Coords;
                            (&neighborChunkCoords.X)[axis]++;
                            neighbor.Chunk = Volume[neighborChunkCoords];
                            Propagator.addAlteredChunk(neighbor.Chunk);
                            (&neighbor.Coords.X)[axis] = 0;
                        }
                        if (neighbor.Chunk != null)
                        {
                            byte *neighborLightPtr = neighbor.LightLevel(channel);
                            byte  neighborLight    = *neighborLightPtr;
                            neighbor.OriginalLight = neighborLight;
                            if (!neighbor.IsOpaque)
                            {
                                if (neighborLight != 0 && (neighborLight < lightLevel))
                                {
                                    *neighborLightPtr = 0;
                                    _depropQueue.Enqueue(neighbor);
                                }
                                else if (neighborLight >= lightLevel)
                                {
                                    _propQueue.Enqueue(new PropNode(neighbor.Chunk, neighbor.Coords));
                                }
                            }
                        }
                    }
                    // negative direction
                    for (int axis = 0; axis < 3; axis++)
                    {
                        var neighbor = node;
                        (&neighbor.Coords.X)[axis]--;
                        if ((&neighbor.Coords.X)[axis] == -1)
                        {
                            var neighborChunkCoords = node.Chunk.Coords;
                            (&neighborChunkCoords.X)[axis]--;
                            neighbor.Chunk = Volume[neighborChunkCoords];
                            Propagator.addAlteredChunk(neighbor.Chunk);
                            (&neighbor.Coords.X)[axis] = VoxelChunk.SIZE - 1;
                        }
                        if (neighbor.Chunk != null)
                        {
                            byte *neighborLightPtr = neighbor.LightLevel(channel);
                            byte  neighborLight    = *neighborLightPtr;
                            neighbor.OriginalLight = neighborLight;
                            if (!neighbor.IsOpaque)
                            {
                                if (neighborLight != 0 && (neighborLight < lightLevel))
                                {
                                    *neighborLightPtr = 0;
                                    _depropQueue.Enqueue(neighbor);
                                }
                                else if (neighborLight >= lightLevel)
                                {
                                    _propQueue.Enqueue(new PropNode(neighbor.Chunk, neighbor.Coords));
                                }
                            }
                        }
                    }
                }
                // propagate
                while (_propQueue.TryDequeue(out var node))
                {
                    byte lightLevel         = *node.Chunk.LightData[channel][node.Coords];
                    int  neighborLightLevel = lightLevel - VoxelLight.LIGHT_DECREMENT;
                    if (neighborLightLevel > 0)
                    {
                        // positive direction
                        for (int axis = 0; axis < 3; axis++)
                        {
                            var neighbor = node;
                            (&neighbor.Coords.X)[axis]++;
                            if ((&neighbor.Coords.X)[axis] == VoxelChunk.SIZE)
                            {
                                var neighborChunkCoords = node.Chunk.Coords;
                                (&neighborChunkCoords.X)[axis]++;
                                neighbor.Chunk = Volume[neighborChunkCoords];
                                Propagator.addAlteredChunk(neighbor.Chunk);
                                (&neighbor.Coords.X)[axis] = 0;
                            }
                            if (neighbor.Chunk != null)
                            {
                                byte *light = neighbor.LightLevel(channel);
                                if (!neighbor.IsOpaque)
                                {
                                    if (*light < neighborLightLevel)
                                    {
                                        *light = (byte)neighborLightLevel;
                                        _propQueue.Enqueue(neighbor);
                                    }
                                }
                            }
                        }
                        // negative direction
                        for (int axis = 0; axis < 3; axis++)
                        {
                            var neighbor = node;
                            (&neighbor.Coords.X)[axis]--;
                            if ((&neighbor.Coords.X)[axis] == -1)
                            {
                                var neighborChunkCoords = node.Chunk.Coords;
                                (&neighborChunkCoords.X)[axis]--;
                                neighbor.Chunk = Volume[neighborChunkCoords];
                                Propagator.addAlteredChunk(neighbor.Chunk);
                                (&neighbor.Coords.X)[axis] = VoxelChunk.SIZE - 1;
                            }
                            if (neighbor.Chunk != null)
                            {
                                byte *light = neighbor.LightLevel(channel);
                                if (!neighbor.IsOpaque)
                                {
                                    if (*light < neighborLightLevel)
                                    {
                                        *light = (byte)neighborLightLevel;
                                        _propQueue.Enqueue(neighbor);
                                    }
                                }
                            }
                        }
                    }
                }
            }
Exemple #15
0
            public override unsafe void Propagate()
            {
                // see VoxelLightChannel enum
                int channel = (int)Channel;
                // these values are used when checking if the current axis in question is the same as the sunlight direction.
                // we have one value for positive axes and one for negative
                int lAxisP = channel;           // the first three are positive
                int lAxisN = channel - 3;       // the second three are negative

                // depropagate
                while (_depropQueue.TryDequeue(out var node))
                {
                    byte lightLevel = node.OriginalLight;
                    // positive direction
                    for (int axis = 0; axis < 3; axis++)
                    {
                        var neighbor = node;
                        (&neighbor.Coords.X)[axis]++;
                        if ((&neighbor.Coords.X)[axis] == VoxelChunk.SIZE)
                        {
                            var neighborChunkCoords = node.Chunk.Coords;
                            (&neighborChunkCoords.X)[axis]++;
                            neighbor.Chunk = Volume[neighborChunkCoords];
                            Propagator.addAlteredChunk(neighbor.Chunk);
                            (&neighbor.Coords.X)[axis] = 0;
                        }
                        if (neighbor.Chunk != null)
                        {
                            byte *neighborLightPtr = neighbor.LightLevel(channel);
                            byte  neighborLight    = *neighborLightPtr;
                            neighbor.OriginalLight = neighborLight;
                            if (!neighbor.IsOpaque)
                            {
                                if (neighborLight != 0 && (neighborLight < lightLevel || (lightLevel == VoxelLight.MAX_LIGHT && axis == lAxisP)))
                                {
                                    *neighborLightPtr = 0;
                                    _depropQueue.Enqueue(neighbor);
                                }
                                else if (neighborLight >= lightLevel)
                                {
                                    _propQueue.Enqueue(new PropNode(neighbor.Chunk, neighbor.Coords));
                                }
                            }
                        }
                    }
                    // negative direction
                    for (int axis = 0; axis < 3; axis++)
                    {
                        var neighbor = node;
                        (&neighbor.Coords.X)[axis]--;
                        if ((&neighbor.Coords.X)[axis] == -1)
                        {
                            var neighborChunkCoords = node.Chunk.Coords;
                            (&neighborChunkCoords.X)[axis]--;
                            neighbor.Chunk = Volume[neighborChunkCoords];
                            Propagator.addAlteredChunk(neighbor.Chunk);
                            (&neighbor.Coords.X)[axis] = VoxelChunk.SIZE - 1;
                        }
                        if (neighbor.Chunk != null)
                        {
                            byte *neighborLightPtr = neighbor.LightLevel(channel);
                            byte  neighborLight    = *neighborLightPtr;
                            neighbor.OriginalLight = neighborLight;
                            if (!neighbor.IsOpaque)
                            {
                                if (neighborLight != 0 && (neighborLight < lightLevel || (lightLevel == VoxelLight.MAX_LIGHT && axis == lAxisN)))
                                {
                                    *neighborLightPtr = 0;
                                    _depropQueue.Enqueue(neighbor);
                                }
                                else if (neighborLight >= lightLevel)
                                {
                                    _propQueue.Enqueue(new PropNode(neighbor.Chunk, neighbor.Coords));
                                }
                            }
                        }
                    }
                }
                // propagate
                while (_propQueue.TryDequeue(out var node))
                {
                    byte lightLevel         = *node.Chunk.LightData[channel][node.Coords];
                    int  neighborLightLevel = lightLevel - VoxelLight.LIGHT_DECREMENT;
                    if (neighborLightLevel > 0)
                    {
                        // positive direction
                        for (int axis = 0; axis < 3; axis++)
                        {
                            var neighbor = node;
                            (&neighbor.Coords.X)[axis]++;
                            if ((&neighbor.Coords.X)[axis] == VoxelChunk.SIZE)
                            {
                                var neighborChunkCoords = node.Chunk.Coords;
                                (&neighborChunkCoords.X)[axis]++;
                                neighbor.Chunk = Volume[neighborChunkCoords];
                                Propagator.addAlteredChunk(neighbor.Chunk);
                                (&neighbor.Coords.X)[axis] = 0;
                            }
                            if (neighbor.Chunk != null)
                            {
                                byte *light = neighbor.LightLevel(channel);
                                if (!neighbor.IsOpaque)
                                {
                                    if (axis == lAxisP && lightLevel == VoxelLight.MAX_LIGHT)
                                    {
                                        *light = VoxelLight.MAX_LIGHT;
                                        _propQueue.Enqueue(neighbor);
                                    }
                                    else if (*light < neighborLightLevel)
                                    {
                                        *light = (byte)neighborLightLevel;
                                        _propQueue.Enqueue(neighbor);
                                    }
                                }
                            }
                        }
                        // negative direction
                        for (int axis = 0; axis < 3; axis++)
                        {
                            var neighbor = node;
                            (&neighbor.Coords.X)[axis]--;
                            if ((&neighbor.Coords.X)[axis] == -1)
                            {
                                var neighborChunkCoords = node.Chunk.Coords;
                                (&neighborChunkCoords.X)[axis]--;
                                neighbor.Chunk = Volume[neighborChunkCoords];
                                Propagator.addAlteredChunk(neighbor.Chunk);
                                (&neighbor.Coords.X)[axis] = VoxelChunk.SIZE - 1;
                            }
                            if (neighbor.Chunk != null)
                            {
                                byte *light = neighbor.LightLevel(channel);
                                if (!neighbor.IsOpaque)
                                {
                                    if (axis == lAxisN && lightLevel == VoxelLight.MAX_LIGHT)
                                    {
                                        *light = VoxelLight.MAX_LIGHT;
                                        _propQueue.Enqueue(neighbor);
                                    }
                                    else if (*light < neighborLightLevel)
                                    {
                                        *light = (byte)neighborLightLevel;
                                        _propQueue.Enqueue(neighbor);
                                    }
                                }
                            }
                        }
                    }
                }
            }
 public virtual async Task <TEntity> GetNextItemAsync(CancellationToken token)
 {
     return(await Propagator.ReceiveAsync(token));
 }