Drew DeVault 8fe7329135 Start moving client towards a more refined design
I'm splitting up core pieces of functionality into several smaller
modules. TrueCraftGame will be made smaller and smaller until it's just
a small wrapper around the modules doing all of the work. This should
allow for modders to easily add new modules or replace builtin modules,
and will make the codebase more maintainable in general.
2015-09-24 21:20:36 -04:00

127 lines
4.8 KiB
C#

using System;
using TrueCraft.Client.Rendering;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.ComponentModel;
using TrueCraft.API;
namespace TrueCraft.Client.Modules
{
public class ChunkModule : IGraphicalModule
{
public TrueCraftGame Game { get; set; }
public ChunkRenderer ChunkRenderer { get; set; }
private List<Mesh> ChunkMeshes { get; set; }
private ConcurrentBag<Mesh> IncomingChunks { get; set; }
private BasicEffect OpaqueEffect { get; set; }
private AlphaTestEffect TransparentEffect { get; set; }
public ChunkModule(TrueCraftGame game)
{
Game = game;
ChunkRenderer = new ChunkRenderer(Game.Client.World, Game, Game.BlockRepository);
Game.Client.ChunkLoaded += (sender, e) => ChunkRenderer.Enqueue(e.Chunk);
//Client.ChunkModified += (sender, e) => ChunkRenderer.Enqueue(e.Chunk, true);
ChunkRenderer.MeshCompleted += MeshCompleted;
ChunkRenderer.Start();
OpaqueEffect = new BasicEffect(Game.GraphicsDevice);
OpaqueEffect.EnableDefaultLighting();
OpaqueEffect.DirectionalLight0.SpecularColor = Color.Black.ToVector3();
OpaqueEffect.DirectionalLight1.SpecularColor = Color.Black.ToVector3();
OpaqueEffect.DirectionalLight2.SpecularColor = Color.Black.ToVector3();
OpaqueEffect.TextureEnabled = true;
OpaqueEffect.Texture = Game.TextureMapper.GetTexture("terrain.png");
OpaqueEffect.FogEnabled = true;
OpaqueEffect.FogStart = 512f;
OpaqueEffect.FogEnd = 1000f;
OpaqueEffect.FogColor = Color.CornflowerBlue.ToVector3();
OpaqueEffect.VertexColorEnabled = true;
TransparentEffect = new AlphaTestEffect(Game.GraphicsDevice);
TransparentEffect.AlphaFunction = CompareFunction.Greater;
TransparentEffect.ReferenceAlpha = 127;
TransparentEffect.Texture = Game.TextureMapper.GetTexture("terrain.png");
TransparentEffect.VertexColorEnabled = true;
ChunkMeshes = new List<Mesh>();
IncomingChunks = new ConcurrentBag<Mesh>();
}
void MeshCompleted(object sender, RendererEventArgs<ReadOnlyChunk> e)
{
IncomingChunks.Add(e.Result);
}
void HandleClientPropertyChanged(object sender, PropertyChangedEventArgs e)
{
switch (e.PropertyName)
{
case "Position":
var sorter = new ChunkRenderer.ChunkSorter(new Coordinates3D(
(int)Game.Client.Position.X, 0, (int)Game.Client.Position.Z));
Game.PendingMainThreadActions.Add(() => ChunkMeshes.Sort(sorter));
break;
}
}
public void Update(GameTime gameTime)
{
Mesh mesh;
while (IncomingChunks.TryTake(out mesh))
{
ChunkMeshes.Add(mesh);
}
}
private static readonly BlendState ColorWriteDisable = new BlendState()
{
ColorWriteChannels = ColorWriteChannels.None
};
public void Draw(GameTime gameTime)
{
Game.Camera.ApplyTo(OpaqueEffect);
Game.Camera.ApplyTo(TransparentEffect);
int verticies = 0, chunks = 0;
Game.GraphicsDevice.DepthStencilState = DepthStencilState.Default;
for (int i = 0; i < ChunkMeshes.Count; i++)
{
if (Game.Camera.Frustum.Intersects(ChunkMeshes[i].BoundingBox))
{
verticies += ChunkMeshes[i].GetTotalVertices();
chunks++;
ChunkMeshes[i].Draw(OpaqueEffect, 0);
}
}
Game.GraphicsDevice.BlendState = ColorWriteDisable;
for (int i = 0; i < ChunkMeshes.Count; i++)
{
if (Game.Camera.Frustum.Intersects(ChunkMeshes[i].BoundingBox))
{
if (!ChunkMeshes[i].IsDisposed)
verticies += ChunkMeshes[i].GetTotalVertices();
ChunkMeshes[i].Draw(TransparentEffect, 1);
}
}
Game.GraphicsDevice.BlendState = BlendState.NonPremultiplied;
for (int i = 0; i < ChunkMeshes.Count; i++)
{
if (Game.Camera.Frustum.Intersects(ChunkMeshes[i].BoundingBox))
{
if (!ChunkMeshes[i].IsDisposed)
verticies += ChunkMeshes[i].GetTotalVertices();
ChunkMeshes[i].Draw(TransparentEffect, 1);
}
}
}
}
}