public static VoxelHandle GetNeighbor(VoxelHandle Of, GlobalVoxelOffset Offset) { if (!Of.IsValid) { return(VoxelHandle.InvalidHandle); } return(new VoxelHandle(Of.Chunk.Manager.ChunkData, Of.Coordinate + Offset)); }
private static void BuildVoxelTopFaceGeometry( RawPrimitive Into, VoxelChunk Chunk, Cache Cache, BoxPrimitive Primitive, VoxelHandle V, BoxPrimitive.BoxTextureCoords UVs, int i) { var face = (BoxFace)i; var delta = FaceDeltas[i]; var faceVoxel = new VoxelHandle(Chunk.Manager, V.Coordinate + GlobalVoxelOffset.FromVector3(delta)); if (!IsFaceVisible(V, faceVoxel, face)) { return; } var faceDescriptor = Primitive.GetFace(face); int exploredVerts = 0; var vertexColors = new VertexColorInfo[4]; var vertexTint = new Color[4]; // Find all verticies to use for geometry later, and for the fringe var vertexPositions = new Vector3[4]; for (int faceVertex = 0; faceVertex < faceDescriptor.VertexCount; faceVertex++) { var vertex = Primitive.Vertices[faceDescriptor.VertexOffset + faceVertex]; var voxelVertex = Primitive.Deltas[faceDescriptor.VertexOffset + faceVertex]; var rampOffset = Vector3.Zero; if (V.IsExplored && V.Type.CanRamp && ShouldRamp(voxelVertex, V.RampType)) { rampOffset = new Vector3(0, -V.Type.RampSize, 0); } var worldPosition = V.WorldPosition + vertex.Position + rampOffset; //worldPosition += VertexNoise.GetNoiseVectorFromRepeatingTexture(worldPosition); vertexPositions[faceVertex] = worldPosition; } if (V.IsExplored) { exploredVerts = 4; } else { for (int faceVertex = 0; faceVertex < faceDescriptor.VertexCount; ++faceVertex) { var voxelVertex = Primitive.Deltas[faceDescriptor.VertexOffset + faceVertex]; var cacheKey = GetCacheKey(V, voxelVertex); bool anyNeighborExplored = true; if (!Cache.ExploredCache.TryGetValue(cacheKey, out anyNeighborExplored)) { anyNeighborExplored = VoxelHelpers.EnumerateVertexNeighbors2D(V.Coordinate, voxelVertex) .Select(c => new VoxelHandle(V.Chunk.Manager, c)) .Any(n => n.IsValid && n.IsExplored); Cache.ExploredCache.Add(cacheKey, anyNeighborExplored); } if (anyNeighborExplored) { exploredVerts += 1; } } } for (int faceVertex = 0; faceVertex < faceDescriptor.VertexCount; ++faceVertex) { var voxelVertex = Primitive.Deltas[faceDescriptor.VertexOffset + faceVertex]; var cacheKey = GetCacheKey(V, voxelVertex); VertexColorInfo vertexColor; if (!Cache.LightCache.TryGetValue(cacheKey, out vertexColor)) { vertexColor = CalculateVertexLight(V, voxelVertex, Chunk.Manager); Cache.LightCache.Add(cacheKey, vertexColor); } vertexColors[faceVertex] = vertexColor; vertexTint[faceVertex] = new Color(1.0f, 1.0f, 1.0f, 1.0f); if (exploredVerts != 4) { bool anyNeighborExplored = true; if (!Cache.ExploredCache.TryGetValue(cacheKey, out anyNeighborExplored)) { throw new InvalidProgramException("Failed cache lookup"); } if (!anyNeighborExplored) { vertexTint[faceVertex] = new Color(0.0f, 0.0f, 0.0f, 1.0f); } } vertexTint[faceVertex] = new Color(vertexTint[faceVertex].ToVector4() * V.Type.Tint.ToVector4()); } if (exploredVerts != 0) { var baseUVs = UVs.Uvs[11]; // EW var baseUVBounds = new Vector4(baseUVs.X + 0.001f, baseUVs.Y + 0.001f, baseUVs.X + (1.0f / 16.0f) - 0.001f, baseUVs.Y + (1.0f / 16.0f) - 0.001f); // Draw central top tile. AddTopFaceGeometry(Into, Cache.AmbientValues, Primitive, faceDescriptor, vertexPositions, vertexColors, vertexTint, Vector2.One, baseUVs, baseUVBounds); if (V.GrassType != 0) { BuildGrassFringeGeometry(Into, Chunk, Cache, Primitive, V, vertexColors, vertexTint, vertexPositions, faceDescriptor, exploredVerts); } } else { if (!Debugger.Switches.HideSliceTop) { var indexOffset = Into.VertexCount; for (int faceVertex = 0; faceVertex < faceDescriptor.VertexCount; faceVertex++) { Into.AddVertex(new ExtendedVertex( vertexPositions[faceVertex] + VertexNoise.GetNoiseVectorFromRepeatingTexture(vertexPositions[faceVertex]), new Color(0, 0, 0, 255), new Color(0, 0, 0, 255), new Vector2(12.5f / 16.0f, 0.5f / 16.0f), new Vector4(12.0f / 16.0f, 0.0f, 13.0f / 16.0f, 1.0f / 16.0f))); } for (int idx = faceDescriptor.IndexOffset; idx < faceDescriptor.IndexCount + faceDescriptor.IndexOffset; idx++) { ushort offset = Primitive.Indexes[idx]; ushort offset0 = Primitive.Indexes[faceDescriptor.IndexOffset]; Into.AddIndex((short)(indexOffset + offset - offset0)); } } } }
private static void BuildVoxelFaceGeometry( RawPrimitive Into, VoxelChunk Chunk, Cache Cache, BoxPrimitive Primitive, VoxelHandle V, Color Tint, BoxPrimitive.BoxTextureCoords UVs, Matrix VertexTransform, int i, bool ApplyLighting) { var face = (BoxFace)i; var delta = FaceDeltas[i]; var faceVoxel = new VoxelHandle(Chunk.Manager, V.Coordinate + GlobalVoxelOffset.FromVector3(delta)); if (!IsFaceVisible(V, faceVoxel, face)) { return; } var faceDescriptor = Primitive.GetFace(face); var indexOffset = Into.VertexCount; for (int faceVertex = 0; faceVertex < faceDescriptor.VertexCount; faceVertex++) { var vertex = Primitive.Vertices[faceDescriptor.VertexOffset + faceVertex]; var voxelVertex = Primitive.Deltas[faceDescriptor.VertexOffset + faceVertex]; var vertexColor = new VertexColorInfo { SunColor = 255, AmbientColor = 255, DynamicColor = 255, }; if (ApplyLighting) { var cacheKey = GetCacheKey(V, voxelVertex); if (!Cache.LightCache.TryGetValue(cacheKey, out vertexColor)) { vertexColor = CalculateVertexLight(V, voxelVertex, Chunk.Manager); Cache.LightCache.Add(cacheKey, vertexColor); } Cache.AmbientValues[faceVertex] = vertexColor.AmbientColor; } var rampOffset = Vector3.Zero; if (V.IsExplored && V.Type.CanRamp && ShouldRamp(voxelVertex, V.RampType)) { rampOffset = new Vector3(0, -V.Type.RampSize, 0); } var baseWorldPosition = V.WorldPosition + vertex.Position + rampOffset; var noise = VertexNoise.GetNoiseVectorFromRepeatingTexture(baseWorldPosition); var localPosition = Vector3.Transform(vertex.Position + rampOffset + noise, VertexTransform); Into.AddVertex(new ExtendedVertex( V.WorldPosition + localPosition, vertexColor.AsColor(), Tint, UVs.Uvs[faceDescriptor.VertexOffset + faceVertex], UVs.Bounds[faceDescriptor.IndexOffset / 6])); } bool flippedQuad = ApplyLighting && (Cache.AmbientValues[0] + Cache.AmbientValues[2] > Cache.AmbientValues[1] + Cache.AmbientValues[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 int SuccessorToEuclidianLookupKey(GlobalVoxelOffset C) { return((C.X + 1) + (C.Y + 1) * 3 + (C.Z + 1) * 9); }