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); }
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)); } } }
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; } }
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."); } }
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(); }
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(); } }
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); }
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); }
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(); } }
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)); } }
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))); } } }
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); }
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)); }
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); } }
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); }
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(); } }
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)); } }
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)); }
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)); } }
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"); }
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); }
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); } }
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; }
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 }
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)); } }