Real time Lighting, Blocks, Chunks, Registries, Blockstates

This commit is contained in:
Halbear
2026-02-11 21:38:12 +00:00
parent 3a2241af11
commit 414e52de9e
3 changed files with 561 additions and 99 deletions

View File

@@ -34,7 +34,7 @@
// //
// Display // Display
// //
this.Display.BackColor = System.Drawing.Color.Aquamarine; this.Display.BackColor = System.Drawing.Color.Black;
this.Display.Location = new System.Drawing.Point(12, 12); this.Display.Location = new System.Drawing.Point(12, 12);
this.Display.Name = "Display"; this.Display.Name = "Display";
this.Display.Size = new System.Drawing.Size(100, 50); this.Display.Size = new System.Drawing.Size(100, 50);

View File

@@ -7,6 +7,7 @@ using System.Drawing;
using System.Drawing.Drawing2D; using System.Drawing.Drawing2D;
using System.Linq; using System.Linq;
using System.Linq.Expressions; using System.Linq.Expressions;
using System.Runtime.InteropServices;
using System.Text; using System.Text;
using System.Threading; using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;
@@ -23,6 +24,8 @@ namespace VoxelIsometricRenderer
public static float scale = 2f; public static float scale = 2f;
public static int FPS = 0; public static int FPS = 0;
public static int Frames = 0; public static int Frames = 0;
public static double TotalRamUsage = 0;
public static double RamUsage = 0;
public Terrain4() public Terrain4()
{ {
InitializeComponent(); InitializeComponent();
@@ -49,36 +52,19 @@ namespace VoxelIsometricRenderer
TextureManager.AddBitmap(Resources.PinkSquare); TextureManager.AddBitmap(Resources.PinkSquare);
TextureManager.AddBitmap(Resources.OrangeSquare); TextureManager.AddBitmap(Resources.OrangeSquare);
TextureManager.AddBitmap(Resources.ColourEdges); TextureManager.AddBitmap(Resources.ColourEdges);
Voxels.Add(new Voxel(0, 0, 0, 0, 0, 0));
Voxels.Add(new Voxel(9, 9, 9, 9, 9, 9));
Voxels.Add(new Voxel(10, 10, 10, 10, 10, 10));
Voxels.Add(new Voxel(11, 11, 11, 11, 11, 11));
Voxels.Add(new Voxel(12, 12, 12, 12, 12, 12));
Voxels.Add(new Voxel(3, 3, 3, 3, 3, 3));
Voxels.Add(new Voxel(1, 1, 1, 1, 2, 3));
Voxels.Add(new Voxel(4, 4, 4, 4, 6, 6));
Voxels.Add(new Voxel(5, 5, 5, 5, 6, 6));
Voxels.Add(new Voxel(7, 7, 7, 7, 7, 7));
Voxels.Add(new Voxel(17, 18, 19, 20, 21, 22));
Voxels.Add(new Voxel(23, 23, 23, 23, 23, 23));
Voxels.Add(new Voxel(17, 18, 19, 20, -1, -1));
Voxels.Add(new Voxel(23, 23, 23, 23, -1, -1));
Voxels.Add(new Voxel(-1, -1, -1, -1, 21, 22));
Voxels.Add(new Voxel(-1, -1, -1, -1, 23, 23));
Voxels.Add(new Voxel(1, 13, 13, 13, 13, -1, -1));
Voxels.Add(new Voxel(1, 14, 14, 14,14, -1, -1));
Voxels.Add(new Voxel(1, 15, 15, 15,15, -1, -1));
Voxels.Add(new Voxel(1, 16, 16, 16,16, -1, -1));
Random rnd = new Random();
for(int i = 0; i < 25; i++)
{
Voxels.Add(new Voxel(rnd.Next(0,TextureManager.textures.Count - 1), rnd.Next(0, TextureManager.textures.Count - 1), rnd.Next(0, TextureManager.textures.Count - 1), rnd.Next(0, TextureManager.textures.Count - 1), rnd.Next(0, TextureManager.textures.Count - 1), rnd.Next(0, TextureManager.textures.Count - 1)));
}
TextureManager.GenerateVoxelFaces(); TextureManager.GenerateVoxelFaces();
for (int i = 0; i < Voxels.Count; i++) Chunk TestChunk = ChunkRegistry.IndexChunk(0, 0, 0);
{ Random rnd = new Random();
//TextureManager.CreateModel(Voxels[i]); for (int i = 0; i < 16; i++) {
for (int j = 0; j < 16; j++) {
for (int k = 0; k < 16; k++) {
if (i < 10 && k < 10 && rnd.Next(0, 3) > 0) TestChunk.CreateBlock(new int[] { rnd.Next(0, 13), rnd.Next(0, 13), rnd.Next(0, 13), rnd.Next(0, 13), rnd.Next(0, 13), rnd.Next(0, 13) }, 0, new BlockState(false, BlockType.Ground, true), i, j, k);
else TestChunk.CreateAir(i, j, k);
} }
}
}
TestChunk.GenerateLightMap();
TestChunk.CalculateCull();
MainThread = new Thread(Runtime); MainThread = new Thread(Runtime);
MainThread.SetApartmentState(ApartmentState.STA); MainThread.SetApartmentState(ApartmentState.STA);
MainThread.Start(); MainThread.Start();
@@ -97,28 +83,16 @@ namespace VoxelIsometricRenderer
{ {
LightingFrameTime = Process.GetCurrentProcess().TotalProcessorTime.TotalMilliseconds; LightingFrameTime = Process.GetCurrentProcess().TotalProcessorTime.TotalMilliseconds;
LightingManager.UpdateLighting(); LightingManager.UpdateLighting();
LightingManager.sunAngles[0] += 5f; //LightingManager.sunAngles[0] += 5f;
LightingManager.sunAngles[1] += 1f; // LightingManager.sunAngles[1] += 1f;
} }
if (Process.GetCurrentProcess().TotalProcessorTime.TotalMilliseconds - SecondFrameTime > 1000) { if (Process.GetCurrentProcess().TotalProcessorTime.TotalMilliseconds - SecondFrameTime > 1000) {
TotalRamUsage = Math.Round(System.Diagnostics.Process.GetCurrentProcess().WorkingSet64 / 1000000.0);
RamUsage = Math.Round(GC.GetTotalMemory(false) / 1000000.0);
SecondFrameTime = Process.GetCurrentProcess().TotalProcessorTime.TotalMilliseconds; SecondFrameTime = Process.GetCurrentProcess().TotalProcessorTime.TotalMilliseconds;
FPS = Frames; FPS = Frames;
Frames = 0; Frames = 0;
} }
if (up && LightingManager.AmbientColouring[0] < 1.5f)
{
//LightingManager.AmbientColouring[0] += 0.01f;
//LightingManager.AmbientColouring[1] += 0.01f;
//LightingManager.AmbientColouring[2] += 0.01f;
}
else if (up) up = false;
else if (LightingManager.AmbientColouring[0] > 0.5f)
{
//LightingManager.AmbientColouring[0] -= 0.01f;
//LightingManager.AmbientColouring[1] -= 0.01f;
//LightingManager.AmbientColouring[2] -= 0.01f;
}
else up = true;
} }
} }
private void Draw(object sender, PaintEventArgs e) private void Draw(object sender, PaintEventArgs e)
@@ -127,20 +101,9 @@ namespace VoxelIsometricRenderer
g.PixelOffsetMode = PixelOffsetMode.Half; g.PixelOffsetMode = PixelOffsetMode.Half;
g.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.NearestNeighbor; g.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.NearestNeighbor;
g.ScaleTransform(scale, scale); g.ScaleTransform(scale, scale);
int x = 0; ChunkRegistry.RenderChunk(g, 0);
int y = 0;
foreach(Voxel voxel in Voxels)
{
voxel.Draw(g,2 + x,2 + y);
x += 36;
if ((x+32) * scale > Width)
{
y += 36;
x = 0;
}
}
g.ResetTransform(); g.ResetTransform();
g.DrawString(String.Format("FPS: {0}", FPS), SystemFonts.DefaultFont, Brushes.Red, new PointF(0, 0)); g.DrawString(String.Format("FPS: {0} Ram Usage: {9}MB Ram Allocated: {8}MB\nSunValue: {1}\nMoonValue:{3}\nLightDirection:{4}\nAmbientColourGrading: R{5} G{6} B{7}\nSunAngles:{2}", FPS, LightingManager.SkyLightMetrics[0], String.Format(" x={0}° y={1}°", LightingManager.sunAngles[0], LightingManager.sunAngles[1]), LightingManager.SkyLightMetrics[2], LightingManager.SunAngle, LightingManager.SkyLightMetrics[3], LightingManager.SkyLightMetrics[4], LightingManager.SkyLightMetrics[5], TotalRamUsage, RamUsage), SystemFonts.DefaultFont, Brushes.Red, new PointF(0, 0));
Frames++; Frames++;
} }
public void ResizeDisplay() public void ResizeDisplay()
@@ -164,6 +127,22 @@ namespace VoxelIsometricRenderer
{ {
if (e.KeyCode == Keys.Up) scale += 0.25f; if (e.KeyCode == Keys.Up) scale += 0.25f;
if (e.KeyCode == Keys.Down) scale -= 0.25f; if (e.KeyCode == Keys.Down) scale -= 0.25f;
if (e.KeyCode == Keys.W)
{
LightingManager.sunAngles[1] += 10f;
}
if (e.KeyCode == Keys.S)
{
LightingManager.sunAngles[1] -= 10f;
}
if (e.KeyCode == Keys.A)
{
LightingManager.sunAngles[0] += 10f;
}
if (e.KeyCode == Keys.D)
{
LightingManager.sunAngles[0] += 10f;
}
} }
private void KeyUpEvent(object sender, KeyEventArgs e) private void KeyUpEvent(object sender, KeyEventArgs e)

View File

@@ -3,10 +3,14 @@ using System.Collections.Generic;
using System.Drawing; using System.Drawing;
using System.Drawing.Imaging; using System.Drawing.Imaging;
using System.Linq; using System.Linq;
using System.Runtime.InteropServices;
using System.Runtime.Remoting.Messaging;
using System.Security.AccessControl; using System.Security.AccessControl;
using System.Security.Policy; using System.Security.Policy;
using System.Text; using System.Text;
using System.Threading.Tasks; using System.Threading.Tasks;
using System.Windows.Forms;
using System.Windows.Forms.VisualStyles;
using VoxelIsometricRenderer.Properties; using VoxelIsometricRenderer.Properties;
namespace VoxelIsometricRenderer namespace VoxelIsometricRenderer
@@ -22,15 +26,159 @@ namespace VoxelIsometricRenderer
SouthWest, SouthWest,
South South
} }
public enum LightShape
{
Cylinder,
Sphere,
Cube,
Cuboid
}
public class LightSource
{
int RangeX;
int RangeY;
int RangeZ;
int XWorldPos;
int YWorldPos;
int ZWorldPos;
LightShape Shape;
byte[,,] LightLevels;
float[] LightLevelModifier = new float[] { 1.5f, 1.5f, 1.5f };
int Brightness = 64;
public static bool IsWithinCircle(int Radius, int CentreX, int CentreY, int posX, int PosY)
{
return LightingManager.Square(posX - CentreX) + LightingManager.Square(PosY - CentreY) < LightingManager.Square(Radius);
}
public static bool IsWithinSphere(int Radius, int CentreX, int CentreY, int CentreZ, int posX, int PosY, int PosZ)
{
return LightingManager.Square(posX - CentreX) + LightingManager.Square(PosY - CentreY) + LightingManager.Square(PosZ - CentreZ) < LightingManager.Square(Radius);
}
public LightSource(LightShape shape, int RangeX, int RangeY, int RangeZ, int XWorldPos, int YWorldPos, int ZWorldPos,int Brightness)
{
this.Shape = shape;
this.RangeX = RangeX;
this.RangeY = RangeY;
this.RangeZ = RangeZ;
this.XWorldPos = XWorldPos;
this.YWorldPos = YWorldPos;
this.ZWorldPos = ZWorldPos;
this.Brightness = Brightness;
SetUpLightLevels();
}
public byte CalculateLightLevel(int CentreX, int CentreY, int CentreZ, int PosX, int PosY, int PosZ, int RangeX, int RangeY, int RangeZ, int MaxLevel)
{
int[] Distances = new int[] { CentreX - PosX, CentreY - PosY, CentreZ - PosZ};
int[] Centres = new int[] { CentreX, CentreY, CentreZ };
float[] LightLevel = new float[] {255.0f/ RangeX * (MaxLevel / 255.0f), 255.0f/ RangeY * (MaxLevel / 255.0f), 255.0f/ RangeZ * (MaxLevel / 255.0f) };
float TotalLightLevel = 0;
int Dimensions = 0;
for (int i = 0; i < 3; i++)
{
Distances[i] = Distances[i] > 0 ? Distances[i] : -Distances[i];
}
LightLevel = new float[] { LightLevel[0] * (float)Distances[0], LightLevel[1] * (float)Distances[1], LightLevel[2] * (float)Distances[2] };
for (int i = 0; i < 3; i++)
{
if (Centres[i] >= 0)
{
Dimensions++;
TotalLightLevel += LightLevel[i];
}
}
TotalLightLevel /= Dimensions;
return (byte)Math.Min(Math.Max(TotalLightLevel,0),255);
}
private void SetUpLightLevels()
{
LightLevels = new byte[RangeX*2, RangeY*2, RangeZ*2];
int CentreX = LightLevels.GetLength(0) / 2;
int CentreY = LightLevels.GetLength(1) / 2;
int CentreZ = LightLevels.GetLength(2) / 2;
for (int x = 0; x < LightLevels.GetLength(0); x++)
{
for (int y = 0; y < LightLevels.GetLength(1); y++)
{
for (int z = 0; z < LightLevels.GetLength(2); z++)
{
switch (Shape)
{
case LightShape.Sphere:
if (IsWithinSphere((RangeX + RangeY + RangeZ)/3, CentreX, CentreY, CentreZ, x, y, z)){
LightLevels[x, y, z] = CalculateLightLevel(CentreX, CentreY, CentreZ, x, y, z, RangeX, RangeY, RangeZ,Brightness);
}
break;
case LightShape.Cylinder:
if (IsWithinCircle((RangeX + RangeY) / 2, CentreX, CentreZ, x, z))
{
LightLevels[x, y, z] = CalculateLightLevel(CentreX, -1, CentreZ, x, y, z, RangeX, RangeY, RangeZ, Brightness);
}
break;
default:
LightLevels[x, y, z] = CalculateLightLevel(CentreX, CentreY, CentreZ, x, y, z, RangeX, RangeY, RangeZ, Brightness);
break;
}
}
}
}
}
public LightSource(LightShape shape, int Range, int XWorldPos, int YWorldPos, int ZWorldPos,int Brightness)
{
this.Shape = shape;
this.RangeX = Range;
this.RangeY = Range;
this.RangeZ = Range;
this.XWorldPos = XWorldPos;
this.YWorldPos = YWorldPos;
this.ZWorldPos = ZWorldPos;
this.Brightness = Brightness;
SetUpLightLevels();
}
public LightSource(LightShape shape, int Range, int XWorldPos, int YWorldPos, int ZWorldPos, float[] RGBLightLevels, int Brightness)
{
this.Shape = shape;
this.RangeX = Range;
this.RangeY = Range;
this.RangeZ = Range;
this.XWorldPos = XWorldPos;
this.YWorldPos = YWorldPos;
this.ZWorldPos = ZWorldPos;
this.LightLevelModifier = RGBLightLevels;
this.Brightness = Brightness;
SetUpLightLevels();
}
public LightSource( LightShape shape, int RangeX, int RangeY, int RangeZ, int XWorldPos, int YWorldPos, int ZWorldPos, float[] RGBLightLevels, int Brightness)
{
this.Shape = shape;
this.RangeX = RangeX;
this.RangeY = RangeY;
this.RangeZ = RangeZ;
this.XWorldPos = XWorldPos;
this.YWorldPos = YWorldPos;
this.ZWorldPos = ZWorldPos;
this.LightLevelModifier = RGBLightLevels;
this.Brightness = Brightness;
SetUpLightLevels();
}
}
public static class LightingManager public static class LightingManager
{ {
public static float[] AmbientColouring = new float[] { 1.0f, 1.0f, 1.0f }; public static float[] AmbientColouring = new float[] { 1.0f, 1.0f, 1.0f };
public static float[] AmbientMinimums = new float[] { 0.1f, 0.1f, 0.1f, 0.1f, 0.1f, 0.1f }; public static float[] AmbientMinimums = new float[] { 0.05f, 0.05f, 0.05f, 0.05f, 0.05f, 0.05f };
public static float[] DefaultValues = new float[] { 0.6f, 0.6f, 0.6f, 0.6f, 1.0f, 0.4f }; public static float[] DefaultValues = new float[] { 0.6f, 0.6f, 0.6f, 0.6f, 1.0f, 0.4f };
public static float[] SunModifiedValues = new float[] { 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f }; public static float[] SkyLightModifiedValues = new float[] { 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f };
public static float[] sunAngles = new float[] { 180, 0 }; public static float[] SunLightColourModifier = new float[] { 1.1f, 1.0f, 0.8f };
public static float[] MoonLightColourModifier = new float[] { 0.5f, 0.6f, 0.85f };
public static float[] sunAngles = new float[] { 135, 0 };
public static float[] SkyLightMetrics = new float[] { 0, 0, 0, 0,0,0 };
public static List<LightSource> Lights = new List<LightSource>();
public static LightDirection SunAngle = LightDirection.North; public static LightDirection SunAngle = LightDirection.North;
public static float MaxBloom = 1.05f;
public static float[] RenderLightOnCube(int WorldX, int WorldY, int WorldZ, int face)
{
return new float[] { 0, 0, 0 };
}
public static void UpdateLighting() public static void UpdateLighting()
{ {
float[] AngleRanges = new float[] { 0, 45, 90, 135, 180, 225, 270, 315 }; float[] AngleRanges = new float[] { 0, 45, 90, 135, 180, 225, 270, 315 };
@@ -42,6 +190,8 @@ namespace VoxelIsometricRenderer
if (sunAngles[1] <= -360) sunAngles[1] += 360; if (sunAngles[1] <= -360) sunAngles[1] += 360;
float CurrentAngle = 0; float CurrentAngle = 0;
int AngleIndex = 0; int AngleIndex = 0;
float MoonAngle = (float)((1 + Math.Sin(Math.PI * (sunAngles[1] - 60) / 180)) / 2.0);
float SunLightAngle = (float)((1 + Math.Cos(Math.PI * sunAngles[1] / 180)) / 1.8);
for (int i = 0; i < AngleRanges.Length; i++) for (int i = 0; i < AngleRanges.Length; i++)
{ {
if (sunAngles[0] < AngleRanges[i]) if (sunAngles[0] < AngleRanges[i])
@@ -56,16 +206,25 @@ namespace VoxelIsometricRenderer
AngleIndex = AngleIndex - 1 >= 0 ? AngleIndex - 1 : AngleRanges.Length - 1; AngleIndex = AngleIndex - 1 >= 0 ? AngleIndex - 1 : AngleRanges.Length - 1;
} }
SunAngle = directions[AngleIndex]; SunAngle = directions[AngleIndex];
for (int i = 0; i < SunModifiedValues.Length - 2; i++) for (int i = 0; i < SkyLightModifiedValues.Length - 2; i++)
{ {
SunModifiedValues[i] = (float)((1 + Math.Cos(Math.PI * (sunAngles[0] + AngleOffsets[i]) / 180)/ 2.0) * (float)( 1 + Math.Sin(Math.PI * (sunAngles[1] + 45) / 180))/ 2.0); SkyLightModifiedValues[i] = (float)((1 + Math.Cos(Math.PI * (sunAngles[0] + AngleOffsets[i]) / 180) / 2.0) * (float)Math.Min(Math.Max((1 + Math.Cos(Math.PI * (sunAngles[1] + 45) / 180)) / 2.0, MoonAngle/2),0.9));
} }
for (int i = SunModifiedValues.Length - 2; i < SunModifiedValues.Length; i++) for (int i = SkyLightModifiedValues.Length - 2; i < SkyLightModifiedValues.Length; i++)
{ {
SunModifiedValues[i] = (float)Math.Max((1 + Math.Cos(Math.PI * (sunAngles[1]) / 180)) / 2.0, 0.3f); SkyLightModifiedValues[i] = (float)Math.Min(Math.Max(SunLightAngle, MoonAngle/2) + (MoonAngle/ 4),MaxBloom);
} }
for (int i = 0; i < AmbientColouring.Length; i++)
{
AmbientColouring[i] = SunLightColourModifier[i] * SunLightAngle + MoonLightColourModifier[i] * MoonAngle;
SkyLightMetrics[3 + i] = AmbientColouring[i];
} }
private static float Square(float ValueIn) AmbientColouring[2] -= sunAngles[1] > 180 || sunAngles[1] < 90 ? Square(Square((float)(Math.Max(Math.Cos(Math.PI * (sunAngles[1] + 45) / 180), 0)))) / 2.0f : 0;//(float)(Math.Max(Math.Cos(Math.PI * (sunAngles[1] + 45) / 180),0));
AmbientColouring[1] -= sunAngles[1] > 180 || sunAngles[1] < 90 ? Square(Square((float)(Math.Max(Math.Cos(Math.PI * (sunAngles[1] + 45) / 180), 0))) / 3.0f) : 0;// (float)(Math.Max(Math.Cos(Math.PI * (sunAngles[1] + 45) / 180),0))/2.0f;
SkyLightMetrics[0] = (float)Math.Max(SunLightAngle, 0.1f) + (float)(MoonAngle / 5);
SkyLightMetrics[2] = MoonAngle;
}
public static float Square(float ValueIn)
{ {
return ValueIn * ValueIn; return ValueIn * ValueIn;
} }
@@ -93,30 +252,32 @@ namespace VoxelIsometricRenderer
if (faces[i] >= 0 && GeneratedFaceTextures[faces[i], i].Height > ImageHeight) ImageHeight = GeneratedFaceTextures[faces[i], i].Height; if (faces[i] >= 0 && GeneratedFaceTextures[faces[i], i].Height > ImageHeight) ImageHeight = GeneratedFaceTextures[faces[i], i].Height;
} }
Bitmap GeneratedModel = new Bitmap(ImageWidth, ImageHeight); Bitmap GeneratedModel = new Bitmap(ImageWidth, ImageHeight);
voxel.Draw(Graphics.FromImage(GeneratedModel),0,0); voxel.Draw(Graphics.FromImage(GeneratedModel),0,0,0,0,0,0);
voxel.SetPreCompiledModel(PreCompiledModels.Count); voxel.SetPreCompiledModel(PreCompiledModels.Count);
PreCompiledModels.Add(GeneratedModel); PreCompiledModels.Add(GeneratedModel);
GeneratedModel.Save("Model" + voxel.GetModelNum() + ".png"); GeneratedModel.Save("Model" + voxel.GetModelNum() + ".png");
} }
public static float GetSunlightValue(int face) public static float GetSunlightValue(int face, int ShadowLevel)
{ {
return LightingManager.SunModifiedValues[face] * LightingManager.DefaultValues[face]; return (LightingManager.SkyLightModifiedValues[face] * LightingManager.DefaultValues[face])/(float)ShadowLevel;
} }
public static float GetShadingValue(float LightValue, int RGBIndex, int FaceIndex) public static float GetShadingValue(float LightValue, int RGBIndex, int FaceIndex)
{ {
return (float)Math.Max(LightValue * LightingManager.AmbientColouring[RGBIndex], LightingManager.AmbientMinimums[FaceIndex]); return (float)Math.Max(LightValue * LightingManager.AmbientColouring[RGBIndex], LightingManager.AmbientMinimums[FaceIndex]);
} }
public static ImageAttributes GetShadow(int face) public static ImageAttributes GetShadow(int face) { return GetShadow(face, 0, 0,0,0); }
public static ImageAttributes GetShadow(int face, int WorldX, int WorldY, int WorldZ, int ShadowLevel)
{ {
ImageAttributes imageAttributes; ImageAttributes imageAttributes;
float[][] colorMatrixElements; float[][] colorMatrixElements;
float[] Lights = LightingManager.RenderLightOnCube(WorldX, WorldY, WorldZ, face);
ColorMatrix colorMatrix; ColorMatrix colorMatrix;
switch (face) { switch (face) {
case 0: case 0:
colorMatrixElements = new float[][]{ colorMatrixElements = new float[][]{
new float[] { GetShadingValue(GetSunlightValue(face), 0,face), 0, 0, 0, 0}, // red new float[] { GetShadingValue(GetSunlightValue(face,ShadowLevel), 0,face), 0, 0, 0, 0}, // red
new float[] {0, GetShadingValue(GetSunlightValue(face), 1, face), 0, 0, 0}, // green new float[] {0, GetShadingValue(GetSunlightValue(face,ShadowLevel), 1, face), 0, 0, 0}, // green
new float[] {0, 0, GetShadingValue(GetSunlightValue(face), 2, face), 0, 0}, // blue new float[] {0, 0, GetShadingValue(GetSunlightValue(face,ShadowLevel), 2, face), 0, 0}, // blue
new float[] {0, 0, 0, 1, 0}, // alpha new float[] {0, 0, 0, 1, 0}, // alpha
new float[] {0, 0, 0, 0, 1}}; // three translations of 0.2 new float[] {0, 0, 0, 0, 1}}; // three translations of 0.2
@@ -126,9 +287,9 @@ namespace VoxelIsometricRenderer
return imageAttributes; return imageAttributes;
case 1: case 1:
colorMatrixElements = new float[][]{ colorMatrixElements = new float[][]{
new float[] { GetShadingValue(GetSunlightValue(face), 0,face), 0, 0, 0, 0}, // red new float[] { GetShadingValue(GetSunlightValue(face,ShadowLevel), 0,face), 0, 0, 0, 0}, // red
new float[] {0, GetShadingValue(GetSunlightValue(face), 1, face), 0, 0, 0}, // green new float[] {0, GetShadingValue(GetSunlightValue(face,ShadowLevel), 1, face), 0, 0, 0}, // green
new float[] {0, 0, GetShadingValue(GetSunlightValue(face), 2, face), 0, 0}, // blue new float[] {0, 0, GetShadingValue(GetSunlightValue(face,ShadowLevel), 2, face), 0, 0}, // blue
new float[] {0, 0, 0, 1, 0}, // alpha new float[] {0, 0, 0, 1, 0}, // alpha
new float[] {0, 0, 0, 0, 1}}; // three translations of 0.2 new float[] {0, 0, 0, 0, 1}}; // three translations of 0.2
@@ -138,9 +299,9 @@ namespace VoxelIsometricRenderer
return imageAttributes; return imageAttributes;
case 2: case 2:
colorMatrixElements = new float[][]{ colorMatrixElements = new float[][]{
new float[] { GetShadingValue(GetSunlightValue(face), 0,face), 0, 0, 0, 0}, // red new float[] { GetShadingValue(GetSunlightValue(face,ShadowLevel), 0,face), 0, 0, 0, 0}, // red
new float[] {0, GetShadingValue(GetSunlightValue(face), 1, face), 0, 0, 0}, // green new float[] {0, GetShadingValue(GetSunlightValue(face,ShadowLevel), 1, face), 0, 0, 0}, // green
new float[] {0, 0, GetShadingValue(GetSunlightValue(face), 2, face), 0, 0}, // blue new float[] {0, 0, GetShadingValue(GetSunlightValue(face,ShadowLevel), 2, face), 0, 0}, // blue
new float[] {0, 0, 0, 1, 0}, // alpha new float[] {0, 0, 0, 1, 0}, // alpha
new float[] {0, 0, 0, 0, 1}}; // three translations of 0.2 new float[] {0, 0, 0, 0, 1}}; // three translations of 0.2
@@ -150,9 +311,9 @@ namespace VoxelIsometricRenderer
return imageAttributes; return imageAttributes;
case 3: case 3:
colorMatrixElements = new float[][]{ colorMatrixElements = new float[][]{
new float[] { GetShadingValue(GetSunlightValue(face), 0,face), 0, 0, 0, 0}, // red new float[] { GetShadingValue(GetSunlightValue(face,ShadowLevel), 0,face), 0, 0, 0, 0}, // red
new float[] {0, GetShadingValue(GetSunlightValue(face), 1, face), 0, 0, 0}, // green new float[] {0, GetShadingValue(GetSunlightValue(face,ShadowLevel), 1, face), 0, 0, 0}, // green
new float[] {0, 0, GetShadingValue(GetSunlightValue(face), 2, face), 0, 0}, // blue new float[] {0, 0, GetShadingValue(GetSunlightValue(face,ShadowLevel), 2, face), 0, 0}, // blue
new float[] {0, 0, 0, 1, 0}, // alpha new float[] {0, 0, 0, 1, 0}, // alpha
new float[] {0, 0, 0, 0, 1}}; // three translations of 0.2 new float[] {0, 0, 0, 0, 1}}; // three translations of 0.2
@@ -162,9 +323,9 @@ namespace VoxelIsometricRenderer
return imageAttributes; return imageAttributes;
case 4: case 4:
colorMatrixElements = new float[][]{ colorMatrixElements = new float[][]{
new float[] { GetShadingValue(GetSunlightValue(face), 0,face), 0, 0, 0, 0}, // red new float[] { GetShadingValue(GetSunlightValue(face,ShadowLevel), 0,face), 0, 0, 0, 0}, // red
new float[] {0, GetShadingValue(GetSunlightValue(face), 1, face), 0, 0, 0}, // green new float[] {0, GetShadingValue(GetSunlightValue(face,ShadowLevel), 1, face), 0, 0, 0}, // green
new float[] {0, 0, GetShadingValue(GetSunlightValue(face), 2, face), 0, 0}, // blue new float[] {0, 0, GetShadingValue(GetSunlightValue(face,ShadowLevel), 2, face), 0, 0}, // blue
new float[] {0, 0, 0, 1, 0}, // alpha new float[] {0, 0, 0, 1, 0}, // alpha
new float[] {0, 0, 0, 0, 1}}; // three translations of 0.2 new float[] {0, 0, 0, 0, 1}}; // three translations of 0.2
@@ -174,9 +335,9 @@ namespace VoxelIsometricRenderer
return imageAttributes; return imageAttributes;
case 5: case 5:
colorMatrixElements = new float[][]{ colorMatrixElements = new float[][]{
new float[] { GetShadingValue(GetSunlightValue(face), 0,face), 0, 0, 0, 0}, // red new float[] { GetShadingValue(GetSunlightValue(face,ShadowLevel), 0,face), 0, 0, 0, 0}, // red
new float[] {0, GetShadingValue(GetSunlightValue(face), 1, face), 0, 0, 0}, // green new float[] {0, GetShadingValue(GetSunlightValue(face,ShadowLevel), 1, face), 0, 0, 0}, // green
new float[] {0, 0, GetShadingValue(GetSunlightValue(face), 2, face), 0, 0}, // blue new float[] {0, 0, GetShadingValue(GetSunlightValue(face,ShadowLevel), 2, face), 0, 0}, // blue
new float[] {0, 0, 0, 1, 0}, // alpha new float[] {0, 0, 0, 1, 0}, // alpha
new float[] {0, 0, -0, 0, 1}}; // three translations of 0.2 new float[] {0, 0, -0, 0, 1}}; // three translations of 0.2
@@ -430,6 +591,7 @@ namespace VoxelIsometricRenderer
int[] DrawOrder = new int[] { 5, 0, 3, 1, 2, 4 }; int[] DrawOrder = new int[] { 5, 0, 3, 1, 2, 4 };
int ModelType = 0; int ModelType = 0;
int ModelNum = -1; int ModelNum = -1;
bool Cull = false;
public int[] getFaces() public int[] getFaces()
{ {
return faces; return faces;
@@ -450,12 +612,18 @@ namespace VoxelIsometricRenderer
{ {
return VoxelNum; return VoxelNum;
} }
public Voxel(int ModelType,int NorthFace, int SouthFace, int EastFace, int WestFace, int UpFace, int DownFace) public Voxel(int ModelType,int NorthFace, int SouthFace, int EastFace, int WestFace, int UpFace, int DownFace, bool cull)
{ {
this.ModelType = ModelType; this.ModelType = ModelType;
faces = new int[] { NorthFace, SouthFace, EastFace, WestFace, UpFace, DownFace }; faces = new int[] { NorthFace, SouthFace, EastFace, WestFace, UpFace, DownFace };
VoxelNum = TextureManager.VoxelCount; VoxelNum = TextureManager.VoxelCount;
TextureManager.VoxelCount++; TextureManager.VoxelCount++;
if (cull) SetCullFaces(false,true,false,false, false, false);
Cull = cull;
}
public void SetCullFaces(bool up, bool down, bool West, bool East,bool north, bool south)
{
DrawOrder = new int[] { down?-1:5, north?-1:0, West?-1:3, south?-1:1, East?-1:2, up?-1:4 };
} }
public void SetPreCompiledModel(int ModelNum) public void SetPreCompiledModel(int ModelNum)
{ {
@@ -467,10 +635,10 @@ namespace VoxelIsometricRenderer
VoxelNum = TextureManager.VoxelCount; VoxelNum = TextureManager.VoxelCount;
TextureManager.VoxelCount++; TextureManager.VoxelCount++;
} }
virtual public void Draw(Graphics g, int x, int y) virtual public void Draw(Graphics g, int x, int y, int WorldX, int WorldY, int WorldZ, int ShadowLevel)
{ {
for (int i = 0; i < DrawOrder.Length; i++) { for (int i = 0; i < DrawOrder.Length; i++) {
if (faces[DrawOrder[i]] >= 0) if (DrawOrder[i] > 0 && DrawOrder[i] < 6 && faces[DrawOrder[i]] >= 0)
{ {
if (ModelNum == -1) if (ModelNum == -1)
{ {
@@ -479,7 +647,7 @@ namespace VoxelIsometricRenderer
{ {
case 0: case 0:
Side = GetRenderedSide(DrawOrder[i]); Side = GetRenderedSide(DrawOrder[i]);
g.DrawImage(Side, new Rectangle(x, y, Side.Width, Side.Height), 0, 0, Side.Width, Side.Height, GraphicsUnit.Pixel, TextureManager.GetShadow(DrawOrder[i])); g.DrawImage(Side, new Rectangle(x, y, Side.Width, Side.Height), 0, 0, Side.Width, Side.Height, GraphicsUnit.Pixel, TextureManager.GetShadow(DrawOrder[i], WorldX, WorldY,WorldZ, ShadowLevel));
break; break;
default: default:
@@ -487,23 +655,23 @@ namespace VoxelIsometricRenderer
{ {
case 0: case 0:
Side = GetRenderedSide(0); Side = GetRenderedSide(0);
g.DrawImage(Side, new Rectangle(x - (Side.Width / 4), y, Side.Width, Side.Height),0,0,Side.Width,Side.Height, GraphicsUnit.Pixel, TextureManager.GetShadow(0)); g.DrawImage(Side, new Rectangle(x - (Side.Width / 4), y, Side.Width, Side.Height),0,0,Side.Width,Side.Height, GraphicsUnit.Pixel, TextureManager.GetShadow(0, WorldX, WorldY, WorldZ, ShadowLevel));
break; break;
case 1: case 1:
Side = GetRenderedSide(1); Side = GetRenderedSide(1);
g.DrawImage(Side, new Rectangle(x + (Side.Width / 4), y - (Side.Height / 4), Side.Width, Side.Height),0,0,Side.Width,Side.Height, GraphicsUnit.Pixel, TextureManager.GetShadow(1)); g.DrawImage(Side, new Rectangle(x + (Side.Width / 4), y - (Side.Height / 4), Side.Width, Side.Height),0,0,Side.Width,Side.Height, GraphicsUnit.Pixel, TextureManager.GetShadow(1, WorldX, WorldY, WorldZ, ShadowLevel));
break; break;
case 2: case 2:
Side = GetRenderedSide(2); Side = GetRenderedSide(2);
g.DrawImage(Side, new Rectangle(x - (Side.Width / 4), y - (Side.Height / 4), Side.Width, Side.Height),0,0,Side.Width,Side.Height, GraphicsUnit.Pixel, TextureManager.GetShadow(2)); g.DrawImage(Side, new Rectangle(x - (Side.Width / 4), y - (Side.Height / 4), Side.Width, Side.Height),0,0,Side.Width,Side.Height, GraphicsUnit.Pixel, TextureManager.GetShadow(2, WorldX, WorldY, WorldZ, ShadowLevel));
break; break;
case 3: case 3:
Side = GetRenderedSide(3); Side = GetRenderedSide(3);
g.DrawImage(Side, new Rectangle( x + (Side.Width / 4),y,Side.Width,Side.Height),0,0,Side.Width,Side.Height, GraphicsUnit.Pixel, TextureManager.GetShadow(3)); g.DrawImage(Side, new Rectangle( x + (Side.Width / 4),y,Side.Width,Side.Height),0,0,Side.Width,Side.Height, GraphicsUnit.Pixel, TextureManager.GetShadow(3, WorldX, WorldY, WorldZ, ShadowLevel));
break; break;
default: default:
Side = GetRenderedSide(DrawOrder[i]); Side = GetRenderedSide(DrawOrder[i]);
g.DrawImage(Side, new Rectangle(x, y, Side.Width, Side.Height), 0, 0, Side.Width, Side.Height, GraphicsUnit.Pixel, TextureManager.GetShadow(DrawOrder[i])); g.DrawImage(Side, new Rectangle(x, y, Side.Width, Side.Height), 0, 0, Side.Width, Side.Height, GraphicsUnit.Pixel, TextureManager.GetShadow(DrawOrder[i], WorldX, WorldY, WorldZ, ShadowLevel));
break; break;
} }
break; break;
@@ -577,4 +745,319 @@ namespace VoxelIsometricRenderer
faces[5] = Texture; faces[5] = Texture;
} }
} }
public static class VoxelRegistry
{
public static List<Voxel> Voxels = new List<Voxel>();
public static int IndexVoxel(Voxel voxel)
{
if(Voxels.Contains(voxel)) return Voxels.IndexOf(voxel);
Voxels.Add(voxel);
return Voxels.IndexOf(Voxels.Last());
}
public static int VoxelExists(Voxel voxel)
{
return Voxels.Contains(voxel) ? Voxels.IndexOf(voxel) : -1;
}
public static Voxel FetchVoxel(int VoxelIndex)
{
return Voxels[VoxelIndex];
}
}
public enum BlockType
{
Plant,
Ground,
Wood,
Metal,
BuildMaterial,
Gas,
Fluid
}
public class BlockState
{
bool TickUpdate = false;
BlockType BlockType;
bool BlocksLight = false;
public BlockState(bool TickUpdate, BlockType blocktype, bool blocksLight)
{
this.TickUpdate = TickUpdate;
this.BlockType = blocktype;
BlocksLight = blocksLight;
}
public bool hasBlocksLight() { return BlocksLight; }
public BlockType GetBlockType() { return BlockType; }
public bool Ticks() { return TickUpdate; }
}
public static class BlockstateRegistry
{
public static List<BlockState> Blockstates = new List<BlockState>();
public static int GetBlockstateIndex(BlockState blockstate)
{
if (!Blockstates.Contains(blockstate)) Blockstates.Add(blockstate);
return Blockstates.IndexOf(blockstate);
}
public static BlockState GetBlockstate(int index)
{
return Blockstates[index];
}
public static void SetBlockstate(int index, BlockState blockstate)
{
Blockstates[index] = blockstate;
}
}
public class Chunk
{
public List<int>DrawList = new List<int>();
public List<int[]>DrawPositions = new List<int[]>();
public int[,,] BlockReg;
public bool[,,] Culled;
public int[] ChunkPos;
public int ChunkID;
public int[,,] SkyLightHeightMap;
public Chunk(int X, int Y, int Z, int Width, int Height, int Length, int ChunkID)
{
this.ChunkID = ChunkID;
BlockReg = new int[Width,Height,Length];
Culled = new bool[Width,Height,Length];
SkyLightHeightMap = new int[Width,Height,Length];
ChunkPos = new int[] { X, Y, Z };
}
public void CalculateCull()
{
DrawList = new List<int>();
int CulledCount = 0;
for (int x = 0; x < Culled.GetLength(0); x++)
{
for (int y = 0; y < Culled.GetLength(1); y++)
{
for (int z = 0; z < Culled.GetLength(2); z++)
{
if (!(x == Culled.GetLength(0) - 1 || x < Culled.GetLength(0) - 1 && (BlockReg[x + 1, y, z] != -1 && !BlockRegistry.FetchBlockState(BlockReg[x + 1, y, z]).hasBlocksLight() || BlockReg[x + 1, y, z] == -1))
&& !(x > 0 && (BlockReg[x - 1, y, z] != -1 && !BlockRegistry.FetchBlockState(BlockReg[x - 1, y, z]).hasBlocksLight() || BlockReg[x - 1, y, z] == -1))
&& !(y == Culled.GetLength(1) - 1 || y < Culled.GetLength(1) - 1 && (BlockReg[x, y + 1, z] != -1 && !BlockRegistry.FetchBlockState(BlockReg[x, y + 1, z]).hasBlocksLight() || BlockReg[x, y + 1, z] == -1))
&& !(y > 0 && (BlockReg[x, y - 1, z] != -1 && !BlockRegistry.FetchBlockState(BlockReg[x, y - 1, z]).hasBlocksLight() || BlockReg[x, y - 1, z] == -1))
&& !(z == Culled.GetLength(2) - 1 || z < Culled.GetLength(2) - 1 && (BlockReg[x, y, z + 1] != -1 && !BlockRegistry.FetchBlockState(BlockReg[x, y, z + 1]).hasBlocksLight() || BlockReg[x, y, z + 1] == -1))
&& !(z > 0 && (BlockReg[x, y, z - 1] != -1 && !BlockRegistry.FetchBlockState(BlockReg[x, y, z - 1]).hasBlocksLight() || BlockReg[x, y, z - 1] == -1)))
{
Culled[x, y, z] = true;
CulledCount++;
}
}
}
}
for (int x = 0; x < BlockReg.GetLength(0); x++)
{
for (int y = 0; y < BlockReg.GetLength(1); y++)
{
for (int z = 0; z < BlockReg.GetLength(1); z++)
{
if (Culled[x,y,z] == false && BlockReg[x, y, z] != -1)
{
DrawList.Add(BlockReg[x,y,z]);
DrawPositions.Add(new int[] { x, y, z });
}
}
}
}
}
public void GenerateLightMap()
{
for (int x = 0;x < SkyLightHeightMap.GetLength(0); x++)
{
for(int z = 0; z < SkyLightHeightMap.GetLength(1); z++)
{
int Y = 1;
for (int y = SkyLightHeightMap.GetLength(1) - 1; y > 0; y--)
{
SkyLightHeightMap[x, y, z] = Y;
if (BlockReg[x,y,z] != -1 && BlockRegistry.FetchBlockState(BlockReg[x, y, z]).hasBlocksLight())
{
Y++;
}
}
}
}
}
public void RenderBlocks(Graphics g)
{
if (DrawList.Count == 0)
{
for (int x = 0; x < BlockReg.GetLength(0); x++)
{
for (int y = 0; y < BlockReg.GetLength(1); y++)
{
for (int z = 0; z < BlockReg.GetLength(1); z++)
{
if (BlockReg[x, y, z] != -1 && Culled[x, y, z] == false)
{
BlockRegistry.RenderBlock(g, BlockReg[x, y, z], x + ChunkPos[0] * ChunkRegistry.FetchDimensions()[0], y + ChunkPos[1] * ChunkRegistry.FetchDimensions()[1], z + ChunkPos[1] * ChunkRegistry.FetchDimensions()[1], SkyLightHeightMap[x, y, z]);
}
}
}
}
}
else
{
for (int i = 0; i < DrawList.Count; i++)
{
BlockRegistry.RenderBlock(g, DrawList[i], DrawPositions[i][0] + ChunkPos[0] * ChunkRegistry.FetchDimensions()[0], DrawPositions[i][1] + ChunkPos[1] * ChunkRegistry.FetchDimensions()[1], DrawPositions[i][2] + ChunkPos[1] * ChunkRegistry.FetchDimensions()[1], SkyLightHeightMap[DrawPositions[i][0], DrawPositions[i][1], DrawPositions[i][2]]);
}
}
}
public void CreateAir(int X, int Y, int Z)
{
BlockReg[X, Y, Z] = -1;
}
public void CreateBlock(int[] Faces, int RenderType, BlockState blockState, int X, int Y, int Z)
{
Voxel voxel = new Voxel(RenderType, Faces[0], Faces[1], Faces[2], Faces[3], Faces[4], Faces[5],blockState.hasBlocksLight());
int index = VoxelRegistry.VoxelExists(voxel);
if (index == -1)
{
index = VoxelRegistry.IndexVoxel(voxel);
}
Block newBlock = new Block(index, BlockstateRegistry.GetBlockstateIndex(blockState), ChunkID);
int x = X + ChunkPos[0] * ChunkRegistry.FetchDimensions()[0];
int y = Y + ChunkPos[1] * ChunkRegistry.FetchDimensions()[1];
int z = Z + ChunkPos[2] * ChunkRegistry.FetchDimensions()[2];
int BlockID = BlockRegistry.CheckInBlock(newBlock, x, y, z);
BlockReg[X, Y, Z] = BlockID;
}
public Block FetchBlock(int x, int y, int z)
{
return BlockRegistry.FetchBlock(BlockReg[x,y,z]);
}
public void IndexBlock(int BlockIndex, int x, int y, int z)
{
BlockReg[x,y,z] = BlockIndex;
}
public string FetchPosString()
{
return String.Format("x={0};y={1};z={2}", ChunkPos[0], ChunkPos[1], ChunkPos[2]);
}
public int[] FetchPos()
{
return ChunkPos;
}
public int[,,] FetchAllBlocks()
{
return BlockReg;
}
public int FetchBlockReg(int x, int y, int z)
{
return BlockReg[x, y, z];
}
}
public static class ChunkRegistry
{
static int ChunkWidth = 16;
static int ChunkHeight = 16;
static int ChunkLength = 16;
static List<Chunk> Chunks = new List<Chunk>();
static List<string> Chunk_Pos_Lookup = new List<string>();
public static Chunk IndexChunk(int x, int y, int z)
{
Chunk newChunk = new Chunk(x, y, z, ChunkWidth, ChunkHeight, ChunkLength, Chunks.Count);
Chunks.Add(newChunk);
Chunk_Pos_Lookup.Add(String.Format("x={0};y={1};z={2}", x, y, z));
return newChunk;
}
public static Chunk FetchChunk(string pos_lookup)
{
if (!Chunk_Pos_Lookup.Contains(pos_lookup)) return null;
return Chunks[Chunk_Pos_Lookup.IndexOf(pos_lookup)];
}
public static Chunk FetchChunk(int index)
{
return Chunks[index];
}
public static void RenderChunk(Graphics g,int chunkIndex)
{
Chunks[chunkIndex].RenderBlocks(g);
}
public static int FetchChunkID(string pos_lookup)
{
if (!Chunk_Pos_Lookup.Contains(pos_lookup)) return -1;
return Chunk_Pos_Lookup.IndexOf(pos_lookup);
}
public static int[] FetchDimensions()
{
return new int[] {ChunkWidth, ChunkHeight, ChunkLength};
}
}
public static class BlockRegistry
{
static List<Block> blocks = new List<Block>();
static List<string> block_pos_lookup = new List<string>();
static int BlockSize = 32;
public static BlockState FetchBlockState(int BlockID)
{
return BlockstateRegistry.GetBlockstate(blocks[BlockID].FetchBlockState());
}
public static Block FetchBlock(int BlockID)
{
return blocks[BlockID];
}
public static int FetchBlockIDFromPos(string pos_lookup)
{
if (!block_pos_lookup.Contains(pos_lookup)) return -1;
return block_pos_lookup.IndexOf(pos_lookup);
}
public static int[] GetDrawLocation(int x, int y, int z, int offsetX, int offsetY, int offsetZ)
{
return new int[]{(int)((((double)(x + offsetX) * 0.5) + ((double)(z + offsetZ) * -0.5))*(double)BlockSize),
(int)((((double)(x + offsetX) * 0.5) + ((double)(z + offsetZ) * 0.5) - (offsetY + (y)))*((double)BlockSize/2.0)) };
}
public static void RenderBlock(Graphics g, int BlockID,int WorldX, int WorldY, int WorldZ, int ShadowLevel)
{
int[] location = GetDrawLocation(WorldX, WorldY, WorldZ, 0, 0, 0);
VoxelRegistry.FetchVoxel(blocks[BlockID].FetchVoxelID()).Draw(g, location[0] + 300, location[1] + 300, WorldX, WorldY, WorldZ, ShadowLevel);
}
public static int CheckInBlock(Block block,int x, int y, int z)
{
blocks.Add(block);
block_pos_lookup.Add(String.Format("x={0};y={1};z={2}",x,y,z));
return blocks.IndexOf(blocks.Last());
}
public static string FetchBlockString(int x, int y, int z)
{
return String.Format("x={0};y={1};z={2}", x, y, z);
}
}
public class Block
{
int VoxelID;
int BlockstateID;
int ChunkID;
bool render;
public Block(int voxelID, int blockstateID, int chunkID)
{
VoxelID = voxelID;
BlockstateID = blockstateID;
ChunkID = chunkID;
}
public int FetchVoxelID()
{
return VoxelID;
}
public int FetchChunkID()
{
return ChunkID;
}
public int FetchBlockState()
{
return BlockstateID;
}
public void SetRender(bool render)
{
this.render = render;
}
public bool Renders()
{
return render;
}
}
} }