public BoxelVertex(Vector3b position, Color color, Vector3b normal) { Position = position; Color = color; Normal = normal; Padding1 = 0; Padding2 = 0; }
/// <summary> /// If the boxel has an opaque neighbor /// this method will return true. /// </summary> /// <param name="boxel">Boxel to check</param> /// <param name="face">Face to check</param> /// <returns></returns> private bool HasNeighbor(BoxelType boxel, BoxelFace face, Vector3b position) { int index = -1; bool hasNeighbor = false; Vector3 worldPosition = position.AsVector3() + Position; switch (face) { case BoxelFace.BOTTOM: index = (int)(worldPosition.X + (SIZE * ChunkManager.SIZE) * ((worldPosition.Y - 1) + (SIZE * ChunkManager.SIZE) * worldPosition.Z)); if (index >= 0 && index < ChunkManager.Instance.Boxels.Length && ChunkManager.Instance.Boxels[index] != BoxelType.NONE && worldPosition.Y != 0) { hasNeighbor = true; } break; case BoxelFace.TOP: index = (int)(worldPosition.X + (SIZE * ChunkManager.SIZE) * ((worldPosition.Y + 1) + (SIZE * ChunkManager.SIZE) * worldPosition.Z)); if (index >= 0 && index < ChunkManager.Instance.Boxels.Length && ChunkManager.Instance.Boxels[index] != BoxelType.NONE && worldPosition.Y != (SIZE * ChunkManager.SIZE) - 1) { hasNeighbor = true; } break; case BoxelFace.FRONT: index = (int)(worldPosition.X + (SIZE * ChunkManager.SIZE) * (worldPosition.Y + (SIZE * ChunkManager.SIZE) * (worldPosition.Z - 1))); if (index >= 0 && index < ChunkManager.Instance.Boxels.Length && ChunkManager.Instance.Boxels[index] != BoxelType.NONE && worldPosition.Z != 0) { hasNeighbor = true; } break; case BoxelFace.BACK: index = (int)(worldPosition.X + (SIZE * ChunkManager.SIZE) * (worldPosition.Y + (SIZE * ChunkManager.SIZE) * (worldPosition.Z + 1))); if (index >= 0 && index < ChunkManager.Instance.Boxels.Length && ChunkManager.Instance.Boxels[index] != BoxelType.NONE && worldPosition.Z != (SIZE * ChunkManager.SIZE) - 1) { hasNeighbor = true; } break; case BoxelFace.LEFT: index = (int)((worldPosition.X - 1) + (SIZE * ChunkManager.SIZE) * (worldPosition.Y + (SIZE * ChunkManager.SIZE) * worldPosition.Z)); if (index >= 0 && index < ChunkManager.Instance.Boxels.Length && ChunkManager.Instance.Boxels[index] != BoxelType.NONE && worldPosition.X != 0) { hasNeighbor = true; } break; case BoxelFace.RIGHT: index = (int)((worldPosition.X + 1) + (SIZE * ChunkManager.SIZE) * (worldPosition.Y + (SIZE * ChunkManager.SIZE) * worldPosition.Z)); if (index >= 0 && index < ChunkManager.Instance.Boxels.Length && ChunkManager.Instance.Boxels[index] != BoxelType.NONE && worldPosition.X != (SIZE * ChunkManager.SIZE) - 1) { hasNeighbor = true; } break; } return hasNeighbor; }
/// <summary> /// Creates the vertex buffer for the chunk /// </summary> private void BuildVertexBuffer() { List<int> indices = new List<int>(); List<Vector3> verts = new List<Vector3>(); List<BoxelVertex> vertices = new List<BoxelVertex>(); for (int y = 0; y < SIZE; y++) { for (int x = 0; x < SIZE; x++) { for (int z = 0; z < SIZE; z++) { double xWorld = (Position.X + x); double yWorld = (Position.Y + y); double zWorld = (Position.Z + z); int index = (int)(xWorld + (SIZE * ChunkManager.SIZE) * (yWorld + (SIZE * ChunkManager.SIZE) * zWorld)); BoxelType boxel = ChunkManager.Instance.Boxels[index]; if (boxel != BoxelType.NONE) { Color color = Color.Purple; Vector3b relativePosition = new Vector3b((byte)x, (byte)y, (byte)z); Vector3 worldPosition = relativePosition.AsVector3() + Position; switch (boxel) { case BoxelType.GRASS: //color = new Color(102, 205, 0); color = GameResources.Color; color.R = (byte)(xWorld + color.R); color.G = (byte)(yWorld + color.G); color.B = (byte)(zWorld + color.B); break; case BoxelType.DIRT: color = new Color(139, 101, 8); color.R = (byte)((GameResources.Random.Next(40)) + color.R); color.G = (byte)((GameResources.Random.Next(40)) + color.G); color.B = (byte)((GameResources.Random.Next(40)) + color.B); break; } // Calculate the position of the vertices on the top face. Vector3 topLeftFront = new Vector3(-0.5f, 0.5f, -0.5f) + worldPosition; Vector3 topLeftBack = new Vector3(-0.5f, 0.5f, 0.5f) + worldPosition; Vector3 topRightFront = new Vector3(0.5f, 0.5f, -0.5f) + worldPosition; Vector3 topRightBack = new Vector3(0.5f, 0.5f, 0.5f) + worldPosition; // Calculate the position of the vertices on the bottom face. Vector3 btmLeftFront = new Vector3(-0.5f, -0.5f, -0.5f) + worldPosition; Vector3 btmLeftBack = new Vector3(-0.5f, -0.5f, 0.5f) + worldPosition; Vector3 btmRightFront = new Vector3(0.5f, -0.5f, -0.5f) + worldPosition; Vector3 btmRightBack = new Vector3(0.5f, -0.5f, 0.5f) + worldPosition; // Calculate the position of the vertices on the top face. Vector3b topLeftFrontb = new Vector3b(1, 2, 1) + relativePosition; Vector3b topLeftBackb = new Vector3b(1, 2, 2) + relativePosition; Vector3b topRightFrontb = new Vector3b(2, 2, 1) + relativePosition; Vector3b topRightBackb = new Vector3b(2, 2, 2) + relativePosition; // Calculate the position of the vertices on the bottom face. Vector3b btmLeftFrontb = new Vector3b(1, 1, 1) + relativePosition; Vector3b btmLeftBackb = new Vector3b(1, 1, 2) + relativePosition; Vector3b btmRightFrontb = new Vector3b(2, 1, 1) + relativePosition; Vector3b btmRightBackb = new Vector3b(2, 1, 2) + relativePosition; Vector3b normalFront = new Vector3b(3, 3, 2); Vector3b normalBack = new Vector3b(3, 3, 4); Vector3b normalTop = new Vector3b(3, 4, 3); Vector3b normalBottom = new Vector3b(3, 2, 3); Vector3b normalLeft = new Vector3b(2, 3, 3); Vector3b normalRight = new Vector3b(4, 3, 3); if (!HasNeighbor(boxel, BoxelFace.FRONT, relativePosition)) { // Add the vertices for the FRONT face. vertices.Add(new BoxelVertex(topLeftFrontb, color, normalFront)); vertices.Add(new BoxelVertex(btmLeftFrontb, color, normalFront)); vertices.Add(new BoxelVertex(topRightFrontb, color, normalFront)); vertices.Add(new BoxelVertex(btmLeftFrontb, color, normalFront)); vertices.Add(new BoxelVertex(btmRightFrontb, color, normalFront)); vertices.Add(new BoxelVertex(topRightFrontb, color, normalFront)); int offset = verts.Count; verts.Add(topLeftFront); // 0 verts.Add(btmLeftFront); // 1 verts.Add(topRightFront); // 2 verts.Add(btmRightFront); // 3 indices.Add(0 + offset); indices.Add(1 + offset); indices.Add(2 + offset); indices.Add(3 + offset); indices.Add(2 + offset); indices.Add(1 + offset); } if (!HasNeighbor(boxel, BoxelFace.BACK, relativePosition)) { // Add the verts for the BACK face. vertices.Add(new BoxelVertex(topLeftBackb, color, normalBack)); vertices.Add(new BoxelVertex(topRightBackb, color, normalBack)); vertices.Add(new BoxelVertex(btmLeftBackb, color, normalBack)); vertices.Add(new BoxelVertex(btmLeftBackb, color, normalBack)); vertices.Add(new BoxelVertex(topRightBackb, color, normalBack)); vertices.Add(new BoxelVertex(btmRightBackb, color, normalBack)); int offset = verts.Count; verts.Add(topLeftBack); // 0 verts.Add(topRightBack); // 1 verts.Add(btmLeftBack); // 2 verts.Add(btmRightBack); // 3 indices.Add(0 + offset); indices.Add(1 + offset); indices.Add(2 + offset); indices.Add(3 + offset); indices.Add(2 + offset); indices.Add(1 + offset); } if (!HasNeighbor(boxel, BoxelFace.TOP, relativePosition)) { // Add the verts for the TOP face. vertices.Add(new BoxelVertex(topLeftFrontb, color, normalTop)); vertices.Add(new BoxelVertex(topRightBackb, color, normalTop)); vertices.Add(new BoxelVertex(topLeftBackb, color, normalTop)); vertices.Add(new BoxelVertex(topLeftFrontb, color, normalTop)); vertices.Add(new BoxelVertex(topRightFrontb, color, normalTop)); vertices.Add(new BoxelVertex(topRightBackb, color, normalTop)); int offset = verts.Count; verts.Add(topLeftFront); // 0 verts.Add(topRightBack); // 1 verts.Add(topLeftBack); // 2 verts.Add(topRightFront); // 3 indices.Add(0 + offset); indices.Add(1 + offset); indices.Add(2 + offset); indices.Add(3 + offset); indices.Add(1 + offset); indices.Add(0 + offset); } if (!HasNeighbor(boxel, BoxelFace.BOTTOM, relativePosition)) { // Add the verts for the BOTTOM face. vertices.Add(new BoxelVertex(btmLeftFrontb, color, normalBottom)); vertices.Add(new BoxelVertex(btmLeftBackb, color, normalBottom)); vertices.Add(new BoxelVertex(btmRightBackb, color, normalBottom)); vertices.Add(new BoxelVertex(btmLeftFrontb, color, normalBottom)); vertices.Add(new BoxelVertex(btmRightBackb, color, normalBottom)); vertices.Add(new BoxelVertex(btmRightFrontb, color, normalBottom)); int offset = verts.Count; verts.Add(btmLeftFront); // 0 verts.Add(btmLeftBack); // 1 verts.Add(btmRightBack); // 2 verts.Add(btmRightFront); // 3 indices.Add(0 + offset); indices.Add(1 + offset); indices.Add(2 + offset); indices.Add(3 + offset); indices.Add(0 + offset); indices.Add(2 + offset); } if (!HasNeighbor(boxel, BoxelFace.LEFT, relativePosition)) { // Add the verts for the LEFT face. vertices.Add(new BoxelVertex(topLeftFrontb, color, normalLeft)); vertices.Add(new BoxelVertex(btmLeftBackb, color, normalLeft)); vertices.Add(new BoxelVertex(btmLeftFrontb, color, normalLeft)); vertices.Add(new BoxelVertex(topLeftBackb, color, normalLeft)); vertices.Add(new BoxelVertex(btmLeftBackb, color, normalLeft)); vertices.Add(new BoxelVertex(topLeftFrontb, color, normalLeft)); int offset = verts.Count; verts.Add(topLeftFront); // 0 verts.Add(btmLeftBack); // 1 verts.Add(btmLeftFront); // 2 verts.Add(topLeftBack); // 3 indices.Add(0 + offset); indices.Add(1 + offset); indices.Add(2 + offset); indices.Add(3 + offset); indices.Add(1 + offset); indices.Add(0 + offset); } if (!HasNeighbor(boxel, BoxelFace.RIGHT, relativePosition)) { // Add the verts for the RIGHT face. vertices.Add(new BoxelVertex(topRightFrontb, color, normalRight)); vertices.Add(new BoxelVertex(btmRightFrontb, color, normalRight)); vertices.Add(new BoxelVertex(btmRightBackb, color, normalRight)); vertices.Add(new BoxelVertex(topRightBackb, color, normalRight)); vertices.Add(new BoxelVertex(topRightFrontb, color, normalRight)); vertices.Add(new BoxelVertex(btmRightBackb, color, normalRight)); int offset = verts.Count; verts.Add(topRightFront); // 0 verts.Add(btmRightFront); // 1 verts.Add(btmRightBack); // 2 verts.Add(topRightBack); // 3 indices.Add(0 + offset); indices.Add(1 + offset); indices.Add(2 + offset); indices.Add(3 + offset); indices.Add(0 + offset); indices.Add(1 + offset); } } } } } if (vertices.Count > 0) { _vertexBuffer = new VertexBuffer(GameResources.GraphicsDevice, BoxelVertex.VertexDeclaration, vertices.Count, BufferUsage.None); _vertexBuffer.SetData(vertices.ToArray()); _collisionMesh = new StaticMesh(verts.ToArray(), indices.ToArray()); ChunkManager.Instance.FaceCount += indices.Count / 3; PhysicsManager.Instance.Space.Add(_collisionMesh); } }