private static void AddDecalGeometry( RawPrimitive Into, int[] AmbientScratchSpace, BoxPrimitive Primitive, VoxelHandle V, BoxPrimitive.FaceDescriptor faceDescriptor, int exploredVerts, Vector3[] VertexPositions, VertexColorInfo[] VertexColors, Color[] VertexTints, DecalType Decal, byte Orientation) { var indexOffset = Into.VertexCount; var UV = new Vector2(Decal.Tile.X * (1.0f / 16.0f), Decal.Tile.Y * (1.0f / 16.0f)); var UVBounds = new Vector4(UV.X + 0.001f, UV.Y + 0.001f, UV.X + (1.0f / 16.0f) - 0.001f, UV.Y + (1.0f / 16.0f) - 0.001f); var UVs = new Vector2[faceDescriptor.VertexCount]; for (int faceVertex = 0; faceVertex < faceDescriptor.VertexCount; faceVertex++) { var vertex = Primitive.Vertices[faceDescriptor.VertexOffset + faceVertex]; UVs[faceVertex] = UV + new Vector2(vertex.Position.X / 16.0f, vertex.Position.Z / 16.0f); } for (int faceVertex = 0; faceVertex < faceDescriptor.VertexCount; faceVertex++) { var vertex = Primitive.Vertices[faceDescriptor.VertexOffset + faceVertex]; AmbientScratchSpace[faceVertex] = VertexColors[faceVertex].AmbientColor; var uv = faceVertex + Orientation; uv %= faceDescriptor.VertexCount; // This will only work if the face has 4 verts... Into.AddVertex(new ExtendedVertex( VertexPositions[faceVertex] + VertexNoise.GetNoiseVectorFromRepeatingTexture(VertexPositions[faceVertex]), VertexColors[faceVertex].AsColor(), VertexTints[faceVertex], UVs[uv], UVBounds)); } bool flippedQuad = AmbientScratchSpace[0] + AmbientScratchSpace[2] > AmbientScratchSpace[1] + AmbientScratchSpace[3]; for (int idx = faceDescriptor.IndexOffset; idx < faceDescriptor.IndexCount + faceDescriptor.IndexOffset; idx++) { ushort offset = flippedQuad ? Primitive.FlippedIndexes[idx] : Primitive.Indexes[idx]; ushort offset0 = flippedQuad ? Primitive.FlippedIndexes[faceDescriptor.IndexOffset] : Primitive.Indexes[faceDescriptor.IndexOffset]; Into.AddIndex((short)(indexOffset + offset - offset0)); } }
private static void BuildDecalGeometry( RawPrimitive Into, VoxelChunk Chunk, Cache Cache, BoxPrimitive Primitive, VoxelHandle V, VertexColorInfo[] VertexColors, Color[] VertexTint, Vector3[] VertexPositions, BoxPrimitive.FaceDescriptor Face, int ExploredVerts) { if (V.DecalType == 0) { return; } var decalType = Library.GetDecalType(V.DecalType); AddDecalGeometry(Into, Cache.AmbientValues, Primitive, Face, ExploredVerts, VertexPositions, VertexColors, VertexTint, decalType); }
private static void AddTopFaceGeometry( RawPrimitive Into, int[] AmbientScratchSpace, BoxPrimitive Primitive, BoxPrimitive.FaceDescriptor faceDescriptor, Vector3[] VertexPositions, VertexColorInfo[] VertexColors, Color[] VertexTints, Vector2 UVScale, Vector2 UV, Vector4 UVBounds) { var indexOffset = Into.VertexCount; for (int faceVertex = 0; faceVertex < faceDescriptor.VertexCount; faceVertex++) { var vertex = Primitive.Vertices[faceDescriptor.VertexOffset + faceVertex]; AmbientScratchSpace[faceVertex] = VertexColors[faceVertex].AmbientColor; Into.AddVertex(new ExtendedVertex( VertexPositions[faceVertex] + VertexNoise.GetNoiseVectorFromRepeatingTexture(VertexPositions[faceVertex]), VertexColors[faceVertex].AsColor(), VertexTints[faceVertex], UV + new Vector2(vertex.Position.X / 16.0f * UVScale.X, vertex.Position.Z / 16.0f * UVScale.Y), UVBounds)); } bool flippedQuad = AmbientScratchSpace[0] + AmbientScratchSpace[2] > AmbientScratchSpace[1] + AmbientScratchSpace[3]; for (int idx = faceDescriptor.IndexOffset; idx < faceDescriptor.IndexCount + faceDescriptor.IndexOffset; idx++) { ushort offset = flippedQuad ? Primitive.FlippedIndexes[idx] : Primitive.Indexes[idx]; ushort offset0 = flippedQuad ? Primitive.FlippedIndexes[faceDescriptor.IndexOffset] : Primitive.Indexes[faceDescriptor.IndexOffset]; Into.AddIndex((short)(indexOffset + offset - offset0)); } }
private static void AddGrassGeometry( RawPrimitive Into, int[] AmbientScratchSpace, BoxPrimitive Primitive, BoxPrimitive.FaceDescriptor faceDescriptor, Vector3[] VertexPositions, VertexColorInfo[] VertexColors, Color[] VertexTints, GrassType Decal) { var indexOffset = Into.VertexCount; var UV = new Vector2(Decal.Tile.X * (1.0f / 16.0f), Decal.Tile.Y * (1.0f / 16.0f)); var UVBounds = new Vector4(UV.X + 0.001f, UV.Y + 0.001f, UV.X + (1.0f / 16.0f) - 0.001f, UV.Y + (1.0f / 16.0f) - 0.001f); for (int faceVertex = 0; faceVertex < faceDescriptor.VertexCount; faceVertex++) { var vertex = Primitive.Vertices[faceDescriptor.VertexOffset + faceVertex]; AmbientScratchSpace[faceVertex] = VertexColors[faceVertex].AmbientColor; Into.AddVertex(new ExtendedVertex( VertexPositions[faceVertex] + VertexNoise.GetNoiseVectorFromRepeatingTexture(VertexPositions[faceVertex]), VertexColors[faceVertex].AsColor(), VertexTints[faceVertex], UV + new Vector2(vertex.Position.X / 16.0f, vertex.Position.Z / 16.0f), UVBounds)); } bool flippedQuad = (AmbientScratchSpace[0] + AmbientScratchSpace[2]) > (AmbientScratchSpace[1] + AmbientScratchSpace[3]); for (int idx = faceDescriptor.IndexOffset; idx < faceDescriptor.IndexCount + faceDescriptor.IndexOffset; ++idx) { ushort offset = flippedQuad ? Primitive.FlippedIndexes[idx] : Primitive.Indexes[idx]; ushort offset0 = flippedQuad ? Primitive.FlippedIndexes[faceDescriptor.IndexOffset] : Primitive.Indexes[faceDescriptor.IndexOffset]; Into.AddIndex((short)(indexOffset + offset - offset0)); } }
private static void BuildGrassFringeGeometry( RawPrimitive Into, VoxelChunk Chunk, Cache Cache, BoxPrimitive Primitive, VoxelHandle V, VertexColorInfo[] VertexColors, Color[] VertexTint, Vector3[] VertexPositions, BoxPrimitive.FaceDescriptor Face, int ExploredVerts) { if (V.GrassType == 0) { return; } var decalType = Library.GetGrassType(V.GrassType); AddGrassGeometry(Into, Cache.AmbientValues, Primitive, V, Face, ExploredVerts, VertexPositions, VertexColors, VertexTint, decalType); // Draw fringe if (decalType.FringeTransitionUVs == null) { return; } for (var s = 0; s < 4; ++s) { var neighborCoord = V.Coordinate + VoxelHelpers.ManhattanNeighbors2D[s]; var neighbor = new VoxelHandle(Chunk.Manager, neighborCoord); if (!neighbor.IsValid) { continue; } var aboveNeighbor = new VoxelHandle(Chunk.Manager, neighborCoord + new GlobalVoxelOffset(0, 1, 0)); if (!aboveNeighbor.IsValid || aboveNeighbor.IsEmpty) { // Draw horizontal fringe. if (!neighbor.IsEmpty) { if (neighbor.GrassType != 0 && Library.GetGrassType(neighbor.GrassType).FringePrecedence >= decalType.FringePrecedence) { continue; } } // Twizzle vertex positions. var newPositions = new Vector3[4]; newPositions[FringeIndicies[s, 0]] = VertexPositions[FringeIndicies[s, 4]]; newPositions[FringeIndicies[s, 1]] = VertexPositions[FringeIndicies[s, 4]] + (VoxelHelpers.ManhattanNeighbors2D[s].AsVector3() * 0.5f); newPositions[FringeIndicies[s, 2]] = VertexPositions[FringeIndicies[s, 5]] + (VoxelHelpers.ManhattanNeighbors2D[s].AsVector3() * 0.5f); newPositions[FringeIndicies[s, 3]] = VertexPositions[FringeIndicies[s, 5]]; var newColors = new VertexColorInfo[4]; newColors[FringeIndicies[s, 0]] = VertexColors[FringeIndicies[s, 4]]; newColors[FringeIndicies[s, 1]] = VertexColors[FringeIndicies[s, 4]]; newColors[FringeIndicies[s, 2]] = VertexColors[FringeIndicies[s, 5]]; newColors[FringeIndicies[s, 3]] = VertexColors[FringeIndicies[s, 5]]; var slopeTweak = new Vector3(0.0f, 0.0f, 0.0f); if (neighbor.IsEmpty) { slopeTweak.Y = -0.5f; } else { slopeTweak.Y = 0.125f; } newPositions[FringeIndicies[s, 1]] += slopeTweak; newPositions[FringeIndicies[s, 2]] += slopeTweak; var newTints = new Color[4]; newTints[FringeIndicies[s, 0]] = VertexTint[FringeIndicies[s, 4]]; newTints[FringeIndicies[s, 1]] = VertexTint[FringeIndicies[s, 4]]; newTints[FringeIndicies[s, 2]] = VertexTint[FringeIndicies[s, 5]]; newTints[FringeIndicies[s, 3]] = VertexTint[FringeIndicies[s, 5]]; AddTopFaceGeometry(Into, Cache.AmbientValues, Primitive, Face, newPositions, newColors, newTints, SideFringeUVScales[s], decalType.FringeTransitionUVs[s].UV, decalType.FringeTransitionUVs[s].Bounds); } else { // Draw vertical fringe! var newPositions = new Vector3[4]; newPositions[FringeIndicies[s, 0]] = VertexPositions[FringeIndicies[s, 4]]; newPositions[FringeIndicies[s, 1]] = VertexPositions[FringeIndicies[s, 4]] + new Vector3(0.0f, 0.5f, 0.0f) + (VoxelHelpers.ManhattanNeighbors2D[s].AsVector3() * -0.05f); newPositions[FringeIndicies[s, 2]] = VertexPositions[FringeIndicies[s, 5]] + new Vector3(0.0f, 0.5f, 0.0f) + (VoxelHelpers.ManhattanNeighbors2D[s].AsVector3() * -0.05f); newPositions[FringeIndicies[s, 3]] = VertexPositions[FringeIndicies[s, 5]]; var newColors = new VertexColorInfo[4]; newColors[FringeIndicies[s, 0]] = VertexColors[FringeIndicies[s, 4]]; newColors[FringeIndicies[s, 1]] = VertexColors[FringeIndicies[s, 4]]; newColors[FringeIndicies[s, 2]] = VertexColors[FringeIndicies[s, 5]]; newColors[FringeIndicies[s, 3]] = VertexColors[FringeIndicies[s, 5]]; var newTints = new Color[4]; newTints[FringeIndicies[s, 0]] = VertexTint[FringeIndicies[s, 4]]; newTints[FringeIndicies[s, 1]] = VertexTint[FringeIndicies[s, 4]]; newTints[FringeIndicies[s, 2]] = VertexTint[FringeIndicies[s, 5]]; newTints[FringeIndicies[s, 3]] = VertexTint[FringeIndicies[s, 5]]; AddTopFaceGeometry(Into, Cache.AmbientValues, Primitive, Face, newPositions, newColors, newTints, SideFringeUVScales[s], decalType.FringeTransitionUVs[s].UV, decalType.FringeTransitionUVs[s].Bounds); } } for (var s = 0; s < 4; ++s) { var neighborCoord = V.Coordinate + VoxelHelpers.DiagonalNeighbors2D[s]; var handle = new VoxelHandle(Chunk.Manager, neighborCoord); if (handle.IsValid) { if (!handle.IsEmpty) { if (handle.GrassType != 0 && Library.GetGrassType(handle.GrassType).FringePrecedence >= decalType.FringePrecedence) { continue; } } var manhattanA = new VoxelHandle(Chunk.Manager, V.Coordinate + VoxelHelpers.ManhattanNeighbors2D[s]); if (!manhattanA.IsValid || (manhattanA.GrassType == V.GrassType)) { continue; } manhattanA = new VoxelHandle(Chunk.Manager, V.Coordinate + VoxelHelpers.ManhattanNeighbors2D[FringeIndicies[4 + s, 5]]); if (!manhattanA.IsValid || (manhattanA.GrassType == V.GrassType)) { continue; } // Twizzle vertex positions. var newPositions = new Vector3[4]; var pivot = VertexPositions[FringeIndicies[4 + s, 4]]; var nDelta = VoxelHelpers.DiagonalNeighbors2D[s].AsVector3(); newPositions[FringeIndicies[4 + s, 0]] = pivot; newPositions[FringeIndicies[4 + s, 1]] = pivot + new Vector3(nDelta.X * 0.5f, 0, 0); newPositions[FringeIndicies[4 + s, 2]] = pivot + new Vector3(nDelta.X * 0.5f, 0, nDelta.Z * 0.5f); newPositions[FringeIndicies[4 + s, 3]] = pivot + new Vector3(0, 0, nDelta.Z * 0.5f); var slopeTweak = new Vector3(0.0f, 0.0f, 0.0f); if (handle.IsEmpty) { slopeTweak.Y = -0.5f; } else { slopeTweak.Y = 0.125f; } newPositions[FringeIndicies[4 + s, 1]] += slopeTweak; newPositions[FringeIndicies[4 + s, 2]] += slopeTweak; newPositions[FringeIndicies[4 + s, 3]] += slopeTweak; var newColors = new VertexColorInfo[4]; newColors[FringeIndicies[4 + s, 0]] = VertexColors[FringeIndicies[4 + s, 4]]; newColors[FringeIndicies[4 + s, 1]] = VertexColors[FringeIndicies[4 + s, 4]]; newColors[FringeIndicies[4 + s, 2]] = VertexColors[FringeIndicies[4 + s, 4]]; newColors[FringeIndicies[4 + s, 3]] = VertexColors[FringeIndicies[4 + s, 4]]; var newTints = new Color[4]; newTints[FringeIndicies[4 + s, 0]] = VertexTint[FringeIndicies[4 + s, 4]]; newTints[FringeIndicies[4 + s, 1]] = VertexTint[FringeIndicies[4 + s, 4]]; newTints[FringeIndicies[4 + s, 2]] = VertexTint[FringeIndicies[4 + s, 4]]; newTints[FringeIndicies[4 + s, 3]] = VertexTint[FringeIndicies[4 + s, 4]]; AddTopFaceGeometry(Into, Cache.AmbientValues, Primitive, Face, newPositions, newColors, newTints, new Vector2(0.5f, 0.5f), decalType.FringeTransitionUVs[4 + s].UV, decalType.FringeTransitionUVs[4 + s].Bounds); } } }