private void ConnectMinimizingVertices(Chunk c) { Dictionary <Vector3I, short> positionToIndex = _positionToIndex[c]; List <VertexPositionNormalColorLight> vertices = _vertices[c]; List <VertexPositionNormalColorLight> meshVertices = _meshVertices[c]; List <short> meshIndices = _indices[c]; foreach (Edge e in _intersectingEdges[c]) { Direction d = e.FaceDirection; short[] indices = new short[6]; Vector3I[] cubes = e.GetCubePositions(); bool invalid = false; HashSet <Edge> borderEdges = _borderEdges[c]; HashSet <Vector3I> neededBorderPositions = _neededBorderPositions[c]; for (int i = 0; i < cubes.Length; i++) { if (cubes[i].X < 0 || cubes[i].Y < 0 || cubes[i].Z < 0) { invalid = true; break; } if (cubes[i].X > c.Width - 1 || cubes[i].Y > c.Height - 1 || cubes[i].Z > c.Length - 1) { borderEdges.Add(e); neededBorderPositions.Add(cubes[i]); invalid = true; } } if (invalid) { continue; } // used to determine which config the face is in; this is used to know which indices refer to the same vertex below bool indicesConfig = false; // TODO: possible degenerate triangles (0 area) switch (d) { case Direction.XDecreasing: case Direction.ZDecreasing: case Direction.YIncreasing: indices[0] = positionToIndex[cubes[0]]; indices[1] = positionToIndex[cubes[1]]; indices[2] = positionToIndex[cubes[3]]; indices[3] = positionToIndex[cubes[0]]; indices[4] = positionToIndex[cubes[3]]; indices[5] = positionToIndex[cubes[2]]; indicesConfig = true; // duplicates at 0,3 and 2,4 break; case Direction.XIncreasing: case Direction.ZIncreasing: case Direction.YDecreasing: indices[0] = positionToIndex[cubes[0]]; indices[1] = positionToIndex[cubes[3]]; indices[2] = positionToIndex[cubes[1]]; indices[3] = positionToIndex[cubes[0]]; indices[4] = positionToIndex[cubes[2]]; indices[5] = positionToIndex[cubes[3]]; indicesConfig = false; // duplicates at 0,3, and 1,5 break; } short index0 = positionToIndex[cubes[0]]; short index1 = positionToIndex[cubes[1]]; short index2 = positionToIndex[cubes[2]]; short index3 = positionToIndex[cubes[3]]; // triangle 1 Vector3 point0 = vertices[indices[0]].Position; Vector3 point1 = vertices[indices[1]].Position; Vector3 point2 = vertices[indices[2]].Position; Vector3 v01 = point1 - point0; Vector3 v12 = point2 - point1; Vector3 normal1 = Vector3.Cross(v12, v01); normal1.Normalize(); if (Single.IsNaN(normal1.X) || Single.IsNaN(normal1.Y) || Single.IsNaN(normal1.Z)) { normal1 = Vector3.Zero; // TODO: this is a hack; think it through later } // triangle 2 Vector3 point3 = vertices[indices[3]].Position; Vector3 point4 = vertices[indices[4]].Position; Vector3 point5 = vertices[indices[5]].Position; Vector3 v34 = point4 - point3; Vector3 v45 = point5 - point4; Vector3 normal2 = Vector3.Cross(v45, v34); normal2.Normalize(); if (Single.IsNaN(normal2.X) || Single.IsNaN(normal2.Y) || Single.IsNaN(normal2.Z)) { normal2 = Vector3.Zero; // TODO: this is a hack; think it through later } //_normalVertices.Add(new VertexPositionColor(point1, Color.White)); //_normalVertices.Add(new VertexPositionColor(point1 + normal1, Color.White)); //_normalVertices.Add(new VertexPositionColor(point2, Color.Black)); //_normalVertices.Add(new VertexPositionColor(point2 + normal2, Color.Black)); _triangles += 2; VertexPositionNormalColorLight vertex0 = vertices[indices[0]]; VertexPositionNormalColorLight vertex1 = vertices[indices[1]]; VertexPositionNormalColorLight vertex2 = vertices[indices[2]]; VertexPositionNormalColorLight vertex3 = vertices[indices[3]]; VertexPositionNormalColorLight vertex4 = vertices[indices[4]]; VertexPositionNormalColorLight vertex5 = vertices[indices[5]]; if (indicesConfig) { vertex0.Normal += normal1 + normal2; vertex1.Normal += normal1; vertex2.Normal += normal1 + normal2; vertex5.Normal += normal2; AddIndices(meshIndices, meshVertices.Count, 0, 1, 2, 0, 2, 3); AddVertices(meshVertices, vertex0, vertex1, vertex2, vertex5); } else { vertex0.Normal += normal1 + normal2; vertex1.Normal += normal1 + normal2; vertex2.Normal += normal1; vertex4.Normal += normal2; AddIndices(meshIndices, meshVertices.Count, 0, 1, 2, 0, 3, 1); AddVertices(meshVertices, vertex0, vertex1, vertex2, vertex4); } } }
private void BuildBuffers(Chunk c) { VertexPositionNormalColorLight[] vertices = new VertexPositionNormalColorLight[_meshVertices[c].Count]; short[] indices = new short[_indices[c].Count]; _meshVertices[c].CopyTo(vertices); _indices[c].CopyTo(indices); NormalizeNormals(c, vertices); VertexPositionColor[] normal = new VertexPositionColor[_normalVertices[c].Count]; _normalVertices[c].CopyTo(normal); Vector3[] verticesPos = new Vector3[vertices.Length]; int[] indices32 = new int[indices.Length]; for (int i = 0; i < vertices.Length; i++) { verticesPos[i] = vertices[i].Position; } for (int i = 0; i < indices.Length; i++) { indices32[i] = indices[i]; } if (MeshBuilt != null) { MeshBuilt(c, new MeshBuildEventArgs(verticesPos, indices32)); } lock (c.GraphicsSync) { if (c.VertexBuffer != null) { c.VertexBuffer.Dispose(); } if (c.IndexBuffer != null) { c.IndexBuffer.Dispose(); } if (c.NormalsVertexBuffer != null) { c.NormalsVertexBuffer.Dispose(); } if (_vertices[c].Count <= 0 || _indices[c].Count <= 0) { c.VertexBuffer = null; c.IndexBuffer = null; c.NormalsVertexBuffer = null; } else { c.VertexBuffer = new DynamicVertexBuffer(_device, typeof(VertexPositionNormalColorLight), vertices.Length, BufferUsage.WriteOnly); c.IndexBuffer = new DynamicIndexBuffer(_device, IndexElementSize.SixteenBits, indices.Length, BufferUsage.WriteOnly); c.NormalsVertexBuffer = new DynamicVertexBuffer(_device, typeof(VertexPositionColor), normal.Length, BufferUsage.WriteOnly); c.VertexBuffer.SetData <VertexPositionNormalColorLight>(vertices); c.IndexBuffer.SetData <short>(indices); c.NormalsVertexBuffer.SetData <VertexPositionColor>(normal); } } //_vertices[c].Clear(); _normalVertices[c].Clear(); _indices[c].Clear(); _intersectingEdges[c].Clear(); //_positionToIndex[c].Clear(); }
public void PostProcess(Chunk c) { /* * BuildBuffers(c); * c.MarkDataInSync(); * * return;*/ // after we build the chunk's vertices, we need to stitch the borders. // each chunk only stiches borders with its XPositive, YPositive, and ZPositive neighbor chunks. (if they aren't null) // this ensures that we don't create more quads than necessary. List <VertexPositionNormalColorLight> vertices = _vertices[c]; List <VertexPositionNormalColorLight> meshVertices = _meshVertices[c]; List <short> meshIndices = _indices[c]; Dictionary <Vector3I, short> positionToIndex = _positionToIndex[c]; HashSet <Vector3I> neededBorderPositions = _neededBorderPositions[c]; foreach (Vector3I pos in neededBorderPositions) { if (!_world.InBounds((c.Position + pos).ToVector3())) { continue; } Chunk otherChunk = _world.ChunkAt(c.Position.X + pos.X, c.Position.Y + pos.Y, c.Position.Z + pos.Z); Vector3I otherChunkLocalPos = new Vector3I(pos.X % otherChunk.Width, pos.Y % otherChunk.Height, pos.Z % otherChunk.Length); vertices.Add(_vertices[otherChunk][_positionToIndex[otherChunk][otherChunkLocalPos]]); positionToIndex.Add(pos, (short)(vertices.Count - 1)); } foreach (Edge e in _borderEdges[c]) { Direction d = e.FaceDirection; short[] indices = new short[6]; Vector3I[] cubes = e.GetCubePositions(); bool invalid = false; for (int i = 0; i < cubes.Length; i++) { if (cubes[i].X < 0 || cubes[i].Y < 0 || cubes[i].Z < 0 || !_world.InBounds((c.Position + cubes[i]).ToVector3())) { invalid = true; break; } } if (invalid) { continue; } // used to determine which config the face is in; this is used to know which indices refer to the same vertex below bool indicesConfig = false; // TODO: possible degenerate triangles (0 area) switch (d) { case Direction.XDecreasing: case Direction.ZDecreasing: case Direction.YIncreasing: indices[0] = positionToIndex[cubes[0]]; indices[1] = positionToIndex[cubes[1]]; indices[2] = positionToIndex[cubes[3]]; indices[3] = positionToIndex[cubes[0]]; indices[4] = positionToIndex[cubes[3]]; indices[5] = positionToIndex[cubes[2]]; indicesConfig = true; break; case Direction.XIncreasing: case Direction.ZIncreasing: case Direction.YDecreasing: indices[0] = positionToIndex[cubes[0]]; indices[1] = positionToIndex[cubes[3]]; indices[2] = positionToIndex[cubes[1]]; indices[3] = positionToIndex[cubes[0]]; indices[4] = positionToIndex[cubes[2]]; indices[5] = positionToIndex[cubes[3]]; indicesConfig = false; break; } short index0 = positionToIndex[cubes[0]]; short index1 = positionToIndex[cubes[1]]; short index2 = positionToIndex[cubes[2]]; short index3 = positionToIndex[cubes[3]]; // triangle 1 Vector3 point0 = vertices[indices[0]].Position; Vector3 point1 = vertices[indices[1]].Position; Vector3 point2 = vertices[indices[2]].Position; Vector3 v01 = point1 - point0; Vector3 v12 = point2 - point1; Vector3 normal1 = Vector3.Cross(v12, v01); normal1.Normalize(); if (Single.IsNaN(normal1.X) || Single.IsNaN(normal1.Y) || Single.IsNaN(normal1.Z)) { normal1 = Vector3.Zero; // TODO: this is a hack; think it through later } // triangle 2 Vector3 point3 = vertices[indices[3]].Position; Vector3 point4 = vertices[indices[4]].Position; Vector3 point5 = vertices[indices[5]].Position; Vector3 v34 = point4 - point3; Vector3 v45 = point5 - point4; Vector3 normal2 = Vector3.Cross(v45, v34); normal2.Normalize(); if (Single.IsNaN(normal2.X) || Single.IsNaN(normal2.Y) || Single.IsNaN(normal2.Z)) { normal2 = Vector3.Zero; // TODO: this is a hack; think it through later } _triangles += 2; VertexPositionNormalColorLight vertex0 = vertices[indices[0]]; VertexPositionNormalColorLight vertex1 = vertices[indices[1]]; VertexPositionNormalColorLight vertex2 = vertices[indices[2]]; VertexPositionNormalColorLight vertex3 = vertices[indices[3]]; VertexPositionNormalColorLight vertex4 = vertices[indices[4]]; VertexPositionNormalColorLight vertex5 = vertices[indices[5]]; if (indicesConfig) { vertex0.Normal += normal1 + normal2; vertex1.Normal += normal1; vertex2.Normal += normal1 + normal2; vertex5.Normal += normal2; AddIndices(meshIndices, meshVertices.Count, 0, 1, 2, 0, 2, 3); AddVertices(meshVertices, vertex0, vertex1, vertex2, vertex5); } else { vertex0.Normal += normal1 + normal2; vertex1.Normal += normal1 + normal2; vertex2.Normal += normal1; vertex4.Normal += normal2; AddIndices(meshIndices, meshVertices.Count, 0, 1, 2, 0, 3, 1); AddVertices(meshVertices, vertex0, vertex1, vertex2, vertex4); } } System.Diagnostics.Stopwatch sw = new System.Diagnostics.Stopwatch(); sw.Start(); BuildBuffers(c); sw.Stop(); //Console.WriteLine("BuildBuffers(): {0}ms", sw.ElapsedMilliseconds); c.MarkDataInSync(); }