Exemple #1
0
        public static int WriteTopBox(Vector3 M, Vector3 S, Color color, float T, bool Warp, int start, ThickLineVertex[] buffer)
        {
            float halfT = T * 0.5f;

            float   heightOffset = 0.05f;
            Vector3 A            = M + new Vector3(0, S.Y, 0);
            Vector3 B            = M + new Vector3(S.X, S.Y, 0);
            Vector3 C            = M + new Vector3(S.X, S.Y, S.Z);
            Vector3 D            = M + new Vector3(0, S.Y, S.Z);

            if (Warp)
            {
                A += VertexNoise.GetNoiseVectorFromRepeatingTexture(A);
                B += VertexNoise.GetNoiseVectorFromRepeatingTexture(B);
                C += VertexNoise.GetNoiseVectorFromRepeatingTexture(C);
                D += VertexNoise.GetNoiseVectorFromRepeatingTexture(D);
            }
            // Draw top loop.
            // A   1      B
            //   *+---+*
            // 4 |     | 2
            //   *+---+*
            // D   3      C
            start = WriteLineSegment(A + new Vector3(0, heightOffset, halfT), B + new Vector3(0, heightOffset, halfT), color, T, false, start, buffer);
            start = WriteLineSegment(B + new Vector3(-halfT, heightOffset, halfT), C + new Vector3(-halfT, heightOffset, -halfT), color, T, false, start, buffer);
            start = WriteLineSegment(C + new Vector3(0, heightOffset, -halfT), D + new Vector3(halfT, heightOffset, -halfT), color, T, false, start, buffer);
            start = WriteLineSegment(D + new Vector3(halfT, heightOffset, 0), A + new Vector3(halfT, heightOffset, halfT), color, T, false, start, buffer);
            return(start);
        }
Exemple #2
0
        public void HandleBoxes()
        {
            if (Voxels.Count == 0)
            {
                foreach (Body component in Boxes)
                {
                    KillBox(component);
                }
                Boxes.Clear();
            }

            int numBoxes = Math.Min(Math.Max(Resources.CurrentResourceCount / ResourcesPerVoxel, 1), Voxels.Count);

            if (Boxes.Count > numBoxes)
            {
                for (int i = Boxes.Count - 1; i >= numBoxes; i--)
                {
                    KillBox(Boxes[i]);
                    Boxes.RemoveAt(i);
                }
            }
            else if (Boxes.Count < numBoxes)
            {
                for (int i = Boxes.Count; i < numBoxes; i++)
                {
                    CreateBox(Voxels[i].Position + VertexNoise.GetNoiseVectorFromRepeatingTexture(Voxels[i].Position));
                }
            }
        }
Exemple #3
0
        private void ImplementUpdate(DwarfTime gameTime, ChunkManager chunks)
        {
            UpdateTimer.Update(gameTime);
            if (UpdateTimer.HasTriggered)
            {
                GameComponent p = (GameComponent)Parent;

                var voxelBelow = new VoxelHandle(chunks, GlobalVoxelCoordinate.FromVector3(p.GlobalTransform.Translation + Vector3.Down * 0.25f));

                if (voxelBelow.IsValid)
                {
                    var shadowTarget = VoxelHelpers.FindFirstVoxelBelow(voxelBelow);

                    if (shadowTarget.IsValid)
                    {
                        var     h   = shadowTarget.Coordinate.Y + 1;
                        Vector3 pos = p.GlobalTransform.Translation;
                        pos.Y = h;
                        pos  += VertexNoise.GetNoiseVectorFromRepeatingTexture(pos);
                        float  scaleFactor = GlobalScale / (Math.Max((p.GlobalTransform.Translation.Y - h) * 0.25f, 1));
                        Matrix newTrans    = OriginalTransform;
                        newTrans            *= Matrix.CreateScale(scaleFactor);
                        newTrans.Translation = (pos - p.GlobalTransform.Translation) + new Vector3(0.0f, 0.05f, 0.0f);
                        LightRamp            = new Color(LightRamp.R, LightRamp.G, LightRamp.B, (int)(scaleFactor * 255));
                        Matrix globalRotation = p.GlobalTransform;
                        globalRotation.Translation = Vector3.Zero;
                        LocalTransform             = newTrans * Matrix.Invert(globalRotation);
                    }
                }
                UpdateTimer.HasTriggered = false;
            }
        }
Exemple #4
0
        public void HandleCoins()
        {
            if (Voxels == null || Coins == null)
            {
                return;
            }

            if (Voxels.Count == 0)
            {
                foreach (Body component in Coins)
                {
                    KillCoins(component);
                }
                Coins.Clear();
            }

            int numCoins = (int)Math.Ceiling(Math.Min(Math.Max((float)(decimal)Money / (float)(decimal)MoneyPerPile, 1.0f), (float)Voxels.Count));

            if (Money == 0m)
            {
                numCoins = 0;
            }
            if (Coins.Count > numCoins)
            {
                for (int i = Coins.Count - 1; i >= numCoins; i--)
                {
                    KillCoins(Coins[i]);
                    Coins.RemoveAt(i);
                }
            }
            else if (Coins.Count < numCoins)
            {
                for (int i = Coins.Count; i < numCoins; i++)
                {
                    CreateCoins(Voxels[i].WorldPosition + VertexNoise.GetNoiseVectorFromRepeatingTexture(Voxels[i].WorldPosition));
                }
            }


            for (int i = 0; i < Coins.Count - 1; i++)
            {
                var fixture = Coins[i].GetRoot().GetComponent <CoinPileFixture>();
                fixture.SetFullness(1.0f);
                fixture.Name = MoneyPerPile.ToString();
            }

            DwarfBux remainder = Money - (Coins.Count - 1) * MoneyPerPile;

            if (Coins.Count > 0)
            {
                var fixture = Coins.Last().GetRoot().GetComponent <CoinPileFixture>();
                fixture.SetFullness((float)(decimal)remainder / (float)(decimal)MoneyPerPile);
                fixture.Name = remainder.ToString();
            }

            if (IsFull() && Faction.Treasurys.Count(t => !t.IsFull()) == 0 && Voxels.Count > 0)
            {
                Faction.World.MakeAnnouncement("Our treasury is full! Build more treasuries to store more money.");
            }
        }
Exemple #5
0
        public Fixture(
            ComponentManager Manager,
            Vector3 position,
            SpriteSheet asset,
            Point frame,
            SimpleSprite.OrientMode OrientMode = SimpleSprite.OrientMode.Spherical) :
            base(
                Manager,
                "Fixture",
                Matrix.CreateTranslation(position),
                new Vector3(asset.FrameWidth / 32.0f, asset.FrameHeight / 32.0f, asset.FrameWidth / 32.0f) * 0.9f,
                Vector3.Zero)
        {
            DebugColor = Microsoft.Xna.Framework.Color.Salmon;

            Asset           = asset;
            Frame           = frame;
            CollisionType   = CollisionType.Static;
            this.OrientMode = OrientMode;

            AddChild(new Health(Manager, "Hp", 10, 0, 10)
            {
                DebugColor = Color.Silver
            });

            LocalPosition += VertexNoise.GetNoiseVectorFromRepeatingTexture(position);

            CreateCosmeticChildren(Manager);
            PropogateTransforms();
        }
Exemple #6
0
        private Matrix GetWorldMatrix(Camera camera)
        {
            var currDistortion = VertexNoise.GetNoiseVectorFromRepeatingTexture(GlobalTransform.Translation);
            var distortion     = currDistortion * 0.1f + prevDistortion * 0.9f;

            prevDistortion = distortion;

            switch (OrientationType)
            {
            case OrientMode.Spherical:
                return(Matrix.CreateScale(WorldWidth, WorldHeight, 1.0f) * Matrix.CreateBillboard(GlobalTransform.Translation, camera.Position, camera.UpVector, null) * Matrix.CreateTranslation(distortion));

            case OrientMode.Fixed:
            {
                Matrix rotation = GlobalTransform;
                rotation.Translation = rotation.Translation + distortion;
                return(Matrix.CreateScale(WorldWidth, WorldHeight, 1.0f) * rotation);
            }

            case OrientMode.YAxis:
            {
                Matrix worldRot = Matrix.CreateConstrainedBillboard(GlobalTransform.Translation, camera.Position, Vector3.UnitY, null, null);
                worldRot.Translation = worldRot.Translation + distortion;
                return(Matrix.CreateScale(WorldWidth, WorldHeight, 1.0f) * worldRot);
            }

            default:
                throw new InvalidProgramException();
            }
        }
Exemple #7
0
        public static int WriteBox(Vector3 M, Vector3 S, Color C, float T, bool Warp, int start, ThickLineVertex[] buffer)
        {
            Vector3[] verts =
            {
                new Vector3(M.X,       M.Y,       M.Z),       new Vector3(M.X + S.X, M.Y,       M.Z),
                new Vector3(M.X + S.X, M.Y,       M.Z),       new Vector3(M.X + S.X, M.Y,       M.Z + S.Z),
                new Vector3(M.X + S.X, M.Y,       M.Z + S.Z), new Vector3(M.X,       M.Y,       M.Z + S.Z),
                new Vector3(M.X,       M.Y,       M.Z + S.Z), new Vector3(M.X,       M.Y,       M.Z),

                new Vector3(M.X,       M.Y + S.Y, M.Z),       new Vector3(M.X + S.X, M.Y + S.Y, M.Z),
                new Vector3(M.X + S.X, M.Y + S.Y, M.Z),       new Vector3(M.X + S.X, M.Y + S.Y, M.Z + S.Z),
                new Vector3(M.X + S.X, M.Y + S.Y, M.Z + S.Z), new Vector3(M.X,       M.Y + S.Y, M.Z + S.Z),
                new Vector3(M.X,       M.Y + S.Y, M.Z + S.Z), new Vector3(M.X,       M.Y + S.Y, M.Z),

                new Vector3(M.X,       M.Y,       M.Z),       new Vector3(M.X,       M.Y + S.Y, M.Z),
                new Vector3(M.X + S.X, M.Y,       M.Z),       new Vector3(M.X + S.X, M.Y + S.Y, M.Z),
                new Vector3(M.X + S.X, M.Y,       M.Z + S.Z), new Vector3(M.X + S.X, M.Y + S.Y, M.Z + S.Z),
                new Vector3(M.X,       M.Y,       M.Z + S.Z), new Vector3(M.X,       M.Y + S.Y, M.Z + S.Z),
            };
            if (Warp)
            {
                for (int i = 0; i < verts.Length; i++)
                {
                    verts[i] += VertexNoise.GetNoiseVectorFromRepeatingTexture(verts[i]);
                }
            }

            for (int i = 0; i < verts.Length; i += 2)
            {
                start = WriteLineSegment(verts[i] + boxOffsets[i], verts[i + 1] + boxOffsets[i + 1], C, T, false, start, buffer);
            }
            return(start);
        }
Exemple #8
0
        public override void Update(DwarfTime gameTime, ChunkManager chunks, Camera camera)
        {
            UpdateTimer.Update(gameTime);
            if (HasMoved && UpdateTimer.HasTriggered)
            {
                Body p = (Body)Parent;

                VoxelChunk chunk = chunks.ChunkData.GetVoxelChunkAtWorldLocation(p.GlobalTransform.Translation);

                if (chunk != null)
                {
                    Vector3 g = chunk.WorldToGrid(p.GlobalTransform.Translation + Vector3.Down * 0.25f);

                    int h = chunk.GetFilledVoxelGridHeightAt((int)g.X, (int)g.Y, (int)g.Z);

                    if (h != -1)
                    {
                        Vector3 pos = p.GlobalTransform.Translation;
                        pos.Y = h;
                        pos  += VertexNoise.GetNoiseVectorFromRepeatingTexture(pos + Vector3.Down * 0.25f);
                        float  scaleFactor = GlobalScale / (Math.Max((p.GlobalTransform.Translation.Y - h) * 0.25f, 1));
                        Matrix newTrans    = OriginalTransform;
                        newTrans            *= Matrix.CreateScale(scaleFactor);
                        newTrans.Translation = (pos - p.GlobalTransform.Translation) + new Vector3(0.0f, 0.1f, 0.0f);
                        Tint           = new Color(Tint.R, Tint.G, Tint.B, (int)(scaleFactor * 255));
                        LocalTransform = newTrans;
                    }
                }
                UpdateTimer.HasTriggered = false;
            }


            base.Update(gameTime, chunks, camera);
        }
Exemple #9
0
        public static void Render(
            GraphicsDevice Device,
            Shader Effect,
            OrbitCamera Camera,
            DesignationDrawer DesignationDrawer,
            DesignationSet Designations,
            WorldManager World)
        {
            lock (renderLock)
            {
                Drawer3D.Effect = Effect;
                Drawer3D.Camera = Camera;

                var colorModulation = Math.Abs(Math.Sin(DwarfTime.LastTime.TotalGameTime.TotalSeconds * 2.0f));

                DesignationDrawer.DrawHilites(
                    World,
                    Designations,
                    _addBox,
                    (pos, type) =>
                {
                    Effect.MainTexture = AssetManager.GetContentTexture(ContentPaths.Terrain.terrain_tiles);
                    Effect.LightRamp   = Color.White;
                    // Todo: Alpha pulse
                    Effect.VertexColorTint  = new Color(0.1f, 0.9f, 1.0f, 1.0f);
                    var prevTechnique       = Effect.CurrentTechnique;
                    Effect.CurrentTechnique = Effect.Techniques[Shader.Technique.Stipple];
                    var pos_distorted       = pos + Vector3.Up * 0.15f + VertexNoise.GetNoiseVectorFromRepeatingTexture(pos + Vector3.One * 0.5f);
                    Effect.World            = Matrix.CreateTranslation(pos_distorted);

                    foreach (EffectPass pass in Effect.CurrentTechnique.Passes)
                    {
                        pass.Apply();
                        VoxelLibrary.GetPrimitive(type).Render(Device);
                    }

                    Effect.LightRamp        = Color.White;
                    Effect.VertexColorTint  = Color.White;
                    Effect.World            = Matrix.Identity;
                    Effect.CurrentTechnique = prevTechnique;
                });

                foreach (var box in Boxes)
                {
                    _addBox(box.RealBox.Min, box.RealBox.Max - box.RealBox.Min, box.Color, box.Thickness, box.Warp);
                }

                foreach (var segment in Segments)
                {
                    _addLineSegment(segment.A, segment.B, segment.Color, segment.Thickness, false);
                }

                _flush();

                Boxes.Clear();
                Segments.Clear();
            }
        }
Exemple #10
0
        private static void AddDecalGeometry(
            RawPrimitive Into,
            int[] AmbientScratchSpace,
            BoxPrimitive Primitive,
            VoxelHandle V,
            BoxPrimitive.FaceDescriptor faceDescriptor,
            int exploredVerts,
            Vector3[] VertexPositions,
            VertexColorInfo[] VertexColors,
            Color[] VertexTints,
            DecalType Decal,
            byte Orientation)
        {
            var indexOffset = Into.VertexCount;
            var UV          = new Vector2(Decal.Tile.X * (1.0f / 16.0f), Decal.Tile.Y * (1.0f / 16.0f));
            var UVBounds    = new Vector4(UV.X + 0.001f, UV.Y + 0.001f, UV.X + (1.0f / 16.0f) - 0.001f, UV.Y + (1.0f / 16.0f) - 0.001f);
            var UVs         = new Vector2[faceDescriptor.VertexCount];

            for (int faceVertex = 0; faceVertex < faceDescriptor.VertexCount; faceVertex++)
            {
                var vertex = Primitive.Vertices[faceDescriptor.VertexOffset + faceVertex];
                UVs[faceVertex] = UV + new Vector2(vertex.Position.X / 16.0f, vertex.Position.Z / 16.0f);
            }

            for (int faceVertex = 0; faceVertex < faceDescriptor.VertexCount; faceVertex++)
            {
                var vertex = Primitive.Vertices[faceDescriptor.VertexOffset + faceVertex];

                AmbientScratchSpace[faceVertex] = VertexColors[faceVertex].AmbientColor;

                var uv = faceVertex + Orientation;
                uv %= faceDescriptor.VertexCount; // This will only work if the face has 4 verts...

                Into.AddVertex(new ExtendedVertex(
                                   VertexPositions[faceVertex] + VertexNoise.GetNoiseVectorFromRepeatingTexture(VertexPositions[faceVertex]),
                                   VertexColors[faceVertex].AsColor(),
                                   VertexTints[faceVertex],
                                   UVs[uv],
                                   UVBounds));
            }

            bool flippedQuad = AmbientScratchSpace[0] + AmbientScratchSpace[2] >
                               AmbientScratchSpace[1] + AmbientScratchSpace[3];

            for (int idx = faceDescriptor.IndexOffset; idx < faceDescriptor.IndexCount +
                 faceDescriptor.IndexOffset; idx++)
            {
                ushort offset  = flippedQuad ? Primitive.FlippedIndexes[idx] : Primitive.Indexes[idx];
                ushort offset0 = flippedQuad ? Primitive.FlippedIndexes[faceDescriptor.IndexOffset] : Primitive.Indexes[faceDescriptor.IndexOffset];
                Into.AddIndex((short)(indexOffset + offset - offset0));
            }
        }
Exemple #11
0
        private void HandleBoxes()
        {
            if (Voxels == null || Boxes == null)
            {
                return;
            }

            if (Boxes.Any(b => b.IsDead))
            {
                ZoneBodies.RemoveAll(z => z.IsDead);
                Boxes.RemoveAll(c => c.IsDead);

                for (int i = 0; i < Boxes.Count; i++)
                {
                    Boxes[i].LocalPosition = new Vector3(0.5f, 1.5f, 0.5f) + Voxels[i].WorldPosition + VertexNoise.GetNoiseVectorFromRepeatingTexture(Voxels[i].WorldPosition + new Vector3(0.5f, 0, 0.5f));
                }
            }

            if (Voxels.Count == 0)
            {
                foreach (GameComponent component in Boxes)
                {
                    KillBox(component);
                }
                Boxes.Clear();
            }

            int numBoxes = Math.Min(Math.Max(Resources.TotalCount / ResourcesPerVoxel, 1), Voxels.Count);

            if (Resources.TotalCount == 0)
            {
                numBoxes = 0;
            }

            if (Boxes.Count > numBoxes)
            {
                for (int i = Boxes.Count - 1; i >= numBoxes; i--)
                {
                    KillBox(Boxes[i]);
                    Boxes.RemoveAt(i);
                }
            }
            else if (Boxes.Count < numBoxes)
            {
                for (int i = Boxes.Count; i < numBoxes; i++)
                {
                    CreateBox(Voxels[i].WorldPosition + VertexNoise.GetNoiseVectorFromRepeatingTexture(Voxels[i].WorldPosition + new Vector3(0.5f, 0, 0.5f)));
                }
            }
        }
Exemple #12
0
        public CraftedBody(
            ComponentManager Manager,
            string name,
            Matrix localTransform,
            Vector3 bboxExtents,
            Vector3 bboxPos,
            CraftDetails details) :
            base(Manager, name, localTransform, bboxExtents, bboxPos)
        {
            this.SetFlag(Flag.ShouldSerialize, true);
            AddChild(details);

            LocalPosition += VertexNoise.GetNoiseVectorFromRepeatingTexture(LocalPosition);
        }
Exemple #13
0
        public static int WriteLineSegment(Vector3 A, Vector3 B, Color Color, float Thickness, bool Warp, int start, ThickLineVertex[] buffer)
        {
            if (Warp)
            {
                A += VertexNoise.GetNoiseVectorFromRepeatingTexture(A);
                B += VertexNoise.GetNoiseVectorFromRepeatingTexture(B);
            }

            var bRay = A - B;

            bRay.Normalize();

            start = WriteTriangle(new Vector4(A, Thickness), new Vector4(B, Thickness), new Vector4(A, -Thickness), bRay, Color, start, buffer);
            return(WriteTriangle(new Vector4(A, -Thickness), new Vector4(B, -Thickness), new Vector4(B, Thickness), bRay, Color, start, buffer));
        }
Exemple #14
0
 public override void UpdateViewMatrix()
 {
     if (this.Control == ControlType.Walk)
     {
         float heightOffset = crouched ? 0.0f : 0.5f;
         HeightOffset = heightOffset * 0.1f + HeightOffset * 0.9f;
         var undistorted = Position + Vector3.UnitY * heightOffset;
         var distorted   = VertexNoise.Warp(undistorted);
         var noise       = distorted - undistorted;
         Noise      = noise * 0.1f + Noise * 0.9f;
         ViewMatrix = Matrix.CreateLookAt(Position + Vector3.UnitY * HeightOffset + Noise, FollowAutoTarget ? (AutoTarget * 0.5f + Target * 0.5f) : Target + Vector3.UnitY * HeightOffset + Noise, Vector3.UnitY);
     }
     else
     {
         ViewMatrix = Matrix.CreateLookAt(Position, FollowAutoTarget ? (AutoTarget * 0.5f + Target * 0.5f) : Target, Vector3.UnitY);
     }
 }
Exemple #15
0
        private static void _addLineSegment(Vector3 A, Vector3 B, Color Color, float Thickness, bool Warp)
        {
            if (Warp)
            {
                A += VertexNoise.GetNoiseVectorFromRepeatingTexture(A);
                B += VertexNoise.GetNoiseVectorFromRepeatingTexture(B);
            }

            var aRay = A - Camera.Position;
            var bRay = A - B;
            var perp = Vector3.Cross(aRay, bRay);

            perp.Normalize();
            perp *= Thickness / 2;

            _addTriangle(A + perp, B + perp, A - perp, Color);
            _addTriangle(A - perp, B - perp, B + perp, Color);
        }
Exemple #16
0
        private Matrix GetWorldMatrix(Camera camera)
        {
            var currDistortion = VertexNoise.GetNoiseVectorFromRepeatingTexture(GlobalTransform.Translation);
            var distortion     = currDistortion * 0.1f + prevDistortion * 0.9f;

            prevDistortion = distortion;
            var   frameSize      = AnimPlayer.GetCurrentFrameSize();
            var   offsets        = AnimPlayer.GetCurrentAnimation().YOffset;
            float verticalOffset = offsets == null || offsets.Count == 0 ? 0.0f : offsets[Math.Min(AnimPlayer.CurrentFrame, offsets.Count - 1)] * 1.0f / 32.0f;
            var   pos            = GlobalTransform.Translation + Vector3.Up * verticalOffset;

            switch (OrientationType)
            {
            case OrientMode.Spherical:
            {
                Matrix bill = Matrix.CreateScale(frameSize.X, frameSize.Y, 1.0f) * Matrix.CreateBillboard(pos, camera.Position, camera.UpVector, null) * Matrix.CreateTranslation(distortion);
                //Matrix noTransBill = bill;
                //noTransBill.Translation = Vector3.Zero;

                //Matrix worldRot = noTransBill;
                //worldRot.Translation = bill.Translation;// + VertexNoise.GetNoiseVectorFromRepeatingTexture(bill.Translation);
                return(bill);
            }

            case OrientMode.Fixed:
            {
                Matrix rotation = Matrix.CreateScale(frameSize.X, frameSize.Y, 1.0f) * GlobalTransform;
                rotation.Translation = pos + distortion;
                return(rotation);
            }

            case OrientMode.YAxis:
            {
                Matrix worldRot = Matrix.CreateScale(frameSize.X, frameSize.Y, 1.0f) * Matrix.CreateConstrainedBillboard(pos, camera.Position, Vector3.UnitY, null, null);
                worldRot.Translation = worldRot.Translation + distortion;
                return(worldRot);
            }

            default:
                throw new InvalidProgramException();
            }
        }
Exemple #17
0
        public BoxDrawCommand3D(BoundingBox box, Color color, float thickness, bool warp) :
            base(color)
        {
            BoundingBox = box;
            Matrix worldMatrix = Matrix.CreateScale(box.Max.X - box.Min.X, box.Max.Y - box.Min.Y, box.Max.Z - box.Min.Z);

            worldMatrix.Translation = box.Min;

            for (int i = 0; i < 4; i++)
            {
                Vector3[] points = warp ? VertexNoise.WarpPoints(BoxPoints[i], new Vector3(box.Max.X - box.Min.X, box.Max.Y - box.Min.Y, box.Max.Z - box.Min.Z), box.Min) : BoxPoints[i];

                int count = 0;

                List <VertexPositionColor> triangleStrip = Drawer3D.GetTriangleStrip(points, thickness, color, ref count, worldMatrix);
                _stripVertices.Add(new VertexPositionColor[triangleStrip.Count]);
                _stripTriangleCounts.Add(count);
                triangleStrip.CopyTo(_stripVertices[i]);
            }
        }
        private static void AddTopFaceGeometry(
            RawPrimitive Into,
            int[] AmbientScratchSpace,
            BoxPrimitive Primitive,
            BoxPrimitive.FaceDescriptor faceDescriptor,
            Vector3[] VertexPositions,
            VertexColorInfo[] VertexColors,
            Color[] VertexTints,
            Vector2 UVScale,
            Vector2 UV,
            Vector4 UVBounds)
        {
            var indexOffset = Into.VertexCount;

            for (int faceVertex = 0; faceVertex < faceDescriptor.VertexCount; faceVertex++)
            {
                var vertex = Primitive.Vertices[faceDescriptor.VertexOffset + faceVertex];

                AmbientScratchSpace[faceVertex] = VertexColors[faceVertex].AmbientColor;

                Into.AddVertex(new ExtendedVertex(
                                   VertexPositions[faceVertex] + VertexNoise.GetNoiseVectorFromRepeatingTexture(VertexPositions[faceVertex]),
                                   VertexColors[faceVertex].AsColor(),
                                   VertexTints[faceVertex],
                                   UV + new Vector2(vertex.Position.X / 16.0f * UVScale.X, vertex.Position.Z / 16.0f * UVScale.Y),
                                   UVBounds));
            }

            bool flippedQuad = AmbientScratchSpace[0] + AmbientScratchSpace[2] >
                               AmbientScratchSpace[1] + AmbientScratchSpace[3];

            for (int idx = faceDescriptor.IndexOffset; idx < faceDescriptor.IndexCount +
                 faceDescriptor.IndexOffset; idx++)
            {
                ushort offset  = flippedQuad ? Primitive.FlippedIndexes[idx] : Primitive.Indexes[idx];
                ushort offset0 = flippedQuad ? Primitive.FlippedIndexes[faceDescriptor.IndexOffset] : Primitive.Indexes[faceDescriptor.IndexOffset];
                Into.AddIndex((short)(indexOffset + offset - offset0));
            }
        }
Exemple #19
0
        public static int WriteLineSegment(Vector3 A, Vector3 B, Color Color, float Thickness, bool Warp, int start, VertexPositionColor[] buffer)
        {
            if (Warp)
            {
                A += VertexNoise.GetNoiseVectorFromRepeatingTexture(A);
                B += VertexNoise.GetNoiseVectorFromRepeatingTexture(B);
            }

            var aRay = Vector3.Up;
            var bRay = A - B;

            if (Math.Abs(Vector3.Dot(aRay, bRay)) > 0.99)
            {
                aRay = Vector3.Right;
            }
            var perp = Vector3.Cross(aRay, bRay);

            perp.Normalize();
            perp *= Thickness / 2;

            start = WriteTriangle(A + perp, B + perp, A - perp, Color, start, buffer);
            return(WriteTriangle(A - perp, B - perp, B + perp, Color, start, buffer));
        }
Exemple #20
0
        private static void AddGrassGeometry(
            RawPrimitive Into,
            int[] AmbientScratchSpace,
            BoxPrimitive Primitive,
            BoxPrimitive.FaceDescriptor faceDescriptor,
            Vector3[] VertexPositions,
            VertexColorInfo[] VertexColors,
            Color[] VertexTints,
            GrassType Decal)
        {
            var indexOffset = Into.VertexCount;
            var UV          = new Vector2(Decal.Tile.X * (1.0f / 16.0f), Decal.Tile.Y * (1.0f / 16.0f));
            var UVBounds    = new Vector4(UV.X + 0.001f, UV.Y + 0.001f, UV.X + (1.0f / 16.0f) - 0.001f, UV.Y + (1.0f / 16.0f) - 0.001f);

            for (int faceVertex = 0; faceVertex < faceDescriptor.VertexCount; faceVertex++)
            {
                var vertex = Primitive.Vertices[faceDescriptor.VertexOffset + faceVertex];

                AmbientScratchSpace[faceVertex] = VertexColors[faceVertex].AmbientColor;

                Into.AddVertex(new ExtendedVertex(
                                   VertexPositions[faceVertex] + VertexNoise.GetNoiseVectorFromRepeatingTexture(VertexPositions[faceVertex]),
                                   VertexColors[faceVertex].AsColor(),
                                   VertexTints[faceVertex],
                                   UV + new Vector2(vertex.Position.X / 16.0f, vertex.Position.Z / 16.0f),
                                   UVBounds));
            }

            bool flippedQuad = (AmbientScratchSpace[0] + AmbientScratchSpace[2]) > (AmbientScratchSpace[1] + AmbientScratchSpace[3]);

            for (int idx = faceDescriptor.IndexOffset; idx < faceDescriptor.IndexCount + faceDescriptor.IndexOffset; ++idx)
            {
                ushort offset  = flippedQuad ? Primitive.FlippedIndexes[idx] : Primitive.Indexes[idx];
                ushort offset0 = flippedQuad ? Primitive.FlippedIndexes[faceDescriptor.IndexOffset] : Primitive.Indexes[faceDescriptor.IndexOffset];
                Into.AddIndex((short)(indexOffset + offset - offset0));
            }
        }
Exemple #21
0
        public void Render(DwarfTime gameTime,
                           ChunkManager chunks,
                           Camera camera,
                           SpriteBatch spriteBatch,
                           GraphicsDevice graphicsDevice,
                           Shader effect,
                           bool renderingForWater)
        {
            if (!IsVisible)
            {
                return;
            }

            if (CurrentAnimation == null || CurrentAnimation.CurrentFrame < 0 ||
                CurrentAnimation.CurrentFrame >= CurrentAnimation.Primitives.Count)
            {
                return;
            }

            GamePerformance.Instance.StartTrackPerformance("Render - Sprite");

            // Everything that draws should set it's tint, making this pointless.
            Color origTint = effect.VertexColorTint;

            ApplyTintingToEffect(effect);


            CurrentAnimation.PreRender();
            SpriteSheet = CurrentAnimation.SpriteSheet;
            var currDistortion = VertexNoise.GetNoiseVectorFromRepeatingTexture(GlobalTransform.Translation);
            var distortion     = currDistortion * 0.1f + prevDistortion * 0.9f;

            prevDistortion = distortion;
            switch (OrientationType)
            {
            case OrientMode.Spherical:
            {
                Matrix bill = Matrix.CreateBillboard(GlobalTransform.Translation, camera.Position, camera.UpVector, null) * Matrix.CreateTranslation(distortion);
                //Matrix noTransBill = bill;
                //noTransBill.Translation = Vector3.Zero;

                //Matrix worldRot = noTransBill;
                //worldRot.Translation = bill.Translation;// + VertexNoise.GetNoiseVectorFromRepeatingTexture(bill.Translation);
                effect.World = bill;
                break;
            }

            case OrientMode.Fixed:
            {
                Matrix rotation = GlobalTransform;
                rotation.Translation = rotation.Translation + distortion;
                effect.World         = rotation;
                break;
            }

            case OrientMode.YAxis:
            {
                Matrix worldRot = Matrix.CreateConstrainedBillboard(GlobalTransform.Translation, camera.Position, Vector3.UnitY, null, null);
                worldRot.Translation = worldRot.Translation + distortion;
                effect.World         = worldRot;
                break;
            }
            }

            effect.MainTexture = SpriteSheet.GetTexture();

            if (DrawSilhouette)
            {
                Color oldTint = effect.VertexColorTint;
                effect.VertexColorTint           = SilhouetteColor;
                graphicsDevice.DepthStencilState = DepthStencilState.None;
                var oldTechnique = effect.CurrentTechnique;
                effect.CurrentTechnique = effect.Techniques[Shader.Technique.Silhouette];
                foreach (EffectPass pass in effect.CurrentTechnique.Passes)
                {
                    pass.Apply();
                    CurrentAnimation.Primitives[CurrentAnimation.CurrentFrame].Render(graphicsDevice);
                }

                graphicsDevice.DepthStencilState = DepthStencilState.Default;
                effect.VertexColorTint           = oldTint;
                effect.CurrentTechnique          = oldTechnique;
            }

            if (EnableWind)
            {
                effect.EnableWind = true;
            }

            foreach (EffectPass pass in effect.CurrentTechnique.Passes)
            {
                pass.Apply();
                CurrentAnimation.Primitives[CurrentAnimation.CurrentFrame].Render(graphicsDevice);
            }
            effect.VertexColorTint = origTint;
            effect.EnableWind      = false;

            GamePerformance.Instance.StopTrackPerformance("Render - Sprite");
        }
Exemple #22
0
        public override void Render(DwarfTime gameTime,
                                    ChunkManager chunks,
                                    Camera camera,
                                    SpriteBatch spriteBatch,
                                    GraphicsDevice graphicsDevice,
                                    Effect effect,
                                    bool renderingForWater)
        {
            base.Render(gameTime, chunks, camera, spriteBatch, graphicsDevice, effect, renderingForWater);

            if (!IsVisible)
            {
                return;
            }

            if (CurrentAnimation != null && CurrentAnimation.CurrentFrame >= 0 && CurrentAnimation.CurrentFrame < CurrentAnimation.Primitives.Count)
            {
                CurrentAnimation.PreRender();
                SpriteSheet = CurrentAnimation.SpriteSheet;
                effect.Parameters["xTexture"].SetValue(SpriteSheet.GetTexture());

                if (OrientationType != OrientMode.Fixed)
                {
                    if (camera.Projection == Camera.ProjectionMode.Perspective)
                    {
                        if (OrientationType == OrientMode.Spherical)
                        {
                            float  xscale      = GlobalTransform.Left.Length();
                            float  yscale      = GlobalTransform.Up.Length();
                            float  zscale      = GlobalTransform.Forward.Length();
                            Matrix rot         = Matrix.CreateRotationZ(BillboardRotation);
                            Matrix bill        = Matrix.CreateBillboard(GlobalTransform.Translation, camera.Position, camera.UpVector, null);
                            Matrix noTransBill = bill;
                            noTransBill.Translation = Vector3.Zero;

                            Matrix worldRot = Matrix.CreateScale(new Vector3(xscale, yscale, zscale)) * rot * noTransBill;
                            worldRot.Translation = DistortPosition ? bill.Translation + VertexNoise.GetNoiseVectorFromRepeatingTexture(bill.Translation) : bill.Translation;
                            effect.Parameters["xWorld"].SetValue(worldRot);
                        }
                        else
                        {
                            Vector3 axis = Vector3.Zero;

                            switch (OrientationType)
                            {
                            case OrientMode.XAxis:
                                axis = Vector3.UnitX;
                                break;

                            case OrientMode.YAxis:
                                axis = Vector3.UnitY;
                                break;

                            case OrientMode.ZAxis:
                                axis = Vector3.UnitZ;
                                break;
                            }

                            Matrix worldRot = Matrix.CreateConstrainedBillboard(GlobalTransform.Translation, camera.Position, axis, null, null);
                            worldRot.Translation = DistortPosition ? worldRot.Translation + VertexNoise.GetNoiseVectorFromRepeatingTexture(worldRot.Translation) : worldRot.Translation;
                            effect.Parameters["xWorld"].SetValue(worldRot);
                        }
                    }
                    else
                    {
                        Matrix rotation = Matrix.CreateRotationY(-(float)Math.PI * 0.25f) * Matrix.CreateTranslation(GlobalTransform.Translation);
                        rotation.Translation = DistortPosition ? rotation.Translation + VertexNoise.GetNoiseVectorFromRepeatingTexture(rotation.Translation) : rotation.Translation;
                        effect.Parameters["xWorld"].SetValue(rotation);
                    }
                }
                else
                {
                    Matrix rotation = GlobalTransform;
                    rotation.Translation = DistortPosition ? rotation.Translation + VertexNoise.GetNoiseVectorFromRepeatingTexture(rotation.Translation) : rotation.Translation;
                    effect.Parameters["xWorld"].SetValue(rotation);
                }


                foreach (EffectPass pass in effect.CurrentTechnique.Passes)
                {
                    pass.Apply();
                    CurrentAnimation.Primitives[CurrentAnimation.CurrentFrame].Render(graphicsDevice);
                }
            }
        }
        override public void Render(DwarfTime gameTime,
                                    ChunkManager chunks,
                                    Camera camera,
                                    SpriteBatch spriteBatch,
                                    GraphicsDevice graphicsDevice,
                                    Shader effect,
                                    bool renderingForWater)
        {
            if (!IsVisible)
            {
                return;
            }

            foreach (var layer in Layers)
            {
                if (layer.Verticies == null)
                {
                    float normalizeX = layer.Sheet.FrameWidth / (float)(layer.Sheet.Width);
                    float normalizeY = layer.Sheet.FrameWidth / (float)(layer.Sheet.Height);

                    List <Vector2> uvs = new List <Vector2>
                    {
                        new Vector2(0.0f, 0.0f),
                        new Vector2(1.0f, 0.0f),
                        new Vector2(1.0f, 1.0f),
                        new Vector2(0.0f, 1.0f)
                    };

                    Vector2 pixelCoords      = new Vector2(layer.Frame.X * layer.Sheet.FrameWidth, layer.Frame.Y * layer.Sheet.FrameHeight);
                    Vector2 normalizedCoords = new Vector2(pixelCoords.X / (float)layer.Sheet.Width, pixelCoords.Y / (float)layer.Sheet.Height);
                    var     bounds           = new Vector4(normalizedCoords.X + 0.001f, normalizedCoords.Y + 0.001f, normalizedCoords.X + normalizeX - 0.001f, normalizedCoords.Y + normalizeY - 0.001f);

                    for (int vert = 0; vert < 4; vert++)
                    {
                        uvs[vert] = new Vector2(normalizedCoords.X + uvs[vert].X * normalizeX, normalizedCoords.Y + uvs[vert].Y * normalizeY);
                    }


                    Vector3 topLeftFront  = new Vector3(-0.5f * WorldWidth, 0.5f * WorldHeight, 0.0f);
                    Vector3 topRightFront = new Vector3(0.5f * WorldWidth, 0.5f * WorldHeight, 0.0f);
                    Vector3 btmRightFront = new Vector3(0.5f * WorldWidth, -0.5f * WorldHeight, 0.0f);
                    Vector3 btmLeftFront  = new Vector3(-0.5f * WorldWidth, -0.5f * WorldHeight, 0.0f);

                    layer.Verticies = new[]
                    {
                        new ExtendedVertex(topLeftFront, Color.White, Color.White, uvs[0], bounds),  // 0
                        new ExtendedVertex(topRightFront, Color.White, Color.White, uvs[1], bounds), // 1
                        new ExtendedVertex(btmRightFront, Color.White, Color.White, uvs[2], bounds), // 2
                        new ExtendedVertex(btmLeftFront, Color.White, Color.White, uvs[3], bounds)   // 3
                    };

                    layer.Indicies = new int[]
                    {
                        0, 1, 3,
                        1, 2, 3
                    };
                }
            }

            // Everything that draws should set it's tint, making this pointless.
            Color origTint = effect.VertexColorTint;

            ApplyTintingToEffect(effect);

            var currDistortion = VertexNoise.GetNoiseVectorFromRepeatingTexture(GlobalTransform.Translation);
            var distortion     = currDistortion * 0.1f + prevDistortion * 0.9f;

            prevDistortion = distortion;
            switch (OrientationType)
            {
            case OrientMode.Spherical:
            {
                Matrix bill = Matrix.CreateBillboard(GlobalTransform.Translation, camera.Position, camera.UpVector, null) * Matrix.CreateTranslation(distortion);
                effect.World = bill;
                break;
            }

            case OrientMode.Fixed:
            {
                Matrix rotation = GlobalTransform;
                rotation.Translation = rotation.Translation + distortion;
                effect.World         = rotation;
                break;
            }

            case OrientMode.YAxis:
            {
                Matrix worldRot = Matrix.CreateConstrainedBillboard(GlobalTransform.Translation, camera.Position, Vector3.UnitY, null, null);
                worldRot.Translation = worldRot.Translation + distortion;
                effect.World         = worldRot;
                break;
            }
            }

            effect.EnableWind = EnableWind;

            foreach (var layer in Layers)
            {
                effect.MainTexture = layer.Sheet.GetTexture();

                if (DrawSilhouette)
                {
                    Color oldTint = effect.VertexColorTint;
                    effect.VertexColorTint           = SilhouetteColor;
                    graphicsDevice.DepthStencilState = DepthStencilState.None;
                    var oldTechnique = effect.CurrentTechnique;
                    effect.CurrentTechnique = effect.Techniques[Shader.Technique.Silhouette];
                    foreach (EffectPass pass in effect.CurrentTechnique.Passes)
                    {
                        pass.Apply();
                        graphicsDevice.DrawUserIndexedPrimitives(PrimitiveType.TriangleList,
                                                                 layer.Verticies, 0, 4, layer.Indicies, 0, 2);
                    }

                    graphicsDevice.DepthStencilState = DepthStencilState.Default;
                    effect.VertexColorTint           = oldTint;
                    effect.CurrentTechnique          = oldTechnique;
                }

                foreach (EffectPass pass in effect.CurrentTechnique.Passes)
                {
                    pass.Apply();
                    graphicsDevice.DrawUserIndexedPrimitives(PrimitiveType.TriangleList,
                                                             layer.Verticies, 0, 4, layer.Indicies, 0, 2);
                }
            }

            effect.VertexColorTint = origTint;
            effect.EnableWind      = false;
            EndDraw(effect);
        }
Exemple #24
0
        public void Update(ParticleManager manager, DwarfTime gameTime, ChunkManager chunks, Camera camera)
        {
            ParticleEmitter._camera = camera;

            List <Particle> toRemove = new List <Particle>();

            TriggerTimer.Update(gameTime);
            if (TriggerTimer.HasTriggered && Data.ParticlesPerFrame > 0)
            {
                Trigger(Data.ParticlesPerFrame, Vector3.Zero, new Color(255, 255, 0));
            }


            bool particlePhysics = GameSettings.Default.ParticlePhysics;

            foreach (Particle p in Particles)
            {
                float vel = p.Velocity.LengthSquared();
                if (Data.EmitsLight && p.Scale > 0.1f)
                {
                    DynamicLight.TempLights.Add(new DynamicLight(10.0f, 255.0f, false)
                    {
                        Position = p.Position
                    });
                }
                p.Position += p.Velocity * (float)gameTime.ElapsedGameTime.TotalSeconds;

                if (Data.RotatesWithVelocity)
                {
                    Vector3 cameraVel   = camera.Project(p.Velocity + camera.Position);
                    float   projectionX = cameraVel.X;
                    float   projectionY = cameraVel.Y;

                    p.Angle = (float)Math.Atan2(projectionY, projectionX);
                }
                else
                {
                    p.Angle += (float)(p.AngularVelocity * gameTime.ElapsedGameTime.TotalSeconds);
                }
                if (!Data.Sleeps || vel > 0.01f)
                {
                    p.Velocity += Data.ConstantAccel * (float)gameTime.ElapsedGameTime.TotalSeconds;
                }
                p.Velocity        *= Data.LinearDamping;
                p.AngularVelocity *= Data.AngularDamping;


                if (!Data.UseManualControl)
                {
                    p.LifeRemaining -= Data.ParticleDecay * (float)gameTime.ElapsedGameTime.TotalSeconds;
                }
                else if (p.TimeAlive > 60)
                {
                    p.LifeRemaining = 0;
                }

                p.Scale += Data.GrowthSpeed * (float)gameTime.ElapsedGameTime.TotalSeconds;

                p.Scale = Math.Max(p.Scale, 0.0f);

                var v = new VoxelHandle(chunks.ChunkData,
                                        GlobalVoxelCoordinate.FromVector3(p.Position));

                if (Data.HasLighting)
                {
                    if (v.IsValid)
                    {
                        p.LightRamp = new Color(v.Sunlight ? 255 : 0, 255, 0);
                    }
                }
                else
                {
                    p.LightRamp = new Color(255, 255, 0);
                }

                if (Data.CollidesWorld && particlePhysics && vel > 0.2f)
                {
                    if (v.IsValid && !v.IsEmpty)
                    {
                        BoundingBox     b       = new BoundingBox(p.Position - Vector3.One * p.Scale * 0.5f, p.Position + Vector3.One * p.Scale * 0.5f);
                        BoundingBox     vBox    = v.GetBoundingBox();
                        Physics.Contact contact = new Physics.Contact();
                        if (Physics.TestStaticAABBAABB(b, vBox, ref contact))
                        {
                            p.Position += contact.NEnter * contact.Penetration;
                            Vector3 newVelocity = Vector3.Reflect(p.Velocity, -contact.NEnter);
                            p.Velocity         = newVelocity * Data.Damping;
                            p.AngularVelocity *= 0.5f;
                            if (Data.Sleeps)
                            {
                                p.Velocity        = Vector3.Zero;
                                p.AngularVelocity = 0.0f;
                                vel = 0.0f;
                            }
                            if (!String.IsNullOrEmpty(Data.SpatterType))
                            {
                                var above = VoxelHelpers.GetVoxelAbove(v);
                                if (!above.IsValid || above.IsEmpty)
                                {
                                    float x = MathFunctions.Clamp(p.Position.X, vBox.Min.X + 0.1f, vBox.Max.X - 0.1f);
                                    float z = MathFunctions.Clamp(p.Position.Z, vBox.Min.Z + 0.1f, vBox.Max.Z - 0.1f);
                                    manager.Create(Data.SpatterType,
                                                   VertexNoise.Warp(new Vector3(x, v.RampType == RampType.None ? v.WorldPosition.Y + 1.02f : v.WorldPosition.Y + 0.6f, z)), Vector3.Zero, Color.White, Vector3.Up);
                                }
                                else
                                {
                                    manager.Create(Data.SpatterType, p.Position - contact.NEnter * contact.Penetration * 0.95f, Vector3.Zero, Color.White, contact.NEnter);
                                }
                                p.LifeRemaining = -1.0f;
                            }
                        }
                    }
                }

                if (p.LifeRemaining < 0)
                {
                    if (p.InstanceData != null)
                    {
                        p.InstanceData.ShouldDraw = false;
                        p.InstanceData.Transform  = Matrix.CreateTranslation(camera.Position + new Vector3(-1000, -1000, -1000));
                        Sprites[p.Frame].Remove(p.InstanceData);
                    }

                    toRemove.Add(p);
                }

                else if (p.InstanceData != null)
                {
                    p.TimeAlive += (float)gameTime.ElapsedGameTime.TotalSeconds + MathFunctions.Rand() * 0.01f;
                    int prevFrame = p.Frame;
                    int newFrame  = AnimPlayer.GetFrame(p.TimeAlive);
                    if (vel < 0.2f)
                    {
                        newFrame = prevFrame;
                    }
                    if (newFrame != prevFrame)
                    {
                        p.Frame = newFrame;
                        if (Sprites.Count > 0)
                        {
                            Sprites[prevFrame].Remove(p.InstanceData);
                            Sprites[newFrame].Add(p.InstanceData);
                        }
                        if (/*!Data.Animation.Loops && */ p.Frame == Data.Animation.Frames.Count - 1)
                        {
                            p.LifeRemaining *= 0.1f;
                        }
                    }
                    p.InstanceData.ShouldDraw = true;
                    p.InstanceData.Transform  = MatrixFromParticle(Data, p);
                    p.InstanceData.LightRamp  = p.LightRamp;
                }
            }

            foreach (Particle p in toRemove)
            {
                Particles.Remove(p);
            }


            foreach (var sprites in Sprites)
            {
                sprites.Update(gameTime, camera, GameState.Game.GraphicsDevice, chunks.World.Master.MaxViewingLevel);
            }
        }
Exemple #25
0
        public static void GenerateRoomComponentsTemplate(Room room, ComponentManager componentManager, Microsoft.Xna.Framework.Content.ContentManager content, GraphicsDevice graphics)
        {
            RoomTile[,] currentTiles = RoomTemplate.CreateFromRoom(room, room.Chunks);
            float[,] rotations       = new float[currentTiles.GetLength(0), currentTiles.GetLength(1)];
            foreach (RoomTemplate template in room.RoomData.Templates)
            {
                for (int r = -2; r < currentTiles.GetLength(0) + 1; r++)
                {
                    for (int c = -2; c < currentTiles.GetLength(1) + 1; c++)
                    {
                        for (int rotation = 0; rotation < 5; rotation++)
                        {
                            if (MathFunctions.RandEvent(template.Probability))
                            {
                                template.PlaceTemplate(ref currentTiles, ref rotations, r, c);
                                template.RotateClockwise(1);
                            }
                        }
                    }
                }
            }

            BoundingBox box = room.GetBoundingBox();

            int thingsMade = 0;

            for (int r = 0; r < currentTiles.GetLength(0); r++)
            {
                for (int c = 0; c < currentTiles.GetLength(1); c++)
                {
                    RoomTile tile             = currentTiles[r, c];
                    Body     createdComponent = null;
                    Vector3  noise            =
                        VertexNoise.GetNoiseVectorFromRepeatingTexture(box.Min +
                                                                       new Vector3(r + 0.5f - 1, 1.5f, c + 0.5f - 1));
                    switch (tile)
                    {
                    case RoomTile.Wheat:
                        createdComponent = EntityFactory.CreateEntity <Body>("Wheat", box.Min + new Vector3(r + 0.5f - 1, 1.5f, c + 0.5f - 1) + noise);
                        thingsMade++;
                        break;

                    case RoomTile.Mushroom:
                        createdComponent = EntityFactory.CreateEntity <Body>("Mushroom", box.Min + new Vector3(r + 0.5f - 1, 1.5f, c + 0.5f - 1) + noise);
                        thingsMade++;
                        break;

                    case RoomTile.Table:
                        createdComponent = EntityFactory.CreateEntity <Body>("Table", box.Min + new Vector3(r + 0.5f - 1, 1.5f, c + 0.5f - 1) + noise);
                        thingsMade++;
                        break;

                    case RoomTile.Lamp:
                        createdComponent = EntityFactory.CreateEntity <Body>("Lamp", box.Min + new Vector3(r + 0.5f - 1, 1.5f, c + 0.5f - 1) + noise);
                        thingsMade++;
                        break;

                    case RoomTile.Flag:
                        createdComponent = EntityFactory.CreateEntity <Body>("Flag", box.Min + new Vector3(r + 0.5f - 1, 1.5f, c + 0.5f - 1) + noise);
                        thingsMade++;
                        break;

                    case RoomTile.Chair:
                        createdComponent = EntityFactory.CreateEntity <Body>("Chair", box.Min + new Vector3(r + 0.5f - 1, 1.5f, c + 0.5f - 1) + noise);
                        thingsMade++;
                        break;

                    case RoomTile.BookTable:
                        createdComponent = EntityFactory.CreateEntity <Body>(MathFunctions.RandEvent(0.5f) ? "BookTable" : "PotionTable", box.Min + new Vector3(r + 0.5f - 1, 1.5f, c + 0.5f - 1) + noise);
                        thingsMade++;
                        break;

                    case RoomTile.Anvil:
                        createdComponent = EntityFactory.CreateEntity <Body>("Anvil", box.Min + new Vector3(r + 0.5f - 1, 1.5f, c + 0.5f - 1) + noise);
                        thingsMade++;
                        break;

                    case RoomTile.Forge:
                        createdComponent = EntityFactory.CreateEntity <Body>("Forge", box.Min + new Vector3(r + 0.5f - 1, 1.5f, c + 0.5f - 1) + noise);
                        thingsMade++;
                        break;

                    case RoomTile.Target:
                        createdComponent = EntityFactory.CreateEntity <Body>("Target", box.Min + new Vector3(r + 0.5f - 1, 1.5f, c + 0.5f - 1) + noise);
                        thingsMade++;
                        break;

                    case RoomTile.Strawman:
                        createdComponent = EntityFactory.CreateEntity <Body>("Strawman", box.Min + new Vector3(r + 0.5f - 1, 1.5f, c + 0.5f - 1) + noise);
                        thingsMade++;
                        break;

                    case RoomTile.BookShelf:
                        createdComponent = EntityFactory.CreateEntity <Body>("Bookshelf", box.Min + new Vector3(r - 1 + 0.5f, 1.5f, c - 1 + 0.5f) + noise);
                        thingsMade++;
                        break;

                    case RoomTile.Pillow:

                        for (int dx = -1; dx < 2; dx++)
                        {
                            for (int dy = -1; dy < 2; dy++)
                            {
                                if (Math.Abs(dx) + Math.Abs(dy) != 1 || r + dx < 0 || r + dx >= currentTiles.GetLength(0) || c + dy < 0 || c + dy >= currentTiles.GetLength(1))
                                {
                                    continue;
                                }

                                if (currentTiles[r + dx, c + dy] != RoomTile.Bed)
                                {
                                    continue;
                                }

                                createdComponent = EntityFactory.CreateEntity <Body>("Bed", box.Min + new Vector3(r - 1 + 0.5f, 1.5f, c - 1 + 0.5f) + noise);

                                /*
                                 * float angle = (float) Math.Atan2(dx, dy);
                                 *
                                 * Vector3 translation = createdComponent.LocalTransform.Translation;
                                 * Matrix bedRotation = Matrix.CreateRotationY(angle);
                                 * createdComponent.LocalTransform = Matrix.CreateTranslation(new Vector3(-0.5f, 0, -0.5f)) * bedRotation * Matrix.CreateTranslation(new Vector3(0.5f, 0, 0.5f)) * Matrix.CreateTranslation(translation);
                                 * createdComponent.BoundingBoxPos = Vector3.Transform(createdComponent.BoundingBoxPos, bedRotation);
                                 * createdComponent.BoundingBox.Min = Vector3.Transform(createdComponent.BoundingBox.Min - translation, bedRotation) + translation;
                                 * createdComponent.BoundingBox.Max = Vector3.Transform(createdComponent.BoundingBox.Max - translation, bedRotation) + translation;
                                 */
                                break;
                            }
                        }


                        thingsMade++;
                        break;

                    default:
                        break;
                    }

                    if (createdComponent != null)
                    {
                        createdComponent.LocalTransform = Matrix.CreateRotationY(-(rotations[r, c] + (float)Math.PI * 0.5f)) * createdComponent.LocalTransform;
                        Vector3 endPos          = createdComponent.LocalTransform.Translation;
                        Matrix  offsetTransform = createdComponent.LocalTransform;
                        offsetTransform.Translation    += new Vector3(0, -1, 0);
                        createdComponent.LocalTransform = offsetTransform;
                        createdComponent.AnimationQueue.Add(new EaseMotion(0.8f, offsetTransform, endPos));
                        room.AddBody(createdComponent);
                        PlayState.ParticleManager.Trigger("puff", endPos + new Vector3(0.5f, 0.5f, 0.5f), Color.White, 10);
                    }
                }
            }
        }
        private static void BuildVoxelTopFaceGeometry(
            RawPrimitive Into,
            VoxelChunk Chunk,
            Cache Cache,
            BoxPrimitive Primitive,
            VoxelHandle V,
            BoxPrimitive.BoxTextureCoords UVs,
            int i)
        {
            var face  = (BoxFace)i;
            var delta = FaceDeltas[i];

            var faceVoxel = new VoxelHandle(Chunk.Manager, V.Coordinate + GlobalVoxelOffset.FromVector3(delta));

            if (!IsFaceVisible(V, faceVoxel, face))
            {
                return;
            }

            var faceDescriptor = Primitive.GetFace(face);
            int exploredVerts  = 0;
            var vertexColors   = new VertexColorInfo[4];
            var vertexTint     = new Color[4];

            // Find all verticies to use for geometry later, and for the fringe
            var vertexPositions = new Vector3[4];

            for (int faceVertex = 0; faceVertex < faceDescriptor.VertexCount; faceVertex++)
            {
                var vertex      = Primitive.Vertices[faceDescriptor.VertexOffset + faceVertex];
                var voxelVertex = Primitive.Deltas[faceDescriptor.VertexOffset + faceVertex];

                var rampOffset = Vector3.Zero;
                if (V.IsExplored && V.Type.CanRamp && ShouldRamp(voxelVertex, V.RampType))
                {
                    rampOffset = new Vector3(0, -V.Type.RampSize, 0);
                }

                var worldPosition = V.WorldPosition + vertex.Position + rampOffset;
                //worldPosition += VertexNoise.GetNoiseVectorFromRepeatingTexture(worldPosition);

                vertexPositions[faceVertex] = worldPosition;
            }

            if (V.IsExplored)
            {
                exploredVerts = 4;
            }
            else
            {
                for (int faceVertex = 0; faceVertex < faceDescriptor.VertexCount; ++faceVertex)
                {
                    var  voxelVertex         = Primitive.Deltas[faceDescriptor.VertexOffset + faceVertex];
                    var  cacheKey            = GetCacheKey(V, voxelVertex);
                    bool anyNeighborExplored = true;

                    if (!Cache.ExploredCache.TryGetValue(cacheKey, out anyNeighborExplored))
                    {
                        anyNeighborExplored = VoxelHelpers.EnumerateVertexNeighbors2D(V.Coordinate, voxelVertex)
                                              .Select(c => new VoxelHandle(V.Chunk.Manager, c))
                                              .Any(n => n.IsValid && n.IsExplored);
                        Cache.ExploredCache.Add(cacheKey, anyNeighborExplored);
                    }


                    if (anyNeighborExplored)
                    {
                        exploredVerts += 1;
                    }
                }
            }

            for (int faceVertex = 0; faceVertex < faceDescriptor.VertexCount; ++faceVertex)
            {
                var voxelVertex = Primitive.Deltas[faceDescriptor.VertexOffset + faceVertex];
                var cacheKey    = GetCacheKey(V, voxelVertex);

                VertexColorInfo vertexColor;
                if (!Cache.LightCache.TryGetValue(cacheKey, out vertexColor))
                {
                    vertexColor = CalculateVertexLight(V, voxelVertex, Chunk.Manager);
                    Cache.LightCache.Add(cacheKey, vertexColor);
                }

                vertexColors[faceVertex] = vertexColor;

                vertexTint[faceVertex] = new Color(1.0f, 1.0f, 1.0f, 1.0f);
                if (exploredVerts != 4)
                {
                    bool anyNeighborExplored = true;
                    if (!Cache.ExploredCache.TryGetValue(cacheKey, out anyNeighborExplored))
                    {
                        throw new InvalidProgramException("Failed cache lookup");
                    }

                    if (!anyNeighborExplored)
                    {
                        vertexTint[faceVertex] = new Color(0.0f, 0.0f, 0.0f, 1.0f);
                    }
                }

                vertexTint[faceVertex] = new Color(vertexTint[faceVertex].ToVector4() * V.Type.Tint.ToVector4());
            }

            if (exploredVerts != 0)
            {
                var baseUVs = UVs.Uvs[11]; // EW

                var baseUVBounds = new Vector4(baseUVs.X + 0.001f, baseUVs.Y + 0.001f, baseUVs.X + (1.0f / 16.0f) - 0.001f, baseUVs.Y + (1.0f / 16.0f) - 0.001f);

                // Draw central top tile.
                AddTopFaceGeometry(Into,
                                   Cache.AmbientValues, Primitive,
                                   faceDescriptor,
                                   vertexPositions,
                                   vertexColors,
                                   vertexTint,
                                   Vector2.One,
                                   baseUVs, baseUVBounds);

                if (V.GrassType != 0)
                {
                    BuildGrassFringeGeometry(Into, Chunk, Cache, Primitive, V, vertexColors,
                                             vertexTint, vertexPositions, faceDescriptor, exploredVerts);
                }
            }
            else
            {
                if (!Debugger.Switches.HideSliceTop)
                {
                    var indexOffset = Into.VertexCount;

                    for (int faceVertex = 0; faceVertex < faceDescriptor.VertexCount; faceVertex++)
                    {
                        Into.AddVertex(new ExtendedVertex(
                                           vertexPositions[faceVertex] + VertexNoise.GetNoiseVectorFromRepeatingTexture(vertexPositions[faceVertex]),
                                           new Color(0, 0, 0, 255),
                                           new Color(0, 0, 0, 255),
                                           new Vector2(12.5f / 16.0f, 0.5f / 16.0f),
                                           new Vector4(12.0f / 16.0f, 0.0f, 13.0f / 16.0f, 1.0f / 16.0f)));
                    }

                    for (int idx = faceDescriptor.IndexOffset; idx < faceDescriptor.IndexCount +
                         faceDescriptor.IndexOffset; idx++)
                    {
                        ushort offset  = Primitive.Indexes[idx];
                        ushort offset0 = Primitive.Indexes[faceDescriptor.IndexOffset];
                        Into.AddIndex((short)(indexOffset + offset - offset0));
                    }
                }
            }
        }
        public void InitializeFromChunk(VoxelChunk chunk, GraphicsDevice graphics)
        {
            //chunk.PrimitiveMutex.WaitOne();
            if (!chunk.IsVisible || IsBuilding)
            {
                // chunk.PrimitiveMutex.ReleaseMutex();
                return;
            }

            IsBuilding = true;
            //chunk.PrimitiveMutex.ReleaseMutex();

            accumulatedVertices.Clear();
            faceExists.Clear();
            drawFace.Clear();

            int[,,] totalDepth = new int[chunk.SizeX, chunk.SizeY, chunk.SizeZ];
            for (int x = 0; x < chunk.SizeX; x++)
            {
                for (int z = 0; z < chunk.SizeZ; z++)
                {
                    bool drynessEncountered = false;
                    int  previousSum        = 0;

                    for (int y = 0; y < chunk.SizeY; y++)
                    {
                        WaterCell cell       = chunk.Data.Water[chunk.Data.IndexAt(x, y, z)];
                        byte      waterLevel = cell.WaterLevel;

                        if (cell.Type != LiqType)
                        {
                            waterLevel = 0;
                        }

                        if (drynessEncountered)
                        {
                            if (waterLevel > 0)
                            {
                                drynessEncountered  = false;
                                previousSum        += waterLevel;
                                totalDepth[x, y, z] = previousSum;
                            }
                        }
                        else
                        {
                            if (waterLevel > 0)
                            {
                                previousSum        += waterLevel;
                                totalDepth[x, y, z] = previousSum;
                            }
                            else
                            {
                                drynessEncountered  = true;
                                previousSum         = 0;
                                totalDepth[x, y, z] = 0;
                            }
                        }
                    }
                }
            }

            int maxY = chunk.SizeY;

            if (chunk.Manager.ChunkData.Slice == ChunkManager.SliceMode.Y)
            {
                maxY = (int)Math.Min(chunk.Manager.ChunkData.MaxViewingLevel + 1, chunk.SizeY);
            }


            Voxel myVoxel = chunk.MakeVoxel(0, 0, 0);
            Voxel vox     = chunk.MakeVoxel(0, 0, 0);

            for (int x = 0; x < chunk.SizeX; x++)
            {
                for (int y = 0; y < maxY; y++)
                {
                    for (int z = 0; z < chunk.SizeZ; z++)
                    {
                        int index = chunk.Data.IndexAt(x, y, z);
                        if (chunk.Data.Water[index].WaterLevel > 0 && chunk.Data.Water[index].Type == LiqType)
                        {
                            bool isTop = false;

                            myVoxel.GridPosition = new Vector3(x, y, z);

                            for (int i = 0; i < 6; i++)
                            {
                                BoxFace face = (BoxFace)i;
                                if (face == BoxFace.Bottom)
                                {
                                    continue;
                                }

                                Vector3 delta = faceDeltas[face];


                                bool success = chunk.Manager.ChunkData.GetVoxel(chunk, new Vector3(x + (int)delta.X, y + (int)delta.Y, z + (int)delta.Z) + chunk.Origin, ref vox);

                                if (success)
                                {
                                    if (face == BoxFace.Top)
                                    {
                                        if (vox.WaterLevel == 0 || y == (int)chunk.Manager.ChunkData.MaxViewingLevel)
                                        {
                                            drawFace[face] = true;
                                        }
                                        else
                                        {
                                            drawFace[face] = false;
                                        }
                                    }
                                    else
                                    {
                                        if (vox.WaterLevel == 0 && vox.IsEmpty)
                                        {
                                            drawFace[face] = true;
                                        }
                                        else
                                        {
                                            drawFace[face] = false;
                                        }

                                        bool gotVox = chunk.Manager.ChunkData.GetVoxel(chunk, new Vector3(x, y + 1, z) + chunk.Origin, ref vox);

                                        isTop = !gotVox || vox.IsEmpty || vox.WaterLevel == 0;
                                    }
                                }
                                else
                                {
                                    drawFace[face] = true;
                                }


                                if (!drawFace[face])
                                {
                                    continue;
                                }

                                IEnumerable <ExtendedVertex> vertices = CreateWaterFace(myVoxel, face, chunk, x, y, z, totalDepth[x, y, z], isTop);


                                foreach (ExtendedVertex newVertex in vertices.Select(vertex => new ExtendedVertex(vertex.Position + VertexNoise.GetRandomNoiseVector(vertex.Position),
                                                                                                                  vertex.Color, vertex.VertColor, vertex.TextureCoordinate, vertex.TextureBounds)))
                                {
                                    accumulatedVertices.Add(newVertex);
                                }
                            }
                        }
                    }
                }
            }


            try
            {
                ExtendedVertex[] vertex = new ExtendedVertex[accumulatedVertices.Count];

                for (int i = 0; i < accumulatedVertices.Count; i++)
                {
                    vertex[i] = accumulatedVertices[i];
                }


                Vertices = vertex;

                chunk.PrimitiveMutex.WaitOne();
                ResetBuffer(graphics);
                chunk.PrimitiveMutex.ReleaseMutex();
            }
            catch (System.Threading.AbandonedMutexException e)
            {
                Console.Error.WriteLine(e.Message);
            }

            IsBuilding = false;
        }
Exemple #28
0
        private static void CreateWaterFaces(
            VoxelHandle voxel,
            VoxelChunk chunk,
            int x, int y, int z,
            ExtendedVertex[] vertices,
            ushort[] Indexes,
            int startVertex,
            int startIndex)
        {
            // Reset the appropriate parts of the cache.
            cache.Reset();

            // These are reused for every face.
            var   origin           = voxel.WorldPosition;
            float centerWaterlevel = voxel.LiquidLevel;

            var  below       = VoxelHelpers.GetVoxelBelow(voxel);
            bool belowFilled = false;
            bool belowLiquid = below.IsValid && below.LiquidLevel > 0;
            bool belowRamps  = below.IsValid && below.RampType != RampType.None;

            if ((below.IsValid && !below.IsEmpty) || belowLiquid)
            {
                belowFilled = true;
            }

            float[] foaminess = new float[4];

            for (int i = 0; i < cache.drawFace.Length; i++)
            {
                if (!cache.drawFace[i])
                {
                    continue;
                }
                BoxFace face = (BoxFace)i;

                var faceDescriptor = primitive.GetFace(face);
                int indexOffset    = startVertex;

                for (int vertOffset = 0; vertOffset < faceDescriptor.VertexCount; vertOffset++)
                {
                    VoxelVertex currentVertex = primitive.Deltas[faceDescriptor.VertexOffset + vertOffset];

                    // These will be filled out before being used   lh  .
                    //float foaminess1;
                    foaminess[vertOffset] = 0.0f;
                    bool shoreLine = false;

                    Vector3 pos        = Vector3.Zero;
                    Vector3 rampOffset = Vector3.Zero;
                    var     uv         = primitive.UVs.Uvs[vertOffset + faceDescriptor.VertexOffset];
                    // We are going to have to reuse some vertices when drawing a single so we'll store the position/foaminess
                    // for quick lookup when we find one of those reused ones.
                    // When drawing multiple faces the Vertex overlap gets bigger, which is a bonus.
                    if (!cache.vertexCalculated[(int)currentVertex])
                    {
                        float count             = 1.0f;
                        float emptyNeighbors    = 0.0f;
                        float averageWaterLevel = centerWaterlevel;

                        var vertexSucc = VoxelHelpers.VertexNeighbors[(int)currentVertex];

                        // Run through the successors and count up the water in each voxel.
                        for (int v = 0; v < vertexSucc.Length; v++)
                        {
                            var neighborVoxel = new VoxelHandle(chunk.Manager, voxel.Coordinate + vertexSucc[v]);
                            if (!neighborVoxel.IsValid)
                            {
                                continue;
                            }

                            // Now actually do the math.
                            count++;
                            if (neighborVoxel.LiquidLevel < 1)
                            {
                                emptyNeighbors++;
                            }
                            if (neighborVoxel.LiquidType == LiquidType.None && !neighborVoxel.IsEmpty)
                            {
                                shoreLine = true;
                            }
                        }

                        foaminess[vertOffset] = emptyNeighbors / count;

                        if (foaminess[vertOffset] <= 0.5f)
                        {
                            foaminess[vertOffset] = 0.0f;
                        }
                        // Check if it should ramp.
                        else if (!shoreLine)
                        {
                            //rampOffset.Y = -0.4f;
                        }

                        pos = primitive.Vertices[vertOffset + faceDescriptor.VertexOffset].Position;
                        if ((currentVertex & VoxelVertex.Top) == VoxelVertex.Top)
                        {
                            if (belowFilled)
                            {
                                pos.Y -= 0.6f;// Minimum ramp position
                            }
                            var neighbors = VoxelHelpers.EnumerateVertexNeighbors2D(voxel.Coordinate, currentVertex)
                                            .Select(c => new VoxelHandle(chunk.Manager, c))
                                            .Where(h => h.IsValid)
                                            .Select(h => MathFunctions.Clamp((float)h.LiquidLevel / 8.0f, 0.25f, 1.0f));

                            if (neighbors.Count() > 0)
                            {
                                if (belowFilled)
                                {
                                    pos.Y *= neighbors.Average();
                                }
                            }
                        }
                        else
                        {
                            uv.Y -= 0.6f;
                        }

                        pos += VertexNoise.GetNoiseVectorFromRepeatingTexture(voxel.WorldPosition +
                                                                              primitive.Vertices[vertOffset + faceDescriptor.VertexOffset].Position);

                        if (!belowFilled)
                        {
                            pos = (pos - Vector3.One * 0.5f);
                            pos.Normalize();
                            pos *= 0.35f;
                            pos += Vector3.One * 0.5f;
                        }
                        else if ((belowLiquid || belowRamps) && IsBottom(currentVertex))
                        {
                            if (belowRamps)
                            {
                                pos -= Vector3.Up * 0.5f;
                            }
                            else
                            {
                                pos -= Vector3.Up * 0.8f;
                            }
                        }

                        pos += origin + rampOffset;
                        // Store the vertex information for future use when we need it again on this or another face.
                        cache.vertexCalculated[(int)currentVertex] = true;
                        cache.vertexFoaminess[(int)currentVertex]  = foaminess[vertOffset];
                        cache.vertexPositions[(int)currentVertex]  = pos;
                    }
                    else
                    {
                        // We've already calculated this one.  Time for a cheap grab from the lookup.
                        foaminess[vertOffset] = cache.vertexFoaminess[(int)currentVertex];
                        pos = cache.vertexPositions[(int)currentVertex];
                    }

                    vertices[startVertex].Set(pos,
                                              new Color(foaminess[vertOffset], 0.0f, 1.0f, 1.0f),
                                              Color.White,
                                              uv,
                                              new Vector4(0, 0, 1, 1));

                    startVertex++;
                }

                bool flippedQuad = foaminess[1] + foaminess[3] >
                                   foaminess[0] + foaminess[2];

                for (int idx = faceDescriptor.IndexOffset; idx < faceDescriptor.IndexCount + faceDescriptor.IndexOffset; idx++)
                {
                    ushort offset  = flippedQuad ? primitive.FlippedIndexes[idx] : primitive.Indexes[idx];
                    ushort offset0 = flippedQuad ? primitive.FlippedIndexes[faceDescriptor.IndexOffset] : primitive.Indexes[faceDescriptor.IndexOffset];

                    Indexes[startIndex] = (ushort)(indexOffset + offset - offset0);
                    startIndex++;
                }
            }
            // End cache.drawFace loop
        }
Exemple #29
0
        public void InitializeFromChunk(VoxelChunk chunk, GraphicsDevice graphics)
        {
            if (chunk == null)
            {
                return;
            }

            rebuildMutex.WaitOne();
            if (isRebuilding)
            {
                rebuildMutex.ReleaseMutex();
                return;
            }

            isRebuilding = true;
            rebuildMutex.ReleaseMutex();


            accumulatedVertices.Clear();
            accumulatedIndices.Clear();
            faceExists.Clear();
            drawFace.Clear();

            Voxel v           = chunk.MakeVoxel(0, 0, 0);
            Voxel voxelOnFace = chunk.MakeVoxel(0, 0, 0);

            Voxel[] manhattanNeighbors = new Voxel[4];
            for (int x = 0; x < chunk.SizeX; x++)
            {
                for (int y = 0; y < Math.Min(chunk.Manager.ChunkData.MaxViewingLevel + 1, chunk.SizeY); y++)
                {
                    for (int z = 0; z < chunk.SizeZ; z++)
                    {
                        v.GridPosition = new Vector3(x, y, z);


                        if (v.IsEmpty || !v.IsVisible)
                        {
                            continue;
                        }

                        BoxPrimitive primitive = VoxelLibrary.GetPrimitive(v.Type);

                        if (primitive == null)
                        {
                            continue;
                        }

                        BoxPrimitive.BoxTextureCoords uvs = primitive.UVs;

                        if (v.Type.HasTransitionTextures)
                        {
                            uvs = v.ComputeTransitionTexture(manhattanNeighbors);
                        }


                        Voxel worldVoxel = new Voxel();
                        for (int i = 0; i < 6; i++)
                        {
                            BoxFace face  = (BoxFace)i;
                            Vector3 delta = FaceDeltas[face];
                            faceExists[face] = chunk.IsCellValid(x + (int)delta.X, y + (int)delta.Y, z + (int)delta.Z);
                            drawFace[face]   = true;

                            if (faceExists[face])
                            {
                                voxelOnFace.GridPosition = new Vector3(x + (int)delta.X, y + (int)delta.Y, z + (int)delta.Z);
                                drawFace[face]           = voxelOnFace.IsEmpty || !voxelOnFace.IsVisible || (voxelOnFace.Type.CanRamp && voxelOnFace.RampType != RampType.None && IsSideFace(face) && ShouldDrawFace(face, voxelOnFace.RampType, v.RampType));
                            }
                            else
                            {
                                bool success = chunk.Manager.ChunkData.GetNonNullVoxelAtWorldLocation(new Vector3(x + (int)delta.X, y + (int)delta.Y, z + (int)delta.Z) + chunk.Origin, ref worldVoxel);
                                drawFace[face] = !success || worldVoxel.IsEmpty || !worldVoxel.IsVisible || (worldVoxel.Type.CanRamp && worldVoxel.RampType != RampType.None && IsSideFace(face) && ShouldDrawFace(face, worldVoxel.RampType, v.RampType));
                            }
                        }


                        for (int i = 0; i < 6; i++)
                        {
                            BoxFace face = (BoxFace)i;
                            if (!drawFace[face])
                            {
                                continue;
                            }
                            int faceIndex   = 0;
                            int faceCount   = 0;
                            int vertexIndex = 0;
                            int vertexCount = 0;
                            primitive.GetFace(face, uvs, out faceIndex, out faceCount, out vertexIndex, out vertexCount);
                            Vector2 texScale = uvs.Scales[i];

                            int indexOffset = accumulatedVertices.Count;
                            for (int vertOffset = 0; vertOffset < vertexCount; vertOffset++)
                            {
                                ExtendedVertex vert      = primitive.Vertices[vertOffset + vertexIndex];
                                VoxelVertex    bestKey   = VoxelChunk.GetNearestDelta(vert.Position);
                                Color          color     = v.Chunk.Data.GetColor(x, y, z, bestKey);
                                Vector3        offset    = Vector3.Zero;
                                Vector2        texOffset = Vector2.Zero;

                                if (v.Type.CanRamp && ShouldRamp(bestKey, v.RampType))
                                {
                                    offset = new Vector3(0, -v.Type.RampSize, 0);

                                    if (face != BoxFace.Top && face != BoxFace.Bottom)
                                    {
                                        texOffset = new Vector2(0, v.Type.RampSize * (texScale.Y));
                                    }
                                }


                                ExtendedVertex newVertex = new ExtendedVertex((vert.Position + v.Position + VertexNoise.GetNoiseVectorFromRepeatingTexture(vert.Position + v.Position) + offset),
                                                                              color,
                                                                              uvs.Uvs[vertOffset + vertexIndex] + texOffset, uvs.Bounds[faceIndex / 6]);
                                accumulatedVertices.Add(newVertex);
                            }

                            for (int idx = faceIndex; idx < faceCount + faceIndex; idx++)
                            {
                                int vertexOffset = primitive.Indices[idx];
                                accumulatedIndices.Add((short)(indexOffset + (vertexOffset - primitive.Indices[faceIndex])));
                            }
                        }
                    }
                }
            }


            Vertices = new ExtendedVertex[accumulatedVertices.Count];
            accumulatedVertices.CopyTo(Vertices);
            IndexBuffer = new IndexBuffer(graphics, typeof(short), accumulatedIndices.Count, BufferUsage.WriteOnly);
            IndexBuffer.SetData(accumulatedIndices.ToArray());

            ResetBuffer(graphics);
            isRebuilding = false;

            //chunk.PrimitiveMutex.WaitOne();
            chunk.NewPrimitive         = this;
            chunk.NewPrimitiveReceived = true;
            //chunk.PrimitiveMutex.ReleaseMutex();
        }
        private static void BuildVoxelFaceGeometry(
            RawPrimitive Into,
            VoxelChunk Chunk,
            Cache Cache,
            BoxPrimitive Primitive,
            VoxelHandle V,
            Color Tint,
            BoxPrimitive.BoxTextureCoords UVs,
            Matrix VertexTransform,
            int i,
            bool ApplyLighting)
        {
            var face  = (BoxFace)i;
            var delta = FaceDeltas[i];

            var faceVoxel = new VoxelHandle(Chunk.Manager, V.Coordinate + GlobalVoxelOffset.FromVector3(delta));

            if (!IsFaceVisible(V, faceVoxel, face))
            {
                return;
            }

            var faceDescriptor = Primitive.GetFace(face);
            var indexOffset    = Into.VertexCount;

            for (int faceVertex = 0; faceVertex < faceDescriptor.VertexCount; faceVertex++)
            {
                var vertex      = Primitive.Vertices[faceDescriptor.VertexOffset + faceVertex];
                var voxelVertex = Primitive.Deltas[faceDescriptor.VertexOffset + faceVertex];
                var vertexColor = new VertexColorInfo
                {
                    SunColor     = 255,
                    AmbientColor = 255,
                    DynamicColor = 255,
                };

                if (ApplyLighting)
                {
                    var cacheKey = GetCacheKey(V, voxelVertex);

                    if (!Cache.LightCache.TryGetValue(cacheKey, out vertexColor))
                    {
                        vertexColor = CalculateVertexLight(V, voxelVertex, Chunk.Manager);
                        Cache.LightCache.Add(cacheKey, vertexColor);
                    }

                    Cache.AmbientValues[faceVertex] = vertexColor.AmbientColor;
                }

                var rampOffset = Vector3.Zero;
                if (V.IsExplored && V.Type.CanRamp && ShouldRamp(voxelVertex, V.RampType))
                {
                    rampOffset = new Vector3(0, -V.Type.RampSize, 0);
                }

                var baseWorldPosition = V.WorldPosition + vertex.Position + rampOffset;
                var noise             = VertexNoise.GetNoiseVectorFromRepeatingTexture(baseWorldPosition);
                var localPosition     = Vector3.Transform(vertex.Position + rampOffset + noise, VertexTransform);

                Into.AddVertex(new ExtendedVertex(
                                   V.WorldPosition + localPosition,
                                   vertexColor.AsColor(),
                                   Tint,
                                   UVs.Uvs[faceDescriptor.VertexOffset + faceVertex],
                                   UVs.Bounds[faceDescriptor.IndexOffset / 6]));
            }

            bool flippedQuad = ApplyLighting && (Cache.AmbientValues[0] + Cache.AmbientValues[2] >
                                                 Cache.AmbientValues[1] + Cache.AmbientValues[3]);

            for (int idx = faceDescriptor.IndexOffset; idx < faceDescriptor.IndexCount +
                 faceDescriptor.IndexOffset; idx++)
            {
                ushort offset  = flippedQuad ? Primitive.FlippedIndexes[idx] : Primitive.Indexes[idx];
                ushort offset0 = flippedQuad ? Primitive.FlippedIndexes[faceDescriptor.IndexOffset] : Primitive.Indexes[faceDescriptor.IndexOffset];
                Into.AddIndex((short)(indexOffset + offset - offset0));
            }
        }