public static BoxPrimitive CreatePrimitive(GraphicsDevice graphics, Texture2D textureMap, int width, int height, Point top, Point sides, Point bottom) { BoxPrimitive.BoxTextureCoords coords = new BoxPrimitive.BoxTextureCoords(textureMap.Width, textureMap.Height, width, height, sides, sides, top, bottom, sides, sides); BoxPrimitive cube = new BoxPrimitive(graphics, 1.0f, 1.0f, 1.0f, coords); return cube; }
public void InitializeFromChunk(VoxelChunk chunk, DesignationSet DesignationSet, WorldManager World) { DebugHelper.AssertNotNull(chunk); DebugHelper.AssertNotNull(DesignationSet); DebugHelper.AssertNotNull(World); BoxPrimitive bedrockModel = Library.GetVoxelPrimitive("Bedrock"); var sliceStack = new List <RawPrimitive>(); var cache = new Cache(); int maxViewingLevel = World.Renderer.PersistentSettings.MaxViewingLevel; for (var localY = 0; localY < maxViewingLevel - chunk.Origin.Y && localY < VoxelConstants.ChunkSizeY; ++localY) // Todo: Only iterate inside the chunk. { RawPrimitive sliceGeometry = null; lock (chunk.Data.SliceCache) { var cachedSlice = chunk.Data.SliceCache[localY]; if (cachedSlice != null) { cache.Clear(); sliceStack.Add(cachedSlice); if (GameSettings.Default.GrassMotes) { chunk.RebuildMoteLayerIfNull(localY); } continue; } sliceGeometry = new RawPrimitive { Vertices = null, Indexes = null }; chunk.Data.SliceCache[localY] = sliceGeometry; } if (GameSettings.Default.CalculateRamps) { UpdateCornerRamps(World.ChunkManager, chunk, localY); UpdateNeighborEdgeRamps(World.ChunkManager, chunk, localY); } if (GameSettings.Default.GrassMotes) { chunk.RebuildMoteLayer(localY); } DebugHelper.AssertNotNull(sliceGeometry); BuildSliceGeometry(chunk, bedrockModel, cache, localY, sliceGeometry, DesignationSet, World); sliceStack.Add(sliceGeometry); } var combinedGeometry = RawPrimitive.Concat(sliceStack); Vertices = combinedGeometry.Vertices; VertexCount = combinedGeometry.VertexCount; Indexes = combinedGeometry.Indexes.Select(s => (ushort)s).ToArray(); IndexCount = combinedGeometry.IndexCount; }
public static void InitializeDefaultLibrary(GraphicsDevice graphics, Texture2D cubeTexture) { if (PrimitiveMap.Count > 0) { return; } BoxPrimitive grassCube = CreatePrimitive(graphics, cubeTexture, 32, 32, new Point(0, 0), new Point(2, 0), new Point(2, 0)); BoxPrimitive dirtCube = CreatePrimitive(graphics, cubeTexture, 32, 32, new Point(2, 0), new Point(2, 0), new Point(2, 0)); BoxPrimitive stoneCube = CreatePrimitive(graphics, cubeTexture, 32, 32, new Point(4, 2), new Point(1, 0), new Point(4, 2)); BoxPrimitive sandCube = CreatePrimitive(graphics, cubeTexture, 32, 32, new Point(1, 1), new Point(1, 1), new Point(1, 1)); BoxPrimitive ironCube = CreatePrimitive(graphics, cubeTexture, 32, 32, new Point(4, 1), new Point(1, 2), new Point(4, 1)); BoxPrimitive goldCube = CreatePrimitive(graphics, cubeTexture, 32, 32, new Point(3, 1), new Point(0, 2), new Point(3, 1)); BoxPrimitive coalCube = CreatePrimitive(graphics, cubeTexture, 32, 32, new Point(3, 2), new Point(2, 2), new Point(2, 2)); BoxPrimitive manaCube = CreatePrimitive(graphics, cubeTexture, 32, 32, new Point(7, 1), new Point(6, 1), new Point(7, 1)); BoxPrimitive frostCube = CreatePrimitive(graphics, cubeTexture, 32, 32, new Point(0, 1), new Point(2, 1), new Point(2, 0)); BoxPrimitive scaffoldCube = CreatePrimitive(graphics, cubeTexture, 32, 32, new Point(7, 0), new Point(7, 0), new Point(7, 0)); BoxPrimitive plankCube = CreatePrimitive(graphics, cubeTexture, 32, 32, new Point(4, 0), new Point(4, 0), new Point(4, 0)); BoxPrimitive waterCube = CreatePrimitive(graphics, cubeTexture, cubeTexture.Width, cubeTexture.Height, new Point(0, 0), new Point(0, 0), new Point(0, 0)); BoxPrimitive cobblestoneCube = CreatePrimitive(graphics, cubeTexture, 32, 32, new Point(5, 2), new Point(5, 2), new Point(5, 2)); BoxPrimitive magicCube = CreatePrimitive(graphics, cubeTexture, 32, 32, new Point(0, 10), new Point(0, 10), new Point(0, 10)); BoxPrimitive bedrockCube = CreatePrimitive(graphics, cubeTexture, 32, 32, new Point(6, 2), new Point(6, 2), new Point(6, 2)); BoxPrimitive brownTileCube = CreatePrimitive(graphics, cubeTexture, 32, 32, new Point(5, 0), new Point(5, 0), new Point(5, 0)); BoxPrimitive blueTileCube = CreatePrimitive(graphics, cubeTexture, 32, 32, new Point(6, 0), new Point(6, 0), new Point(6, 0)); BoxPrimitive tilledSoilCube = CreatePrimitive(graphics, cubeTexture, 32, 32, new Point(5, 1), new Point(2, 0), new Point(2, 0)); emptyType = new VoxelType { Name = "empty", ReleasesResource = false, IsBuildable = false }; VoxelType tilledSoil = new VoxelType { Name = "TilledSoil", ReleasesResource = false, StartingHealth = 20, CanRamp = true, IsBuildable = false, ParticleType = "dirt_particle", IsSoil = true }; RegisterType(tilledSoil, tilledSoilCube); VoxelType brownTileFloor = new VoxelType { Name = "BrownTileFloor", ReleasesResource = false, StartingHealth = 20, CanRamp = false, IsBuildable = false, ParticleType = "stone_particle" }; RegisterType(brownTileFloor, brownTileCube); VoxelType blueTileFloor = new VoxelType { Name = "BlueTileFloor", ReleasesResource = false, StartingHealth = 20, CanRamp = false, IsBuildable = false, ParticleType = "stone_particle" }; RegisterType(blueTileFloor, blueTileCube); VoxelType cobblestoneFloor = new VoxelType { Name = "CobblestoneFloor", ReleasesResource = false, StartingHealth = 20, CanRamp = false, IsBuildable = false, ParticleType = "stone_particle", HasTransitionTextures = true }; RegisterType(cobblestoneFloor, cobblestoneCube); CreateTransitionUVs(graphics, cubeTexture, 32, 32, new Point(0, 8), new Point(5, 2), new Point(5, 2), cobblestoneFloor.TransitionTextures); VoxelType stockpileType = new VoxelType { Name = "Stockpile", ReleasesResource = false, StartingHealth = 20, CanRamp = false, IsBuildable = false, ParticleType = "stone_particle", HasTransitionTextures = true }; RegisterType(stockpileType, plankCube); CreateTransitionUVs(graphics, cubeTexture, 32, 32, new Point(0, 9), new Point(4, 0), new Point(4, 0), stockpileType.TransitionTextures); VoxelType plankType = new VoxelType { Name = "Plank", ProbabilityOfRelease = 1.0f, ResourceToRelease = ResourceLibrary.ResourceType.Wood, StartingHealth = 20, ReleasesResource = true, CanRamp = true, RampSize = 0.5f, IsBuildable = true, ParticleType = "stone_particle", HasTransitionTextures = true }; CreateTransitionUVs(graphics, cubeTexture, 32, 32, new Point(0, 9), new Point(4, 0), new Point(4, 0), plankType.TransitionTextures); VoxelType magicType = new VoxelType { Name = "Magic", ProbabilityOfRelease = 0.0f, ResourceToRelease = ResourceLibrary.ResourceType.Mana, StartingHealth = 1, ReleasesResource = true, CanRamp = false, IsBuildable = false, ParticleType = "star_particle", ExplosionSound = ContentPaths.Audio.wurp, HasTransitionTextures = false, EmitsLight = true }; CreateTransitionUVs(graphics, cubeTexture, 32, 32, new Point(0, 10), new Point(15, 10), new Point(15, 10), magicType.TransitionTextures); VoxelType scaffoldType = new VoxelType { Name = "Scaffold", StartingHealth = 20, ProbabilityOfRelease = 1.0f, ResourceToRelease = ResourceLibrary.ResourceType.Wood, ReleasesResource = false, CanRamp = false, RampSize = 0.5f, IsBuildable = true, ParticleType = "stone_particle" }; VoxelType grassType = new VoxelType { Name = "Grass", ProbabilityOfRelease = 0.1f, ResourceToRelease = ResourceLibrary.ResourceType.Dirt, StartingHealth = 10, ReleasesResource = true, CanRamp = true, RampSize = 0.5f, IsBuildable = false, ParticleType = "dirt_particle", HasTransitionTextures = true, IsSoil = true }; CreateTransitionUVs(graphics, cubeTexture, 32, 32, new Point(0, 3), new Point(2, 0), new Point(2, 0), grassType.TransitionTextures); VoxelType frostType = new VoxelType { Name = "Frost", ProbabilityOfRelease = 0.1f, ResourceToRelease = ResourceLibrary.ResourceType.Dirt, StartingHealth = 10, ReleasesResource = true, CanRamp = true, RampSize = 0.5f, IsBuildable = false, ParticleType = "dirt_particle", HasTransitionTextures = true }; CreateTransitionUVs(graphics, cubeTexture, 32, 32, new Point(0, 4), new Point(2, 0), new Point(2, 0), frostType.TransitionTextures); VoxelType desertGrass = new VoxelType { Name = "DesertGrass", ProbabilityOfRelease = 0.1f, ResourceToRelease = ResourceLibrary.ResourceType.Sand, StartingHealth = 10, ReleasesResource = true, CanRamp = true, RampSize = 0.5f, IsBuildable = false, ParticleType = "sand_particle", HasTransitionTextures = true }; CreateTransitionUVs(graphics, cubeTexture, 32, 32, new Point(0, 6), new Point(1, 1), new Point(1, 1), desertGrass.TransitionTextures); VoxelType jungleGrass = new VoxelType { Name = "JungleGrass", ProbabilityOfRelease = 0.1f, ResourceToRelease = ResourceLibrary.ResourceType.Dirt, StartingHealth = 10, ReleasesResource = true, CanRamp = true, RampSize = 0.5f, IsBuildable = false, ParticleType = "dirt_particle", HasTransitionTextures = true }; CreateTransitionUVs(graphics, cubeTexture, 32, 32, new Point(0, 5), new Point(2, 0), new Point(2, 0), jungleGrass.TransitionTextures); VoxelType dirtType = new VoxelType { Name = "Dirt", ReleasesResource = true, ResourceToRelease = ResourceLibrary.ResourceType.Dirt, ProbabilityOfRelease = 0.3f, StartingHealth = 10, RampSize = 0.5f, CanRamp = true, IsBuildable = true, ParticleType = "dirt_particle", IsSoil = true }; VoxelType stoneType = new VoxelType { Name = "Stone", ProbabilityOfRelease = 0.5f, ReleasesResource = true, ResourceToRelease = ResourceLibrary.ResourceType.Stone, StartingHealth = 30, IsBuildable = true, ParticleType = "stone_particle" }; VoxelType bedrockType = new VoxelType { Name = "Bedrock", StartingHealth = 255, IsBuildable = false, IsInvincible = true }; VoxelType waterType = new VoxelType { Name = "water", ReleasesResource = false, IsBuildable = false, StartingHealth = 255 }; VoxelType sandType = new VoxelType { Name = "Sand", ReleasesResource = false, StartingHealth = 5, CanRamp = true, RampSize = 0.5f, IsBuildable = false, ParticleType = "sand_particle" }; VoxelType ironType = new VoxelType { Name = "Iron", ProbabilityOfRelease = 0.99f, ReleasesResource = true, ResourceToRelease = ResourceLibrary.ResourceType.Iron, StartingHealth = 80, IsBuildable = false, ParticleType = "stone_particle" }; ResourceSpawns["Iron"] = new ResourceSpawnRate { VeinSize = 0.2f, VeinSpawnThreshold = 0.9f, MinimumHeight = -100, MaximumHeight = 100, Probability = 0.5f }; VoxelType coalType = new VoxelType { Name = "Coal", ProbabilityOfRelease = 0.99f, ReleasesResource = true, ResourceToRelease = ResourceLibrary.ResourceType.Coal, StartingHealth = 75, IsBuildable = false, ParticleType = "stone_particle" }; ResourceSpawns["Coal"] = new ResourceSpawnRate { VeinSize = 0.085f, VeinSpawnThreshold = 0.9f, MinimumHeight = -100, MaximumHeight = 100, Probability = 0.5f }; VoxelType goldType = new VoxelType { Name = "Gold", ProbabilityOfRelease = 1.0f, ReleasesResource = true, ResourceToRelease = ResourceLibrary.ResourceType.Gold, StartingHealth = 90, IsBuildable = false, ParticleType = "stone_particle" }; ResourceSpawns["Gold"] = new ResourceSpawnRate { VeinSize = 0.07f, VeinSpawnThreshold = 0.8f, MinimumHeight = -150, MaximumHeight = 15, Probability = 0.6f }; VoxelType manaType = new VoxelType { Name = "Mana", ProbabilityOfRelease = 1.0f, ReleasesResource = true, ResourceToRelease = ResourceLibrary.ResourceType.Mana, StartingHealth = 200, IsBuildable = false, ParticleType = "stone_particle" }; ResourceSpawns["Mana"] = new ResourceSpawnRate { VeinSize = 0.05f, VeinSpawnThreshold = 0.85f, MinimumHeight = -800, MaximumHeight = 8, Probability = 0.5f }; RegisterType(grassType, grassCube); RegisterType(frostType, frostCube); RegisterType(desertGrass, grassCube); RegisterType(jungleGrass, grassCube); RegisterType(emptyType, null); RegisterType(dirtType, dirtCube); RegisterType(stoneType, stoneCube); RegisterType(waterType, waterCube); RegisterType(sandType, sandCube); RegisterType(ironType, ironCube); RegisterType(goldType, goldCube); RegisterType(manaType, manaCube); RegisterType(plankType, plankCube); RegisterType(scaffoldType, scaffoldCube); RegisterType(bedrockType, bedrockCube); RegisterType(coalType, coalCube); RegisterType(magicType, magicCube); foreach (VoxelType type in VoxelType.TypeList) { Types[type.Name] = type; } }
public static void RegisterType(VoxelType type, BoxPrimitive primitive) { PrimitiveMap[type] = primitive; }
private static void BuildVoxelTopFaceGeometry( RawPrimitive Into, VoxelChunk Chunk, Cache Cache, BoxPrimitive Primitive, VoxelHandle V, BoxPrimitive.BoxTextureCoords UVs) { if (!IsFaceVisible(V, BoxFace.Top, Chunk.Manager, out var _)) { return; } var faceDescriptor = Primitive.GetFace(BoxFace.Top); 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.VertexClassifications[faceDescriptor.VertexOffset + faceVertex]; var rampOffset = Vector3.Zero; if (V.IsExplored && V.Type.CanRamp && ShouldRamp(voxelVertex, V.RampType)) { rampOffset = new Vector3(0, -0.5f, 0); } var worldPosition = V.WorldPosition + vertex.Position + rampOffset; //worldPosition += VertexNoise.GetNoiseVectorFromRepeatingTexture(worldPosition); vertexPositions[faceVertex] = worldPosition; } // Figure out if this vertex is adjacent to any explored voxel. if (V.IsExplored) { exploredVerts = 4; } else { for (int faceVertex = 0; faceVertex < faceDescriptor.VertexCount; ++faceVertex) { var voxelVertex = Primitive.VertexClassifications[faceDescriptor.VertexOffset + faceVertex]; var cacheKey = GetCacheKey(V, voxelVertex); var 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.VertexClassifications[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); // Turn face solid black if there are no explored neighbors - this is an optimization; it means we do not need to apply a solid black decal. if (exploredVerts != 4) { var 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 the base voxel 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); } if (V.DecalType != 0) { BuildDecalGeometry(Into, Chunk, Cache, Primitive, V, vertexColors, vertexTint, vertexPositions, faceDescriptor, exploredVerts); } } else { // Apparently being unexplored hides all grass and decals. Is that the behavior we actually want? 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)); } } } }
// Do not delete: Used to generate block icon texture for menu. public static Texture2D RenderIcons(GraphicsDevice device, Shader shader, ChunkManager chunks, int width, int height, int tileSize) { if (width == -1) { int sqrt = (int)(Math.Ceiling(Math.Sqrt(PrimitiveMap.Count))); width = MathFunctions.NearestPowerOf2(sqrt * tileSize); height = MathFunctions.NearestPowerOf2(sqrt * tileSize); } RenderTarget2D toReturn = new RenderTarget2D(device, width, height, false, SurfaceFormat.Color, DepthFormat.Depth16, 16, RenderTargetUsage.PreserveContents); device.SetRenderTarget(toReturn); device.Clear(Color.Transparent); shader.SetIconTechnique(); shader.MainTexture = chunks.ChunkData.Tilemap; shader.SelfIlluminationEnabled = true; shader.SelfIlluminationTexture = chunks.ChunkData.IllumMap; shader.EnableShadows = false; shader.EnableLighting = false; shader.ClippingEnabled = false; shader.CameraPosition = new Vector3(-0.5f, 0.5f, 0.5f); shader.VertexColorTint = Color.White; shader.LightRampTint = Color.White; shader.SunlightGradient = chunks.ChunkData.SunMap; shader.AmbientOcclusionGradient = chunks.ChunkData.AmbientMap; shader.TorchlightGradient = chunks.ChunkData.TorchMap; Viewport oldview = device.Viewport; List <VoxelType> voxelsByType = Types.Select(type => type.Value).ToList(); voxelsByType.Sort((a, b) => a.ID < b.ID ? -1 : 1); int rows = height / tileSize; int cols = width / tileSize; device.ScissorRectangle = new Rectangle(0, 0, tileSize, tileSize); device.RasterizerState = RasterizerState.CullNone; device.DepthStencilState = DepthStencilState.Default; Vector3 half = Vector3.One * 0.5f; half = new Vector3(half.X, half.Y, half.Z); foreach (EffectPass pass in shader.CurrentTechnique.Passes) { foreach (var type in voxelsByType) { int row = type.ID / cols; int col = type.ID % cols; BoxPrimitive primitive = GetPrimitive(type); if (primitive == null) { continue; } if (type.HasTransitionTextures) { primitive = new BoxPrimitive(device, 1, 1, 1, type.TransitionTextures[new BoxTransition()]); } device.Viewport = new Viewport(col * tileSize, row * tileSize, tileSize, tileSize); Matrix viewMatrix = Matrix.CreateLookAt(new Vector3(-1.2f, 1.0f, -1.5f), Vector3.Zero, Vector3.Up); Matrix projectionMatrix = Matrix.CreateOrthographic(1.5f, 1.5f, 0, 5); shader.View = viewMatrix; shader.Projection = projectionMatrix; shader.World = Matrix.CreateTranslation(-half); pass.Apply(); primitive.Render(device); } } device.Viewport = oldview; return((Texture2D)toReturn); }
public void GetRightFace(BoxPrimitive.BoxTextureCoords uvs, out int idx, out int count) { idx = 30; count = 6; }
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); } } }
public void GetFace(BoxFace face, BoxPrimitive.BoxTextureCoords uvs, out int index, out int count) { switch (face) { case BoxFace.Back: GetBackFace(uvs, out index, out count); return; case BoxFace.Front: GetFrontFace(uvs, out index, out count); return; case BoxFace.Left: GetLeftFace(uvs, out index, out count); return; case BoxFace.Right: GetRightFace(uvs, out index, out count); return; case BoxFace.Top: GetTopFace(uvs, out index, out count); return; case BoxFace.Bottom: GetBottomFace(uvs, out index, out count); return; } index = 0; count = 0; }
public void GetLeftFace(BoxPrimitive.BoxTextureCoords uvs, out int idx, out int count) { idx = 24; count = 6; }
public void GetBottomFace(BoxPrimitive.BoxTextureCoords uvs, out int idx, out int count) { idx = 18; count = 6; }
private static void BuildVoxelGeometryFromPrimitive(RawPrimitive Into, VoxelChunk Chunk, Cache Cache, VoxelHandle v, BoxPrimitive primitive) { var tint = v.Type.Tint; var uvs = primitive.UVs; if (v.Type.HasTransitionTextures && v.IsExplored) { uvs = ComputeTransitionTexture(new VoxelHandle(v.Chunk.Manager, v.Coordinate)); } BuildVoxelTopFaceGeometry(Into, Chunk, Cache, primitive, v, uvs, 0); for (int i = 1; i < 6; i++) { BuildVoxelFaceGeometry(Into, Chunk, Cache, primitive, v, tint, uvs, Matrix.Identity, i, true); } }
public void InitializeFromChunk(VoxelChunk chunk) { if (chunk == null) { return; } BoxPrimitive bedrockModel = VoxelLibrary.GetPrimitive("Bedrock"); var sliceStack = new List <RawPrimitive>(); var cache = new Cache(); for (var y = 0; y < chunk.Manager.ChunkData.MaxViewingLevel; ++y) { RawPrimitive sliceGeometry = null; lock (chunk.Data.SliceCache) { var cachedSlice = chunk.Data.SliceCache[y]; if (chunk.Data.VoxelsPresentInSlice[y] == 0) { cache.Clear(); if (cachedSlice != null) { chunk.Data.SliceCache[y] = null; } continue; } if (cachedSlice != null) { cache.Clear(); sliceStack.Add(cachedSlice); if (GameSettings.Default.GrassMotes) { chunk.RebuildMoteLayerIfNull(y); } continue; } sliceGeometry = new RawPrimitive { Vertices = new ExtendedVertex[128], Indexes = new short[128] }; chunk.Data.SliceCache[y] = sliceGeometry; } if (GameSettings.Default.CalculateRamps) { UpdateCornerRamps(chunk, y); UpdateNeighborEdgeRamps(chunk, y); } if (GameSettings.Default.GrassMotes) { chunk.RebuildMoteLayer(y); } BuildSliceGeometry(chunk, bedrockModel, cache, y, sliceGeometry); sliceStack.Add(sliceGeometry); } var combinedGeometry = RawPrimitive.Concat(sliceStack); Vertices = combinedGeometry.Vertices; VertexCount = combinedGeometry.VertexCount; Indexes = combinedGeometry.Indexes.Select(s => (ushort)s).ToArray(); IndexCount = combinedGeometry.IndexCount; chunk.PrimitiveMutex.WaitOne(); chunk.NewPrimitive = this; chunk.NewPrimitiveReceived = true; chunk.PrimitiveMutex.ReleaseMutex(); }
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)); } }
public void GetTopFace(BoxPrimitive.BoxTextureCoords uvs, out int idx, out int count) { idx = 12; count = 6; }
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)); } } } }
public void GetFace(BoxFace face, BoxPrimitive.BoxTextureCoords uvs, out int index, out int count, out int vertexOffset, out int vertexCount) { vertexCount = 4; count = 6; vertexOffset = 0; switch (face) { case BoxFace.Back: index = 6; vertexOffset = 4; return; case BoxFace.Front: index = 0; vertexOffset = 0; return; case BoxFace.Left: index = 24; vertexOffset = 16; return; case BoxFace.Right: index = 30; vertexOffset = 20; return; case BoxFace.Top: index = 12; vertexOffset = 8; return; case BoxFace.Bottom: index = 18; vertexOffset = 12; return; } index = 0; count = 0; }
public static void InitializeDefaultLibrary(GraphicsDevice graphics, Texture2D cubeTexture) { if (PrimitiveMap.Count > 0) { return; } BoxPrimitive grassCube = CreatePrimitive(graphics, cubeTexture, 32, 32, new Point(0, 0), new Point(2, 0), new Point(2, 0)); BoxPrimitive dirtCube = CreatePrimitive(graphics, cubeTexture, 32, 32, new Point(2, 0), new Point(2, 0), new Point(2, 0)); BoxPrimitive stoneCube = CreatePrimitive(graphics, cubeTexture, 32, 32, new Point(4, 2), new Point(1, 0), new Point(4, 2)); BoxPrimitive sandCube = CreatePrimitive(graphics, cubeTexture, 32, 32, new Point(1, 1), new Point(1, 1), new Point(1, 1)); BoxPrimitive ironCube = CreatePrimitive(graphics, cubeTexture, 32, 32, new Point(4, 1), new Point(1, 2), new Point(4, 1)); BoxPrimitive goldCube = CreatePrimitive(graphics, cubeTexture, 32, 32, new Point(3, 1), new Point(0, 2), new Point(3, 1)); BoxPrimitive coalCube = CreatePrimitive(graphics, cubeTexture, 32, 32, new Point(3, 2), new Point(2, 2), new Point(2, 2)); BoxPrimitive manaCube = CreatePrimitive(graphics, cubeTexture, 32, 32, new Point(7, 1), new Point(6, 1), new Point(7, 1)); BoxPrimitive frostCube = CreatePrimitive(graphics, cubeTexture, 32, 32, new Point(0, 1), new Point(2, 1), new Point(2, 0)); BoxPrimitive snowCube = CreatePrimitive(graphics, cubeTexture, 32, 32, new Point(3, 7), new Point(3, 7), new Point(3, 7)); BoxPrimitive iceCube = CreatePrimitive(graphics, cubeTexture, 32, 32, new Point(2, 7), new Point(2, 7), new Point(2, 7)); BoxPrimitive scaffoldCube = CreatePrimitive(graphics, cubeTexture, 32, 32, new Point(7, 0), new Point(7, 0), new Point(7, 0)); BoxPrimitive plankCube = CreatePrimitive(graphics, cubeTexture, 32, 32, new Point(4, 0), new Point(4, 0), new Point(4, 0)); BoxPrimitive waterCube = CreatePrimitive(graphics, cubeTexture, cubeTexture.Width, cubeTexture.Height, new Point(0, 0), new Point(0, 0), new Point(0, 0)); BoxPrimitive cobblestoneCube = CreatePrimitive(graphics, cubeTexture, 32, 32, new Point(5, 2), new Point(5, 2), new Point(5, 2)); BoxPrimitive magicCube = CreatePrimitive(graphics, cubeTexture, 32, 32, new Point(0, 10), new Point(0, 10), new Point(0, 10)); BoxPrimitive bedrockCube = CreatePrimitive(graphics, cubeTexture, 32, 32, new Point(6, 2), new Point(6, 2), new Point(6, 2)); BoxPrimitive brownTileCube = CreatePrimitive(graphics, cubeTexture, 32, 32, new Point(5, 0), new Point(5, 0), new Point(5, 0)); BoxPrimitive blueTileCube = CreatePrimitive(graphics, cubeTexture, 32, 32, new Point(6, 0), new Point(6, 0), new Point(6, 0)); BoxPrimitive tilledSoilCube = CreatePrimitive(graphics, cubeTexture, 32, 32, new Point(5, 1), new Point(2, 0), new Point(2, 0)); BoxPrimitive redGemCube = CreatePrimitive(graphics, cubeTexture, 32, 32, new Point(0, 11), new Point(0, 12), new Point(0, 11)); BoxPrimitive orangeGemCube = CreatePrimitive(graphics, cubeTexture, 32, 32, new Point(1, 11), new Point(1, 12), new Point(1, 11)); BoxPrimitive yellowGemCube = CreatePrimitive(graphics, cubeTexture, 32, 32, new Point(2, 11), new Point(2, 12), new Point(2, 11)); BoxPrimitive greenGemCube = CreatePrimitive(graphics, cubeTexture, 32, 32, new Point(3, 11), new Point(3, 12), new Point(3, 11)); BoxPrimitive blueGemCube = CreatePrimitive(graphics, cubeTexture, 32, 32, new Point(4, 11), new Point(4, 12), new Point(4, 11)); BoxPrimitive purpleGemCube = CreatePrimitive(graphics, cubeTexture, 32, 32, new Point(5, 11), new Point(5, 12), new Point(5, 11)); emptyType = new VoxelType { Name = "empty", ReleasesResource = false, IsBuildable = false }; VoxelType tilledSoil = new VoxelType { Name = "TilledSoil", ReleasesResource = false, StartingHealth = 20, CanRamp = true, IsBuildable = false, ParticleType = "dirt_particle", IsSoil = true, IsSurface = true }; RegisterType(tilledSoil, tilledSoilCube); VoxelType brownTileFloor = new VoxelType { Name = "BrownTileFloor", ReleasesResource = false, StartingHealth = 20, CanRamp = false, IsBuildable = false, ParticleType = "stone_particle" }; RegisterType(brownTileFloor, brownTileCube); VoxelType blueTileFloor = new VoxelType { Name = "BlueTileFloor", ReleasesResource = false, StartingHealth = 20, CanRamp = false, IsBuildable = false, ParticleType = "stone_particle" }; RegisterType(blueTileFloor, blueTileCube); VoxelType cobblestoneFloor = new VoxelType { Name = "CobblestoneFloor", ReleasesResource = false, StartingHealth = 20, CanRamp = false, IsBuildable = false, ParticleType = "stone_particle", HasTransitionTextures = true }; RegisterType(cobblestoneFloor, cobblestoneCube); CreateTransitionUVs(graphics, cubeTexture, 32, 32, new Point(0, 8), new Point(5, 2), new Point(5, 2), cobblestoneFloor.TransitionTextures); VoxelType stockpileType = new VoxelType { Name = "Stockpile", ReleasesResource = false, StartingHealth = 20, CanRamp = false, IsBuildable = false, ParticleType = "stone_particle", HasTransitionTextures = true }; RegisterType(stockpileType, plankCube); CreateTransitionUVs(graphics, cubeTexture, 32, 32, new Point(0, 9), new Point(4, 0), new Point(4, 0), stockpileType.TransitionTextures); VoxelType plankType = new VoxelType { Name = "Plank", ProbabilityOfRelease = 1.0f, ResourceToRelease = ResourceLibrary.ResourceType.Wood, StartingHealth = 20, ReleasesResource = true, CanRamp = true, RampSize = 0.5f, IsBuildable = true, ParticleType = "stone_particle", HasTransitionTextures = true }; CreateTransitionUVs(graphics, cubeTexture, 32, 32, new Point(0, 9), new Point(4, 0), new Point(4, 0), plankType.TransitionTextures); VoxelType magicType = new VoxelType { Name = "Magic", ProbabilityOfRelease = 0.0f, ResourceToRelease = ResourceLibrary.ResourceType.Mana, StartingHealth = 1, ReleasesResource = true, CanRamp = false, IsBuildable = false, ParticleType = "star_particle", ExplosionSound = ContentPaths.Audio.wurp, HasTransitionTextures = false, EmitsLight = true }; CreateTransitionUVs(graphics, cubeTexture, 32, 32, new Point(0, 10), new Point(15, 10), new Point(15, 10), magicType.TransitionTextures); VoxelType scaffoldType = new VoxelType { Name = "Scaffold", StartingHealth = 20, ProbabilityOfRelease = 1.0f, ResourceToRelease = ResourceLibrary.ResourceType.Wood, ReleasesResource = false, CanRamp = false, RampSize = 0.5f, IsBuildable = true, ParticleType = "stone_particle" }; VoxelType grassType = new VoxelType { Name = "Grass", ProbabilityOfRelease = 0.1f, ResourceToRelease = ResourceLibrary.ResourceType.Dirt, StartingHealth = 10, ReleasesResource = true, CanRamp = true, RampSize = 0.5f, IsBuildable = false, ParticleType = "dirt_particle", HasTransitionTextures = true, IsSoil = true, IsSurface = true }; CreateTransitionUVs(graphics, cubeTexture, 32, 32, new Point(0, 3), new Point(2, 0), new Point(2, 0), grassType.TransitionTextures); VoxelType frostType = new VoxelType { Name = "Frost", ProbabilityOfRelease = 0.1f, ResourceToRelease = ResourceLibrary.ResourceType.Dirt, StartingHealth = 10, ReleasesResource = true, CanRamp = true, RampSize = 0.5f, IsBuildable = false, ParticleType = "dirt_particle", HasTransitionTextures = true, IsSurface = true }; CreateTransitionUVs(graphics, cubeTexture, 32, 32, new Point(0, 4), new Point(2, 0), new Point(2, 0), frostType.TransitionTextures); VoxelType snowType = new VoxelType { Name = "Snow", StartingHealth = 1, ReleasesResource = false, CanRamp = true, RampSize = 0.5f, IsBuildable = false, ParticleType = "snow_particle", HasTransitionTextures = false, IsSurface = true, IsSoil = false }; RegisterType(snowType, snowCube); VoxelType iceType = new VoxelType { Name = "Ice", StartingHealth = 1, ReleasesResource = false, CanRamp = false, IsBuildable = false, ParticleType = "snow_particle", HasTransitionTextures = false, IsSurface = true, IsSoil = false }; RegisterType(iceType, iceCube); VoxelType desertGrass = new VoxelType { Name = "DesertGrass", ProbabilityOfRelease = 0.1f, ResourceToRelease = ResourceLibrary.ResourceType.Sand, StartingHealth = 20, ReleasesResource = true, CanRamp = true, RampSize = 0.5f, IsBuildable = false, ParticleType = "sand_particle", HasTransitionTextures = true, IsSurface = true, IsSoil = true }; CreateTransitionUVs(graphics, cubeTexture, 32, 32, new Point(0, 6), new Point(1, 1), new Point(1, 1), desertGrass.TransitionTextures); VoxelType jungleGrass = new VoxelType { Name = "JungleGrass", ProbabilityOfRelease = 0.1f, ResourceToRelease = ResourceLibrary.ResourceType.Dirt, StartingHealth = 30, ReleasesResource = true, CanRamp = true, RampSize = 0.5f, IsBuildable = false, ParticleType = "dirt_particle", HasTransitionTextures = true, IsSurface = true, IsSoil = true }; CreateTransitionUVs(graphics, cubeTexture, 32, 32, new Point(0, 5), new Point(2, 0), new Point(2, 0), jungleGrass.TransitionTextures); VoxelType caveFungus = new VoxelType { Name = "CaveFungus", ProbabilityOfRelease = 0.25f, ResourceToRelease = ResourceLibrary.ResourceType.Stone, StartingHealth = 30, ReleasesResource = true, CanRamp = false, RampSize = 0.5f, IsBuildable = false, ParticleType = "stone_particle", HasTransitionTextures = true, IsSurface = false, IsSoil = true }; CreateTransitionUVs(graphics, cubeTexture, 32, 32, new Point(0, 13), new Point(1, 0), new Point(1, 0), caveFungus.TransitionTextures); VoxelType dirtType = new VoxelType { Name = "Dirt", ReleasesResource = true, ResourceToRelease = ResourceLibrary.ResourceType.Dirt, ProbabilityOfRelease = 0.3f, StartingHealth = 10, RampSize = 0.5f, CanRamp = true, IsBuildable = true, ParticleType = "dirt_particle", IsSoil = true }; VoxelType stoneType = new VoxelType { Name = "Stone", ProbabilityOfRelease = 0.5f, ReleasesResource = true, ResourceToRelease = ResourceLibrary.ResourceType.Stone, StartingHealth = 40, IsBuildable = true, ParticleType = "stone_particle" }; VoxelType bedrockType = new VoxelType { Name = "Bedrock", StartingHealth = 255, IsBuildable = false, IsInvincible = true }; VoxelType waterType = new VoxelType { Name = "water", ReleasesResource = false, IsBuildable = false, StartingHealth = 255 }; VoxelType sandType = new VoxelType { Name = "Sand", ReleasesResource = true, StartingHealth = 15, CanRamp = true, RampSize = 0.5f, IsBuildable = false, ParticleType = "sand_particle", IsSurface = true, ResourceToRelease = ResourceLibrary.ResourceType.Sand, ProbabilityOfRelease = 0.5f }; VoxelType ironType = new VoxelType { Name = "Iron", ProbabilityOfRelease = 0.99f, ReleasesResource = true, ResourceToRelease = ResourceLibrary.ResourceType.Iron, StartingHealth = 80, IsBuildable = false, ParticleType = "stone_particle", SpawnClusters = true, ClusterSize = 5, SpawnVeins = true, VeinLength = 10, Rarity = 0.0f, MinSpawnHeight = 8, MaxSpawnHeight = 40, SpawnProbability = 0.99f }; VoxelType coalType = new VoxelType { Name = "Coal", ProbabilityOfRelease = 0.99f, ReleasesResource = true, ResourceToRelease = ResourceLibrary.ResourceType.Coal, StartingHealth = 75, IsBuildable = false, ParticleType = "stone_particle", SpawnClusters = true, ClusterSize = 5, MinSpawnHeight = 15, MaxSpawnHeight = 50, SpawnProbability = 0.3f, Rarity = 0.05f, SpawnOnSurface = true }; VoxelType goldType = new VoxelType { Name = "Gold", ProbabilityOfRelease = 1.0f, ReleasesResource = true, ResourceToRelease = ResourceLibrary.ResourceType.Gold, StartingHealth = 90, IsBuildable = false, ParticleType = "stone_particle", SpawnVeins = true, VeinLength = 20, Rarity = 0.2f, MinSpawnHeight = 0, MaxSpawnHeight = 20, SpawnProbability = 0.99f }; VoxelType greenGem = new VoxelType { Name = "Emerald", ProbabilityOfRelease = 1.0f, ReleasesResource = true, ResourceToRelease = "Emerald", StartingHealth = 90, IsBuildable = false, ParticleType = "stone_particle", SpawnClusters = true, ClusterSize = 3, MinSpawnHeight = 0, MaxSpawnHeight = 18, SpawnProbability = 0.8f, Rarity = 0.9f }; VoxelType redGem = new VoxelType { Name = "Ruby", ProbabilityOfRelease = 1.0f, ReleasesResource = true, ResourceToRelease = "Ruby", StartingHealth = 90, IsBuildable = false, ParticleType = "stone_particle", SpawnClusters = true, ClusterSize = 3, MinSpawnHeight = 0, MaxSpawnHeight = 18, SpawnProbability = 0.8f, Rarity = 0.9f }; VoxelType purpleGem = new VoxelType { Name = "Amethyst", ProbabilityOfRelease = 1.0f, ReleasesResource = true, ResourceToRelease = "Amethyst", StartingHealth = 90, IsBuildable = false, ParticleType = "stone_particle", ClusterSize = 3, SpawnClusters = true, MinSpawnHeight = 0, MaxSpawnHeight = 18, SpawnProbability = 0.8f, Rarity = 0.9f }; VoxelType blueGem = new VoxelType { Name = "Sapphire", ProbabilityOfRelease = 1.0f, ReleasesResource = true, ResourceToRelease = "Sapphire", StartingHealth = 90, IsBuildable = false, ParticleType = "stone_particle", SpawnClusters = true, ClusterSize = 3, MinSpawnHeight = 0, MaxSpawnHeight = 18, SpawnProbability = 0.8f, Rarity = 0.9f }; VoxelType yellowGem = new VoxelType { Name = "Citrine", ProbabilityOfRelease = 1.0f, ReleasesResource = true, ResourceToRelease = "Citrine", StartingHealth = 90, IsBuildable = false, ParticleType = "stone_particle", SpawnClusters = true, ClusterSize = 3, MinSpawnHeight = 0, MaxSpawnHeight = 18, SpawnProbability = 0.8f, Rarity = 0.9f }; VoxelType orangeGem = new VoxelType { Name = "Garnet", ProbabilityOfRelease = 1.0f, ReleasesResource = true, ResourceToRelease = "Garnet", StartingHealth = 90, IsBuildable = false, ParticleType = "stone_particle", SpawnClusters = true, ClusterSize = 3, MinSpawnHeight = 0, MaxSpawnHeight = 18, SpawnProbability = 0.8f, Rarity = 0.9f }; VoxelType manaType = new VoxelType { Name = "Mana", ProbabilityOfRelease = 1.0f, ReleasesResource = true, ResourceToRelease = ResourceLibrary.ResourceType.Mana, StartingHealth = 200, IsBuildable = false, ParticleType = "stone_particle", SpawnVeins = true, VeinLength = 25, Rarity = 0.1f, MinSpawnHeight = 0, MaxSpawnHeight = 14, SpawnProbability = 0.99f }; RegisterType(greenGem, greenGemCube); RegisterType(redGem, redGemCube); RegisterType(purpleGem, purpleGemCube); RegisterType(blueGem, blueGemCube); RegisterType(orangeGem, orangeGemCube); RegisterType(yellowGem, yellowGemCube); RegisterType(grassType, grassCube); RegisterType(frostType, frostCube); RegisterType(desertGrass, grassCube); RegisterType(jungleGrass, grassCube); RegisterType(caveFungus, grassCube); RegisterType(emptyType, null); RegisterType(dirtType, dirtCube); RegisterType(stoneType, stoneCube); RegisterType(waterType, waterCube); RegisterType(sandType, sandCube); RegisterType(ironType, ironCube); RegisterType(goldType, goldCube); RegisterType(manaType, manaCube); RegisterType(plankType, plankCube); RegisterType(scaffoldType, scaffoldCube); RegisterType(bedrockType, bedrockCube); RegisterType(coalType, coalCube); RegisterType(magicType, magicCube); foreach (VoxelType type in VoxelType.TypeList) { Types[type.Name] = type; } }
public static Texture2D RenderIcons(GraphicsDevice device, Microsoft.Xna.Framework.Content.ContentManager Content, Gui.JsonTileSheet Sheet) { InitializeDefaultLibrary(device); var shader = new Shader(Content.Load <Effect>(ContentPaths.Shaders.TexturedShaders), true); var sqrt = (int)(Math.Ceiling(Math.Sqrt(PrimitiveMap.Count))); var width = MathFunctions.NearestPowerOf2(sqrt * Sheet.TileWidth); var height = MathFunctions.NearestPowerOf2(sqrt * Sheet.TileWidth); RenderTarget2D toReturn = new RenderTarget2D(device, width, height, false, SurfaceFormat.Color, DepthFormat.Depth16, 16, RenderTargetUsage.PreserveContents); device.SetRenderTarget(toReturn); device.Clear(Color.Transparent); shader.SetIconTechnique(); shader.MainTexture = AssetManager.GetContentTexture(ContentPaths.Terrain.terrain_tiles); shader.SelfIlluminationEnabled = true; shader.SelfIlluminationTexture = AssetManager.GetContentTexture(ContentPaths.Terrain.terrain_illumination); shader.EnableShadows = false; shader.EnableLighting = false; shader.ClippingEnabled = false; shader.CameraPosition = new Vector3(-0.5f, 0.5f, 0.5f); shader.VertexColorTint = Color.White; shader.LightRamp = Color.White; shader.SunlightGradient = AssetManager.GetContentTexture(ContentPaths.Gradients.sungradient); shader.AmbientOcclusionGradient = AssetManager.GetContentTexture(ContentPaths.Gradients.ambientgradient); shader.TorchlightGradient = AssetManager.GetContentTexture(ContentPaths.Gradients.torchgradient); Viewport oldview = device.Viewport; int rows = height / Sheet.TileWidth; int cols = width / Sheet.TileWidth; device.ScissorRectangle = new Rectangle(0, 0, Sheet.TileWidth, Sheet.TileWidth); device.RasterizerState = RasterizerState.CullNone; device.DepthStencilState = DepthStencilState.Default; Vector3 half = Vector3.One * 0.5f; half = new Vector3(half.X, half.Y, half.Z); List <VoxelType> voxelsByType = Types.Select(type => type.Value).ToList(); voxelsByType.Sort((a, b) => a.ID < b.ID ? -1 : 1); foreach (EffectPass pass in shader.CurrentTechnique.Passes) { foreach (var type in voxelsByType) { int row = type.ID / cols; int col = type.ID % cols; BoxPrimitive primitive = GetPrimitive(type); if (primitive == null) { continue; } if (type.HasTransitionTextures) { primitive = new BoxPrimitive(device, 1, 1, 1, type.TransitionTextures[new BoxTransition()]); } device.Viewport = new Viewport(col * Sheet.TileWidth, row * Sheet.TileWidth, Sheet.TileWidth, Sheet.TileWidth); Matrix viewMatrix = Matrix.CreateLookAt(new Vector3(-1.2f, 1.0f, -1.5f), Vector3.Zero, Vector3.Up); Matrix projectionMatrix = Matrix.CreateOrthographic(1.5f, 1.5f, 0, 5); shader.View = viewMatrix; shader.Projection = projectionMatrix; shader.World = Matrix.CreateTranslation(-half); shader.VertexColorTint = type.Tint; pass.Apply(); primitive.Render(device); } } device.Viewport = oldview; device.SetRenderTarget(null); return((Texture2D)toReturn); }
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(); }
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 static void BuildVoxelFaceGeometry( RawPrimitive Into, VoxelChunk Chunk, Cache Cache, BoxPrimitive Primitive, VoxelHandle V, Color Tint, BoxPrimitive.BoxTextureCoords UVs, Matrix VertexTransform, BoxFace BoxFace, bool ApplyLighting) { if (!IsFaceVisible(V, BoxFace, Chunk.Manager, out var neighbor)) { return; } var faceDescriptor = Primitive.GetFace(BoxFace); var indexOffset = Into.VertexCount; for (int faceVertex = 0; faceVertex < faceDescriptor.VertexCount; faceVertex++) { var vertex = Primitive.Vertices[faceDescriptor.VertexOffset + faceVertex]; var voxelVertex = Primitive.VertexClassifications[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; if (!V.IsExplored && !neighbor.IsValid) // Turns the outside of the world black when it's not explored. { Tint = new Color(0.0f, 0.0f, 0.0f, 1.0f); } } var rampOffset = Vector3.Zero; if (V.IsExplored && V.Type.CanRamp && ShouldRamp(voxelVertex, V.RampType)) { rampOffset = new Vector3(0, -0.5f, 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])); } // Sometimes flip the quad to smooth out lighting. 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)); } }