private void CreateVerticies(Color color) { Vertices = new ExtendedVertex[RelativeTransforms.Count * 4]; Vector3 topLeftFront = new Vector3(-0.5f * Width, 0.5f * Height, 0.0f); Vector3 topRightFront = new Vector3(0.5f * Width, 0.5f * Height, 0.0f); Vector3 btmLeftFront = new Vector3(-0.5f * Width, -0.5f * Height, 0.0f); Vector3 btmRightFront = new Vector3(0.5f * Width, -0.5f * Height, 0.0f); Indexes = new ushort[RelativeTransforms.Count * 6]; for (int i = 0; i < RelativeTransforms.Count; i++) { int vertOffset = i * 4; Vertices[vertOffset + 0] = new ExtendedVertex(Vector3.Transform(topLeftFront, RelativeTransforms[i]), Tints[i], VertColors[i], UVs.UVs[0], UVs.Bounds); Vertices[vertOffset + 1] = new ExtendedVertex(Vector3.Transform(btmLeftFront, RelativeTransforms[i]), Tints[i], VertColors[i], UVs.UVs[1], UVs.Bounds); Vertices[vertOffset + 2] = new ExtendedVertex(Vector3.Transform(topRightFront, RelativeTransforms[i]), Tints[i], VertColors[i], UVs.UVs[2], UVs.Bounds); Vertices[vertOffset + 3] = new ExtendedVertex(Vector3.Transform(btmRightFront, RelativeTransforms[i]), Tints[i], VertColors[i], UVs.UVs[3], UVs.Bounds); int indOffset = i * 6; Indexes[indOffset + 0] = (ushort)(vertOffset + 1); Indexes[indOffset + 1] = (ushort)(vertOffset + 0); Indexes[indOffset + 2] = (ushort)(vertOffset + 2); Indexes[indOffset + 3] = (ushort)(vertOffset + 1); Indexes[indOffset + 4] = (ushort)(vertOffset + 2); Indexes[indOffset + 5] = (ushort)(vertOffset + 3); } }
private void CreateVerticies(Color color) { Vertices = new ExtendedVertex[RelativeTransforms.Count * 4]; Vector3 topLeftFront = new Vector3(-0.5f * Width, 0.5f * Height, 0.0f); Vector3 topRightFront = new Vector3(0.5f * Width, 0.5f * Height, 0.0f); Vector3 btmLeftFront = new Vector3(-0.5f * Width, -0.5f * Height, 0.0f); Vector3 btmRightFront = new Vector3(0.5f * Width, -0.5f * Height, 0.0f); short[] indices = new short[RelativeTransforms.Count * 6]; for (int i = 0; i < RelativeTransforms.Count; i++) { int vertOffset = i * 4; Vertices[vertOffset + 0] = new ExtendedVertex(Vector3.Transform(topLeftFront, RelativeTransforms[i]), Tints[i], UVs.UVs[0], UVs.Bounds); Vertices[vertOffset + 1] = new ExtendedVertex(Vector3.Transform(btmLeftFront, RelativeTransforms[i]), Tints[i], UVs.UVs[1], UVs.Bounds); Vertices[vertOffset + 2] = new ExtendedVertex(Vector3.Transform(topRightFront, RelativeTransforms[i]), Tints[i], UVs.UVs[2], UVs.Bounds); Vertices[vertOffset + 3] = new ExtendedVertex(Vector3.Transform(btmRightFront, RelativeTransforms[i]), Tints[i], UVs.UVs[3], UVs.Bounds); int indOffset = i * 6; indices[indOffset + 0] = (short)(vertOffset + 1); indices[indOffset + 1] = (short)(vertOffset + 0); indices[indOffset + 2] = (short)(vertOffset + 2); indices[indOffset + 3] = (short)(vertOffset + 1); indices[indOffset + 4] = (short)(vertOffset + 2); indices[indOffset + 5] = (short)(vertOffset + 3); } IndexBuffer = new IndexBuffer(GameState.Game.GraphicsDevice, typeof(short), RelativeTransforms.Count * 6, BufferUsage.None); IndexBuffer.SetData(indices); }
public BillboardPrimitive() { Vertices = new ExtendedVertex[4]; Indexes = new ushort[] { 1, 0, 2, 1, 2, 3 }; }
public void SetFrame(SpriteSheet Sheet, Rectangle Rect, float Width, float Height, Color Color, Color VertColor, bool Flipped) { var texture = Sheet.GetTexture(); var tileBounds = new Vector4( ((float)Rect.X / texture.Width) + 0.001f, ((float)Rect.Y / texture.Height) + 0.001f, ((float)Rect.Right / texture.Width) - 0.001f, ((float)Rect.Bottom / texture.Height) - 0.001f); Vertices[0] = new ExtendedVertex( new Vector3(-0.5f * Width, 0.5f * Height, 0.0f), Color, VertColor, new Vector2((float)Rect.Right / texture.Width, (float)Rect.Y / texture.Height), tileBounds); Vertices[1] = new ExtendedVertex( new Vector3(-0.5f * Width, -0.5f * Height, 0.0f), Color, VertColor, new Vector2((float)Rect.Right / texture.Width, (float)Rect.Bottom / texture.Height), tileBounds); Vertices[2] = new ExtendedVertex( new Vector3(0.5f * Width, 0.5f * Height, 0.0f), Color, VertColor, new Vector2((float)Rect.X / texture.Width, (float)Rect.Y / texture.Height), tileBounds); Vertices[3] = new ExtendedVertex( new Vector3(0.5f * Width, -0.5f * Height, 0.0f), Color, VertColor, new Vector2((float)Rect.X / texture.Width, (float)Rect.Bottom / texture.Height), tileBounds); //GameState.Game.GraphicsDevice.SetVertexBuffer(null); if (VertexBuffer == null) { ResetBuffer(GameState.Game.GraphicsDevice); } else { var buffers = GameState.Game.GraphicsDevice.GetVertexBuffers(); if (buffers.Any(buffer => buffer.VertexBuffer == VertexBuffer)) { GameState.Game.GraphicsDevice.SetVertexBuffer(null); } VertexBuffer.SetData(Vertices); } }
public void AddTriangle(ExtendedVertex A, ExtendedVertex B, ExtendedVertex C) { var index = (short)VertexCount; AddVertex(A); AddVertex(B); AddVertex(C); AddIndex(index); AddIndex((short)(index + 1)); AddIndex((short)(index + 2)); }
private void CreateVerticies() { Indexes = new ushort[36]; FlippedIndexes = new ushort[36]; Vertices = new ExtendedVertex[NumVertices]; // Calculate the position of the vertices on the top face. Vector3 topLeftFront = new Vector3(0.0f, Height, 0.0f); Vector3 topLeftBack = new Vector3(0.0f, Height, 1.0f); Vector3 topRightFront = new Vector3(Width, Height, 0.0f); Vector3 topRightBack = new Vector3(Width, Height, 1.0f); // Calculate the position of the vertices on the bottom face. Vector3 btmLeftFront = new Vector3(0.0f, 0.0f, 0.0f); Vector3 btmLeftBack = new Vector3(0.0f, 0.0f, 1.0f); Vector3 btmRightFront = new Vector3(Width, 0.0f, 0.0f); Vector3 btmRightBack = new Vector3(Width, 0.0f, 1.0f); // Normal vectors for each face (needed for lighting / display) // Add the vertices for the FRONT face. Vertices[0] = new ExtendedVertex(topLeftFront, Color.White, Color.White, UVs.Uvs[0], UVs.Bounds[0]); Vertices[1] = new ExtendedVertex(btmLeftFront, Color.White, Color.White, UVs.Uvs[1], UVs.Bounds[0]); Vertices[2] = new ExtendedVertex(btmRightFront, Color.White, Color.White, UVs.Uvs[2], UVs.Bounds[0]); Vertices[3] = new ExtendedVertex(topRightFront, Color.White, Color.White, UVs.Uvs[3], UVs.Bounds[0]); /* * 0 . . . 3 * . . . * . . . * . . . * 1 . . . 2 */ Indexes[0] = 0; Indexes[1] = 1; Indexes[2] = 3; Indexes[3] = 3; Indexes[4] = 1; Indexes[5] = 2; /* * 0 . . . 3 * . . . * . . . * . . . * 1 . . . 2 */ FlippedIndexes[0] = 0; FlippedIndexes[1] = 1; FlippedIndexes[2] = 2; FlippedIndexes[3] = 3; FlippedIndexes[4] = 0; FlippedIndexes[5] = 2; // Add the vertices for the BACK face. Vertices[4] = new ExtendedVertex(topRightBack, Color.White, Color.White, UVs.Uvs[4], UVs.Bounds[1]); Vertices[5] = new ExtendedVertex(btmRightBack, Color.White, Color.White, UVs.Uvs[5], UVs.Bounds[1]); Vertices[6] = new ExtendedVertex(btmLeftBack, Color.White, Color.White, UVs.Uvs[6], UVs.Bounds[1]); Vertices[7] = new ExtendedVertex(topLeftBack, Color.White, Color.White, UVs.Uvs[7], UVs.Bounds[1]); /* * 4 . . . 7 * . . . * . . . * . . . * 5 . . . 6 */ Indexes[6] = 4; Indexes[7] = 5; Indexes[8] = 7; Indexes[9] = 7; Indexes[10] = 5; Indexes[11] = 6; /* * 4 . . . 7 * . . . * . . . * . . . * 5 . . . 6 */ FlippedIndexes[6] = 4; FlippedIndexes[7] = 5; FlippedIndexes[8] = 6; FlippedIndexes[9] = 6; FlippedIndexes[10] = 7; FlippedIndexes[11] = 4; // Add the vertices for the TOP face. Vertices[8] = new ExtendedVertex(topLeftBack, Color.White, Color.White, UVs.Uvs[8], UVs.Bounds[2]); Vertices[9] = new ExtendedVertex(topLeftFront, Color.White, Color.White, UVs.Uvs[9], UVs.Bounds[2]); Vertices[10] = new ExtendedVertex(topRightFront, Color.White, Color.White, UVs.Uvs[10], UVs.Bounds[2]); Vertices[11] = new ExtendedVertex(topRightBack, Color.White, Color.White, UVs.Uvs[11], UVs.Bounds[2]); /* * 8 . . .11 * . . . * . . . * . . . * 9 . . . 10 */ Indexes[12] = 8; Indexes[13] = 9; Indexes[14] = 11; Indexes[15] = 10; Indexes[16] = 11; Indexes[17] = 9; /* * 8 . . .11 * . . . * . . . * . . . * 9 . . .10 */ FlippedIndexes[12] = 8; FlippedIndexes[13] = 10; FlippedIndexes[14] = 11; FlippedIndexes[15] = 10; FlippedIndexes[16] = 8; FlippedIndexes[17] = 9; // Add the vertices for the BOTTOM face. Vertices[12] = new ExtendedVertex(btmLeftFront, Color.White, Color.White, UVs.Uvs[12], UVs.Bounds[3]); Vertices[13] = new ExtendedVertex(btmLeftBack, Color.White, Color.White, UVs.Uvs[13], UVs.Bounds[3]); Vertices[14] = new ExtendedVertex(btmRightBack, Color.White, Color.White, UVs.Uvs[14], UVs.Bounds[3]); Vertices[15] = new ExtendedVertex(btmRightFront, Color.White, Color.White, UVs.Uvs[15], UVs.Bounds[3]); /* * 12. . .15 * . . . * . . . * . . . * 13. . .14 */ Indexes[18] = 12; Indexes[19] = 13; Indexes[20] = 15; Indexes[21] = 15; Indexes[22] = 13; Indexes[23] = 14; /* * 12. . .15 * . . . * . . . * . . . * 13. . .14 */ FlippedIndexes[18] = 12; FlippedIndexes[19] = 13; FlippedIndexes[20] = 14; FlippedIndexes[21] = 15; FlippedIndexes[22] = 12; FlippedIndexes[23] = 14; // Add the vertices for the LEFT face. Vertices[16] = new ExtendedVertex(topLeftBack, Color.White, Color.White, UVs.Uvs[16], UVs.Bounds[4]); Vertices[17] = new ExtendedVertex(btmLeftBack, Color.White, Color.White, UVs.Uvs[17], UVs.Bounds[4]); Vertices[18] = new ExtendedVertex(btmLeftFront, Color.White, Color.White, UVs.Uvs[18], UVs.Bounds[4]); Vertices[19] = new ExtendedVertex(topLeftFront, Color.White, Color.White, UVs.Uvs[19], UVs.Bounds[4]); /* * 16. . .19 * . . . * . . . * . . . * 17. . .18 */ Indexes[24] = 16; Indexes[25] = 17; Indexes[26] = 19; Indexes[27] = 18; Indexes[28] = 19; Indexes[29] = 17; /* * 16. . .19 * . . . * . . . * . . . * 17. . .18 */ FlippedIndexes[24] = 16; FlippedIndexes[25] = 17; FlippedIndexes[26] = 18; FlippedIndexes[27] = 18; FlippedIndexes[28] = 19; FlippedIndexes[29] = 16; // Add the vertices for the RIGHT face. Vertices[20] = new ExtendedVertex(topRightFront, Color.White, Color.White, UVs.Uvs[20], UVs.Bounds[5]); Vertices[21] = new ExtendedVertex(btmRightFront, Color.White, Color.White, UVs.Uvs[21], UVs.Bounds[5]); Vertices[22] = new ExtendedVertex(btmRightBack, Color.White, Color.White, UVs.Uvs[22], UVs.Bounds[5]); Vertices[23] = new ExtendedVertex(topRightBack, Color.White, Color.White, UVs.Uvs[23], UVs.Bounds[5]); /* * 20. . .23 * . . . * . . . * . . . * 21. . .22 */ Indexes[30] = 20; Indexes[31] = 21; Indexes[32] = 23; Indexes[33] = 23; Indexes[34] = 21; Indexes[35] = 22; /* * 20. . .23 * . . . * . . . * . . . * 21. . .22 */ FlippedIndexes[30] = 20; FlippedIndexes[31] = 21; FlippedIndexes[32] = 22; FlippedIndexes[33] = 23; FlippedIndexes[34] = 20; FlippedIndexes[35] = 22; try { IndexBuffer = new DynamicIndexBuffer(GameState.Game.GraphicsDevice, typeof(ushort), Indexes.Length, BufferUsage.WriteOnly); IndexBuffer.SetData(Indexes); } catch (Exception exception) { IndexBuffer = null; } Faces = new List <FaceDescriptor> { new FaceDescriptor { Face = BoxFace.Top, VertexCount = 4, IndexCount = 6, IndexOffset = 12, VertexOffset = 8 }, new FaceDescriptor { Face = BoxFace.Bottom, VertexCount = 4, IndexCount = 6, IndexOffset = 18, VertexOffset = 12 }, new FaceDescriptor { Face = BoxFace.Left, VertexCount = 4, IndexCount = 6, IndexOffset = 24, VertexOffset = 16 }, new FaceDescriptor { Face = BoxFace.Right, VertexCount = 4, IndexCount = 6, IndexOffset = 30, VertexOffset = 20 }, new FaceDescriptor { Face = BoxFace.Front, VertexCount = 4, IndexCount = 6, IndexOffset = 0, VertexOffset = 0 }, new FaceDescriptor { Face = BoxFace.Back, VertexCount = 4, IndexCount = 6, IndexOffset = 6, VertexOffset = 4 }, }; }
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 void CreateVerticies() { Indices = new short[36]; Vertices = new ExtendedVertex[NumVertices]; // Calculate the position of the vertices on the top face. Vector3 topLeftFront = new Vector3(0.0f, Height, 0.0f); Vector3 topLeftBack = new Vector3(0.0f, Height, Depth); Vector3 topRightFront = new Vector3(Width, Height, 0.0f); Vector3 topRightBack = new Vector3(Width, Height, Depth); // Calculate the position of the vertices on the bottom face. Vector3 btmLeftFront = new Vector3(0.0f, 0.0f, 0.0f); Vector3 btmLeftBack = new Vector3(0.0f, 0.0f, Depth); Vector3 btmRightFront = new Vector3(Width, 0.0f, 0.0f); Vector3 btmRightBack = new Vector3(Width, 0.0f, Depth); // Normal vectors for each face (needed for lighting / display) // Add the vertices for the FRONT face. Vertices[0] = new ExtendedVertex(topLeftFront, Color.White, UVs.Uvs[0], UVs.Bounds[0]); Vertices[1] = new ExtendedVertex(btmLeftFront, Color.White, UVs.Uvs[1], UVs.Bounds[0]); Vertices[2] = new ExtendedVertex(topRightFront, Color.White, UVs.Uvs[2], UVs.Bounds[0]); Vertices[3] = new ExtendedVertex(btmRightFront, Color.White, UVs.Uvs[3], UVs.Bounds[0]); Indices[0] = 0; Indices[1] = 1; Indices[2] = 2; Indices[3] = 2; Indices[4] = 1; Indices[5] = 3; // Add the vertices for the BACK face. Vertices[4] = new ExtendedVertex(topLeftBack, Color.White, UVs.Uvs[4], UVs.Bounds[1]); Vertices[5] = new ExtendedVertex(topRightBack, Color.White, UVs.Uvs[5], UVs.Bounds[1]); Vertices[6] = new ExtendedVertex(btmLeftBack, Color.White, UVs.Uvs[6], UVs.Bounds[1]); Vertices[7] = new ExtendedVertex(btmRightBack, Color.White, UVs.Uvs[7], UVs.Bounds[1]); Indices[6] = 4; Indices[7] = 5; Indices[8] = 6; Indices[9] = 7; Indices[10] = 6; Indices[11] = 5; // Add the vertices for the TOP face. Vertices[8] = new ExtendedVertex(topLeftFront, Color.White, UVs.Uvs[8], UVs.Bounds[2]); Vertices[9] = new ExtendedVertex(topRightBack, Color.White, UVs.Uvs[9], UVs.Bounds[2]); Vertices[10] = new ExtendedVertex(topLeftBack, Color.White, UVs.Uvs[10], UVs.Bounds[2]); Vertices[11] = new ExtendedVertex(topRightFront, Color.White, UVs.Uvs[11], UVs.Bounds[2]); Indices[12] = 8; Indices[13] = 9; Indices[14] = 10; Indices[15] = 9; Indices[16] = 8; Indices[17] = 11; // Add the vertices for the BOTTOM face. Vertices[12] = new ExtendedVertex(btmLeftFront, Color.White, UVs.Uvs[12], UVs.Bounds[3]); Vertices[13] = new ExtendedVertex(btmLeftBack, Color.White, UVs.Uvs[13], UVs.Bounds[3]); Vertices[14] = new ExtendedVertex(btmRightBack, Color.White, UVs.Uvs[14], UVs.Bounds[3]); Vertices[15] = new ExtendedVertex(btmRightFront, Color.White, UVs.Uvs[15], UVs.Bounds[3]); Indices[18] = 12; Indices[19] = 13; Indices[20] = 14; Indices[21] = 15; Indices[22] = 12; Indices[23] = 14; // Add the vertices for the LEFT face. Vertices[16] = new ExtendedVertex(topLeftFront, Color.White, UVs.Uvs[16], UVs.Bounds[4]); Vertices[17] = new ExtendedVertex(btmLeftBack, Color.White, UVs.Uvs[17], UVs.Bounds[4]); Vertices[18] = new ExtendedVertex(btmLeftFront, Color.White, UVs.Uvs[18], UVs.Bounds[4]); Vertices[19] = new ExtendedVertex(topLeftBack, Color.White, UVs.Uvs[19], UVs.Bounds[4]); Indices[24] = 16; Indices[25] = 17; Indices[26] = 18; Indices[27] = 17; Indices[28] = 16; Indices[29] = 19; // Add the vertices for the RIGHT face. Vertices[20] = new ExtendedVertex(topRightFront, Color.White, UVs.Uvs[20], UVs.Bounds[5]); Vertices[21] = new ExtendedVertex(btmRightFront, Color.White, UVs.Uvs[21], UVs.Bounds[5]); Vertices[22] = new ExtendedVertex(btmRightBack, Color.White, UVs.Uvs[22], UVs.Bounds[5]); Vertices[23] = new ExtendedVertex(topRightBack, Color.White, UVs.Uvs[23], UVs.Bounds[5]); Indices[30] = 20; Indices[31] = 21; Indices[32] = 22; Indices[33] = 23; Indices[34] = 20; Indices[35] = 22; IndexBuffer = new IndexBuffer(GameState.Game.GraphicsDevice, typeof(short), Indices.Length, BufferUsage.WriteOnly); IndexBuffer.SetData(Indices); }
private void CreateVerticies() { Vertices = new ExtendedVertex[NumVertices]; // Calculate the position of the vertices on the top face. Vector3 topLeftFront = new Vector3(0.0f, Height, 0.0f); Vector3 topLeftBack = new Vector3(0.0f, Height, Depth); Vector3 topRightFront = new Vector3(Width, Height, 0.0f); Vector3 topRightBack = new Vector3(Width, Height, Depth); // Calculate the position of the vertices on the bottom face. Vector3 btmLeftFront = new Vector3(0.0f, 0.0f, 0.0f); Vector3 btmLeftBack = new Vector3(0.0f, 0.0f, Depth); Vector3 btmRightFront = new Vector3(Width, 0.0f, 0.0f); Vector3 btmRightBack = new Vector3(Width, 0.0f, Depth); // Normal vectors for each face (needed for lighting / display) /* * Vector3 normalFront = new Vector3(0.0f, 0.0f, 1.0f) * SideLength; * Vector3 normalBack = new Vector3(0.0f, 0.0f, -1.0f) * SideLength; * Vector3 normalTop = new Vector3(0.0f, 1.0f, 0.0f) * SideLength; * Vector3 normalBottom = new Vector3(0.0f, -1.0f, 0.0f) * SideLength; * Vector3 normalLeft = new Vector3(-1.0f, 0.0f, 0.0f) * SideLength; * Vector3 normalRight = new Vector3(1.0f, 0.0f, 0.0f) * SideLength; */ // Add the vertices for the FRONT face. Vertices[0] = new ExtendedVertex(topLeftFront, Color.White, UVs.m_uvs[0], UVs.Bounds[0]); Vertices[1] = new ExtendedVertex(btmLeftFront, Color.White, UVs.m_uvs[1], UVs.Bounds[0]); Vertices[2] = new ExtendedVertex(topRightFront, Color.White, UVs.m_uvs[2], UVs.Bounds[0]); Vertices[3] = new ExtendedVertex(btmLeftFront, Color.White, UVs.m_uvs[3], UVs.Bounds[0]); Vertices[4] = new ExtendedVertex(btmRightFront, Color.White, UVs.m_uvs[4], UVs.Bounds[0]); Vertices[5] = new ExtendedVertex(topRightFront, Color.White, UVs.m_uvs[5], UVs.Bounds[0]); // Add the vertices for the BACK face. Vertices[6] = new ExtendedVertex(topLeftBack, Color.White, UVs.m_uvs[6], UVs.Bounds[1]); Vertices[7] = new ExtendedVertex(topRightBack, Color.White, UVs.m_uvs[7], UVs.Bounds[1]); Vertices[8] = new ExtendedVertex(btmLeftBack, Color.White, UVs.m_uvs[8], UVs.Bounds[1]); Vertices[9] = new ExtendedVertex(btmLeftBack, Color.White, UVs.m_uvs[9], UVs.Bounds[1]); Vertices[10] = new ExtendedVertex(topRightBack, Color.White, UVs.m_uvs[10], UVs.Bounds[1]); Vertices[11] = new ExtendedVertex(btmRightBack, Color.White, UVs.m_uvs[11], UVs.Bounds[1]); // Add the vertices for the TOP face. Vertices[12] = new ExtendedVertex(topLeftFront, Color.White, UVs.m_uvs[12], UVs.Bounds[2]); Vertices[13] = new ExtendedVertex(topRightBack, Color.White, UVs.m_uvs[13], UVs.Bounds[2]); Vertices[14] = new ExtendedVertex(topLeftBack, Color.White, UVs.m_uvs[14], UVs.Bounds[2]); Vertices[15] = new ExtendedVertex(topLeftFront, Color.White, UVs.m_uvs[15], UVs.Bounds[2]); Vertices[16] = new ExtendedVertex(topRightFront, Color.White, UVs.m_uvs[16], UVs.Bounds[2]); Vertices[17] = new ExtendedVertex(topRightBack, Color.White, UVs.m_uvs[17], UVs.Bounds[2]); // Add the vertices for the BOTTOM face. Vertices[18] = new ExtendedVertex(btmLeftFront, Color.White, UVs.m_uvs[18], UVs.Bounds[3]); Vertices[19] = new ExtendedVertex(btmLeftBack, Color.White, UVs.m_uvs[19], UVs.Bounds[3]); Vertices[20] = new ExtendedVertex(btmRightBack, Color.White, UVs.m_uvs[20], UVs.Bounds[3]); Vertices[21] = new ExtendedVertex(btmLeftFront, Color.White, UVs.m_uvs[21], UVs.Bounds[3]); Vertices[22] = new ExtendedVertex(btmRightBack, Color.White, UVs.m_uvs[22], UVs.Bounds[3]); Vertices[23] = new ExtendedVertex(btmRightFront, Color.White, UVs.m_uvs[23], UVs.Bounds[3]); // Add the vertices for the LEFT face. Vertices[24] = new ExtendedVertex(topLeftFront, Color.White, UVs.m_uvs[24], UVs.Bounds[4]); Vertices[25] = new ExtendedVertex(btmLeftBack, Color.White, UVs.m_uvs[25], UVs.Bounds[4]); Vertices[26] = new ExtendedVertex(btmLeftFront, Color.White, UVs.m_uvs[26], UVs.Bounds[4]); Vertices[27] = new ExtendedVertex(topLeftBack, Color.White, UVs.m_uvs[27], UVs.Bounds[4]); Vertices[28] = new ExtendedVertex(btmLeftBack, Color.White, UVs.m_uvs[28], UVs.Bounds[4]); Vertices[29] = new ExtendedVertex(topLeftFront, Color.White, UVs.m_uvs[29], UVs.Bounds[4]); // Add the vertices for the RIGHT face. Vertices[30] = new ExtendedVertex(topRightFront, Color.White, UVs.m_uvs[30], UVs.Bounds[5]); Vertices[31] = new ExtendedVertex(btmRightFront, Color.White, UVs.m_uvs[31], UVs.Bounds[5]); Vertices[32] = new ExtendedVertex(btmRightBack, Color.White, UVs.m_uvs[32], UVs.Bounds[5]); Vertices[33] = new ExtendedVertex(topRightBack, Color.White, UVs.m_uvs[33], UVs.Bounds[5]); Vertices[34] = new ExtendedVertex(topRightFront, Color.White, UVs.m_uvs[34], UVs.Bounds[5]); Vertices[35] = new ExtendedVertex(btmRightBack, Color.White, UVs.m_uvs[35], UVs.Bounds[5]); }
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 IEnumerable <ExtendedVertex> CreateWaterFace(Voxel voxel, BoxFace face, VoxelChunk chunk, int x, int y, int z, int totalDepth, bool top) { List <ExtendedVertex> toReturn = new List <ExtendedVertex>(); int idx = 0; int c = 0; int vertOffset = 0; int numVerts = 0; m_canconicalPrimitive.GetFace(face, m_canconicalPrimitive.UVs, out idx, out c, out vertOffset, out numVerts); for (int i = idx; i < idx + c; i++) { toReturn.Add(m_canconicalPrimitive.Vertices[m_canconicalPrimitive.Indices[i]]); } Vector3 origin = chunk.Origin + new Vector3(x, y, z); List <Voxel> neighborsVertex = new List <Voxel>(); for (int i = 0; i < toReturn.Count; i++) { VoxelVertex currentVertex = VoxelChunk.GetNearestDelta(toReturn[i].Position); chunk.GetNeighborsVertex(currentVertex, voxel, neighborsVertex); int index = chunk.Data.IndexAt(x, y, z); float averageWaterLevel = chunk.Data.Water[index].WaterLevel; float count = 1.0f; float emptyNeighbors = 0.0f; foreach (byte level in neighborsVertex.Select(vox => vox.WaterLevel)) { averageWaterLevel += level; count++; if (level < 1) { emptyNeighbors++; } } averageWaterLevel = averageWaterLevel / count; float averageWaterHeight = (float)averageWaterLevel / 255.0f; float puddleness = 0; Vector2 uv; float foaminess = emptyNeighbors / count; if (foaminess <= 0.5f) { foaminess = 0.0f; } if (totalDepth < 5) { foaminess = 0.75f; puddleness = 0; uv = new Vector2((toReturn[i].Position.X + origin.X) / 80.0f, (toReturn[i].Position.Z + origin.Z) / 80.0f); } else { uv = new Vector2((toReturn[i].Position.X + origin.X) / 80.0f, (toReturn[i].Position.Z + origin.Z) / 80.0f); } Vector4 bounds = new Vector4(0, 0, 1, 1); if (chunk.Data.Water[index].IsFalling || !top) { averageWaterHeight = 1.0f; } if (face == BoxFace.Top) { toReturn[i] = new ExtendedVertex(toReturn[i].Position + origin + new Vector3(0, (averageWaterHeight * 0.4f - 1.0f), 0), new Color(foaminess, puddleness, (float)totalDepth / 512.0f, 1.0f), Color.White, uv, bounds); } else { Vector3 offset = Vector3.Zero; switch (face) { case BoxFace.Back: case BoxFace.Front: uv = new Vector2((Math.Abs(toReturn[i].Position.X + origin.X) / 80.0f), (Math.Abs(toReturn[i].Position.Y + origin.Y) / 80.0f)); foaminess = 1.0f; offset = new Vector3(0, -0.5f, 0); break; case BoxFace.Right: case BoxFace.Left: uv = new Vector2((Math.Abs(toReturn[i].Position.Z + origin.Z) / 80.0f), (Math.Abs(toReturn[i].Position.Y + origin.Y) / 80.0f)); foaminess = 1.0f; offset = new Vector3(0, -0.5f, 0); break; case BoxFace.Top: offset = new Vector3(0, -0.5f, 0); break; } toReturn[i] = new ExtendedVertex(toReturn[i].Position + origin + offset, new Color(foaminess, 0.0f, 1.0f, 1.0f), Color.White, uv, bounds); } } return(toReturn); }
public void AddVertex(ExtendedVertex Vertex) { EnsureSpace(ref Vertices, VertexCount); Vertices[VertexCount] = Vertex; VertexCount += 1; }
// This will loop through the whole world and draw out all liquid primatives that are handed to the function. public static void InitializePrimativesFromChunk(VoxelChunk chunk, List <LiquidPrimitive> primitivesToInit) { LiquidPrimitive[] lps = new LiquidPrimitive[(int)LiquidType.Count]; if (!AddCaches(primitivesToInit, ref lps)) { return; } LiquidType curLiqType = LiquidType.None; LiquidPrimitive curPrimitive = null; ExtendedVertex[] curVertices = null; ushort[] curIndexes = null; int[] maxVertices = new int[lps.Length]; int[] maxIndexes = new int[lps.Length]; int maxVertex = 0; int maxIndex = 0; int totalFaces = 6; bool fogOfWar = GameSettings.Current.FogofWar; for (int globalY = chunk.Origin.Y; globalY < Math.Min(chunk.Manager.World.Renderer.PersistentSettings.MaxViewingLevel + 1, chunk.Origin.Y + VoxelConstants.ChunkSizeY); globalY++) { var y = globalY - chunk.Origin.Y; if (chunk.Data.LiquidPresent[y] == 0) { continue; } for (int x = 0; x < VoxelConstants.ChunkSizeX; x++) { for (int z = 0; z < VoxelConstants.ChunkSizeZ; z++) { var voxel = VoxelHandle.UnsafeCreateLocalHandle(chunk, new LocalVoxelCoordinate(x, y, z)); if (fogOfWar && !voxel.IsExplored) { continue; } if (voxel.LiquidLevel > 0) { var liqType = voxel.LiquidType; // We need to see if we changed types and should change the data we are writing to. if (liqType != curLiqType) { LiquidPrimitive newPrimitive = lps[(int)liqType]; // We weren't passed a LiquidPrimitive object to work with for this type so we'll skip it. if (newPrimitive == null) { continue; } maxVertices[(int)curLiqType] = maxVertex; maxIndexes[(int)curLiqType] = maxIndex; curVertices = newPrimitive.Vertices; curIndexes = newPrimitive.Indexes; curLiqType = liqType; curPrimitive = newPrimitive; maxVertex = maxVertices[(int)liqType]; maxIndex = maxIndexes[(int)liqType]; } int facesToDraw = 0; for (int i = 0; i < totalFaces; i++) { BoxFace face = (BoxFace)i; // We won't draw the bottom face. This might be needed down the line if we add transparent tiles like glass. if (face == BoxFace.Bottom) { continue; } var delta = faceDeltas[(int)face]; // Pull the current neighbor DestinationVoxel based on the face it would be touching. var vox = VoxelHelpers.GetNeighbor(voxel, delta); if (vox.IsValid) { if (face == BoxFace.Top) { if (!(vox.LiquidLevel == 0 || y == (int)chunk.Manager.World.Renderer.PersistentSettings.MaxViewingLevel)) { cache.drawFace[(int)face] = false; continue; } } else { if (vox.LiquidLevel != 0 || !vox.IsEmpty) { cache.drawFace[(int)face] = false; continue; } } } else { cache.drawFace[(int)face] = false; continue; } cache.drawFace[(int)face] = true; facesToDraw++; } // There's no faces to draw on this voxel. Let's go to the next one. if (facesToDraw == 0) { continue; } // Now we check to see if we need to resize the current Vertex array. int vertexSizeIncrease = facesToDraw * 4; int indexSizeIncrease = facesToDraw * 6; lock (curPrimitive.VertexLock) { // Check vertex array size if (curVertices == null) { curVertices = new ExtendedVertex[256]; curPrimitive.Vertices = curVertices; } else if (curVertices.Length <= maxVertex + vertexSizeIncrease) { ExtendedVertex[] newVerts = new ExtendedVertex[MathFunctions.NearestPowerOf2(maxVertex + vertexSizeIncrease)]; curVertices.CopyTo(newVerts, 0); curVertices = newVerts; curPrimitive.Vertices = curVertices; } // Check index array size if (curIndexes == null) { curIndexes = new ushort[256]; curPrimitive.Indexes = curIndexes; } else if (curIndexes.Length <= maxIndex + indexSizeIncrease) { ushort[] newIdxs = new ushort[MathFunctions.NearestPowerOf2(maxIndex + indexSizeIncrease)]; curIndexes.CopyTo(newIdxs, 0); curIndexes = newIdxs; curPrimitive.Indexes = curIndexes; } } // Now we have a list of all the faces that will need to be drawn. Let's draw them. CreateWaterFaces(voxel, chunk, x, y, z, curVertices, curIndexes, maxVertex, maxIndex); // Finally increase the size so we can move on. maxVertex += vertexSizeIncrease; maxIndex += indexSizeIncrease; } } } } // The last thing we need to do is make sure we set the current primative's maxVertices to the right value. maxVertices[(int)curLiqType] = maxVertex; maxIndexes[(int)curLiqType] = maxIndex; // Now actually force the VertexBuffer to be recreated in each primative we worked with. for (int i = 0; i < lps.Length; i++) { LiquidPrimitive updatedPrimative = lps[i]; if (updatedPrimative == null) { continue; } maxVertex = maxVertices[i]; maxIndex = maxIndexes[i]; if (maxVertex > 0) { try { lock (updatedPrimative.VertexLock) { updatedPrimative.VertexCount = maxVertex; updatedPrimative.IndexCount = maxIndex; updatedPrimative.VertexBuffer = null; updatedPrimative.IndexBuffer = null; } } catch (global::System.Threading.AbandonedMutexException e) { Console.Error.WriteLine(e.Message); } } else { try { lock (updatedPrimative.VertexLock) { updatedPrimative.VertexBuffer = null; updatedPrimative.Vertices = null; updatedPrimative.IndexBuffer = null; updatedPrimative.Indexes = null; updatedPrimative.VertexCount = 0; updatedPrimative.IndexCount = 0; } } catch (global::System.Threading.AbandonedMutexException e) { Console.Error.WriteLine(e.Message); } } updatedPrimative.IsBuilding = false; } cache.inUse = false; cache = null; }
public void InitializeFromChunk(VoxelChunk chunk, GraphicsDevice graphics) { if (chunk == null) { return; } rebuildMutex.WaitOne(); if (isRebuilding) { rebuildMutex.ReleaseMutex(); return; } isRebuilding = true; rebuildMutex.ReleaseMutex(); int[] ambientValues = new int[4]; int maxIndex = 0; int maxVertex = 0; Voxel v = chunk.MakeVoxel(0, 0, 0); Voxel voxelOnFace = chunk.MakeVoxel(0, 0, 0); Voxel[] manhattanNeighbors = new Voxel[4]; BoxPrimitive bedrockModel = VoxelLibrary.GetPrimitive("Bedrock"); Voxel worldVoxel = new Voxel(); if (Vertices == null) { Vertices = new ExtendedVertex[1024]; } if (Indexes == null) { Indexes = new ushort[512]; } for (int y = 0; y < Math.Min(chunk.Manager.ChunkData.MaxViewingLevel + 1, chunk.SizeY); y++) { for (int x = 0; x < chunk.SizeX; x++) { for (int z = 0; z < chunk.SizeZ; z++) { v.GridPosition = new Vector3(x, y, z); if ((v.IsExplored && v.IsEmpty) || !v.IsVisible) { continue; } BoxPrimitive primitive = VoxelLibrary.GetPrimitive(v.Type); if (v.IsExplored && primitive == null) { continue; } if (!v.IsExplored) { primitive = bedrockModel; } Color tint = v.Type.Tint; BoxPrimitive.BoxTextureCoords uvs = primitive.UVs; if (v.Type.HasTransitionTextures && v.IsExplored) { uvs = v.ComputeTransitionTexture(manhattanNeighbors); } for (int i = 0; i < 6; i++) { BoxFace face = (BoxFace)i; Vector3 delta = FaceDeltas[(int)face]; faceExists[(int)face] = chunk.IsCellValid(x + (int)delta.X, y + (int)delta.Y, z + (int)delta.Z); drawFace[(int)face] = true; if (faceExists[(int)face]) { voxelOnFace.GridPosition = new Vector3(x + (int)delta.X, y + (int)delta.Y, z + (int)delta.Z); drawFace[(int)face] = (voxelOnFace.IsExplored && 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[(int)face] = !success || (worldVoxel.IsExplored && 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[(int)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 = maxVertex; for (int vertOffset = 0; vertOffset < vertexCount; vertOffset++) { ExtendedVertex vert = primitive.Vertices[vertOffset + vertexIndex]; VoxelVertex bestKey = primitive.Deltas[vertOffset + vertexIndex]; Color color = v.Chunk.Data.GetColor(x, y, z, bestKey); ambientValues[vertOffset] = color.G; 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)); } } if (maxVertex >= Vertices.Length) { ExtendedVertex[] newVertices = new ExtendedVertex[Vertices.Length * 2]; Vertices.CopyTo(newVertices, 0); Vertices = newVertices; } Vertices[maxVertex] = new ExtendedVertex(vert.Position + v.Position + VertexNoise.GetNoiseVectorFromRepeatingTexture( vert.Position + v.Position) + offset, color, tint, uvs.Uvs[vertOffset + vertexIndex] + texOffset, uvs.Bounds[faceIndex / 6]); maxVertex++; } bool flippedQuad = ambientValues[0] + ambientValues[2] > ambientValues[1] + ambientValues[3]; for (int idx = faceIndex; idx < faceCount + faceIndex; idx++) { if (maxIndex >= Indexes.Length) { ushort[] indexes = new ushort[Indexes.Length * 2]; Indexes.CopyTo(indexes, 0); Indexes = indexes; } ushort vertexOffset = flippedQuad ? primitive.FlippedIndexes[idx] : primitive.Indexes[idx]; ushort vertexOffset0 = flippedQuad? primitive.FlippedIndexes[faceIndex] : primitive.Indexes[faceIndex]; Indexes[maxIndex] = (ushort)((int)indexOffset + (int)((int)vertexOffset - (int)vertexOffset0)); maxIndex++; } } } } } MaxIndex = maxIndex; MaxVertex = maxVertex; GenerateLightmap(chunk.Manager.ChunkData.Tilemap.Bounds); isRebuilding = false; //chunk.PrimitiveMutex.WaitOne(); chunk.NewPrimitive = this; chunk.NewPrimitiveReceived = true; //chunk.PrimitiveMutex.ReleaseMutex(); }
// This will loop through the whole world and draw out all liquid primatives that are handed to the function. public static void InitializePrimativesFromChunk(VoxelChunk chunk, List <LiquidPrimitive> primitivesToInit) { LiquidPrimitive[] lps = new LiquidPrimitive[(int)LiquidType.Count]; // We are going to first set up the internal array. foreach (LiquidPrimitive lp in primitivesToInit) { if (lp != null) { lps[(int)lp.LiqType] = lp; } } // We are going to lock around the IsBuilding check/set to avoid the situation where two threads could both pass through // if they both checked IsBuilding at the same time before either of them set IsBuilding. lock (caches) { // We check all parts of the array before setting any to avoid somehow setting a few then leaving before we can unset them. for (int i = 0; i < lps.Length; i++) { if (lps[i] != null && lps[i].IsBuilding) { return; } } // Now we know we are safe so we can set IsBuilding. for (int i = 0; i < lps.Length; i++) { if (lps[i] != null) { lps[i].IsBuilding = true; } } // Now we have to get a valid cache object. bool cacheSet = false; for (int i = 0; i < caches.Count; i++) { if (!caches[i].inUse) { cache = caches[i]; cache.inUse = true; cacheSet = true; } } if (!cacheSet) { cache = new LiquidRebuildCache(); cache.inUse = true; caches.Add(cache); } } LiquidType curLiqType = LiquidType.None; LiquidPrimitive curPrimative = null; ExtendedVertex[] curVertices = null; int[] maxVertices = new int[lps.Length]; int 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); int maxVertex = 0; bool fogOfWar = GameSettings.Default.FogofWar; 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 (fogOfWar && !chunk.Data.IsExplored[index]) { continue; } if (chunk.Data.Water[index].WaterLevel > 0) { LiquidType liqType = chunk.Data.Water[index].Type; // We need to see if we changed types and should change the data we are writing to. if (liqType != curLiqType) { LiquidPrimitive newPrimitive = lps[(int)liqType]; // We weren't passed a LiquidPrimitive object to work with for this type so we'll skip it. if (newPrimitive == null) { continue; } maxVertices[(int)curLiqType] = maxVertex; curVertices = newPrimitive.Vertices; curLiqType = liqType; curPrimative = newPrimitive; maxVertex = maxVertices[(int)liqType]; } myVoxel.GridPosition = new Vector3(x, y, z); int facesToDraw = 0; for (int i = 0; i < 6; i++) { BoxFace face = (BoxFace)i; // We won't draw the bottom face. This might be needed down the line if we add transparent tiles like glass. if (face == BoxFace.Bottom) { continue; } Vector3 delta = faceDeltas[(int)face]; // Pull the current neighbor Voxel based on the face it would be touching. bool success = myVoxel.GetNeighborBySuccessor(delta, ref vox, false); if (success) { if (face == BoxFace.Top) { if (!(vox.WaterLevel == 0 || y == (int)chunk.Manager.ChunkData.MaxViewingLevel)) { cache.drawFace[(int)face] = false; continue; } } else { if (vox.WaterLevel != 0 || !vox.IsEmpty) { cache.drawFace[(int)face] = false; continue; } } } cache.drawFace[(int)face] = true; facesToDraw++; } // There's no faces to draw on this voxel. Let's go to the next one. if (facesToDraw == 0) { continue; } // Now we check to see if we need to resize the current Vertex array. int vertexSizeIncrease = facesToDraw * 6; if (curVertices == null) { curVertices = new ExtendedVertex[256]; curPrimative.Vertices = curVertices; } else if (curVertices.Length <= maxVertex + vertexSizeIncrease) { ExtendedVertex[] newVerts = new ExtendedVertex[curVertices.Length * 2]; curVertices.CopyTo(newVerts, 0); curVertices = newVerts; curPrimative.Vertices = curVertices; } // Now we have a list of all the faces that will need to be drawn. Let's draw them. CreateWaterFaces(myVoxel, chunk, x, y, z, curVertices, maxVertex); // Finally increase the size so we can move on. maxVertex += vertexSizeIncrease; } } } } // The last thing we need to do is make sure we set the current primative's maxVertices to the right value. maxVertices[(int)curLiqType] = maxVertex; // Now actually force the VertexBuffer to be recreated in each primative we worked with. for (int i = 0; i < lps.Length; i++) { LiquidPrimitive updatedPrimative = lps[i]; if (updatedPrimative == null) { continue; } maxVertex = maxVertices[i]; if (maxVertex > 0) { try { lock (updatedPrimative.VertexLock) { updatedPrimative.MaxVertex = maxVertex; updatedPrimative.VertexBuffer = null; } } catch (System.Threading.AbandonedMutexException e) { Console.Error.WriteLine(e.Message); } } else { try { lock (updatedPrimative.VertexLock) { updatedPrimative.VertexBuffer = null; updatedPrimative.Vertices = null; updatedPrimative.Indexes = null; updatedPrimative.MaxVertex = 0; updatedPrimative.MaxIndex = 0; } } catch (System.Threading.AbandonedMutexException e) { Console.Error.WriteLine(e.Message); } } updatedPrimative.IsBuilding = false; } cache.inUse = false; cache = null; }
public void InitializeFromChunk(VoxelChunk chunk) { if (IsBuilding) { return; } IsBuilding = true; int 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); int maxVertex = 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 (GameSettings.Default.FogofWar && !chunk.Data.IsExplored[index]) { continue; } 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++) { if (Vertices == null) { Vertices = new ExtendedVertex[256]; } else if (Vertices.Length <= maxVertex + 6) { ExtendedVertex[] newVerts = new ExtendedVertex[Vertices.Length * 2]; Vertices.CopyTo(newVerts, 0); Vertices = newVerts; } BoxFace face = (BoxFace)i; if (face == BoxFace.Bottom) { continue; } Vector3 delta = faceDeltas[(int)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[(int)face] = true; } else { drawFace[(int)face] = false; } } else { if (vox.WaterLevel == 0 && vox.IsEmpty) { drawFace[(int)face] = true; } else { drawFace[(int)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[(int)face] = true; } if (!drawFace[(int)face]) { continue; } CreateWaterFace(myVoxel, face, chunk, x, y, z, isTop, Vertices, maxVertex); maxVertex += 6; } } } } } if (maxVertex > 0) { try { lock (VertexLock) { MaxVertex = maxVertex; VertexBuffer = null; } } catch (System.Threading.AbandonedMutexException e) { Console.Error.WriteLine(e.Message); } } else { try { lock (VertexLock) { VertexBuffer = null; Vertices = null; Indexes = null; MaxVertex = 0; MaxIndex = 0; } } catch (System.Threading.AbandonedMutexException e) { Console.Error.WriteLine(e.Message); } } IsBuilding = false; }