/// <summary> /// Gets surface data for this chunk. /// </summary> public int GetSurfaceData(Vector3Int internalPos) { Vector3Int worldPos = internalPos.InternalPosToWorldPos(this.ChunkPos); float value; if (worldPos.y == 0) { value = -50; } else { float noise1 = GameManager.Instance.NoiseGeneratorBase.GetNoise(worldPos.x, worldPos.y, worldPos.z); float noise2 = GameManager.Instance.NoiseGeneratorRidged.GetNoise(worldPos.x, worldPos.y, worldPos.z); if (GameManager.Instance.InvertBase == true) { noise1 *= -1; } if (GameManager.Instance.InvertRidged == true) { noise2 *= -1; } noise1.Remap(-1, 1, 0, 1); noise2.Remap(-1, 1, 0, 1); if (GameManager.Instance.NoiseCombination == GameManager.NoiseCombinationEnum.Min) { value = Mathf.Min(noise1, noise2); } else if (GameManager.Instance.NoiseCombination == GameManager.NoiseCombinationEnum.Max) { value = Mathf.Max(noise1, noise2); } else if (GameManager.Instance.NoiseCombination == GameManager.NoiseCombinationEnum.Average) { value = (noise1 + noise2) / 2f; } else if (GameManager.Instance.NoiseCombination == GameManager.NoiseCombinationEnum.Just1) { value = noise1; } else { value = noise2; } value += GameManager.Instance.YMultiplier * (worldPos.y - (GameManager.ChunksPerColumn / 2 * GameManager.ChunkSize)); } if (value >= GameManager.Instance.CutoffValue) { return(0); } else { return(1); } }
/// <summary> /// Generates surface data for this chunk. /// </summary> public void GenerateChunkSurfaceData() { Parallel.For(0, GameManager.Instance.ChunkSize, x => { Parallel.For(0, GameManager.Instance.ChunkSize, y => { Parallel.For(0, GameManager.Instance.ChunkSize, z => { Vector3Int internalPos = new Vector3Int(x, y, z); Vector3Int worldPos = internalPos.InternalPosToWorldPos(this.ChunkPos); float value; if (worldPos.y == 0) { value = -50; } else { if (GameManager.Instance.NoiseCombination == GameManager.NoiseCombinationEnum.Min) { value = Mathf.Min(GameManager.Instance.NoiseGenerator.GetNoise(worldPos.x, worldPos.y, worldPos.z).Remap(-1, 1, 0, 1), GameManager.Instance.NoiseGenerator2.GetNoise(worldPos.x, worldPos.y, worldPos.z).Remap(-1, 1, 0, 1)) + (GameManager.Instance.YMultiplier * (worldPos.y - (GameManager.Instance.ChunksPerColumn / 2 * GameManager.Instance.ChunkSize))); } else if (GameManager.Instance.NoiseCombination == GameManager.NoiseCombinationEnum.Max) { value = Mathf.Max(GameManager.Instance.NoiseGenerator.GetNoise(worldPos.x, worldPos.y, worldPos.z).Remap(-1, 1, 0, 1), GameManager.Instance.NoiseGenerator2.GetNoise(worldPos.x, worldPos.y, worldPos.z).Remap(-1, 1, 0, 1)) + (GameManager.Instance.YMultiplier * (worldPos.y - (GameManager.Instance.ChunksPerColumn / 2 * GameManager.Instance.ChunkSize))); } else if (GameManager.Instance.NoiseCombination == GameManager.NoiseCombinationEnum.Average) { value = ((GameManager.Instance.NoiseGenerator.GetNoise(worldPos.x, worldPos.y, worldPos.z).Remap(-1, 1, 0, 1) + GameManager.Instance.NoiseGenerator2.GetNoise(worldPos.x, worldPos.y, worldPos.z)) / 2f).Remap(-1, 1, 0, 1) + (GameManager.Instance.YMultiplier * (worldPos.y - (GameManager.Instance.ChunksPerColumn / 2 * GameManager.Instance.ChunkSize))); } else if (GameManager.Instance.NoiseCombination == GameManager.NoiseCombinationEnum.Just1) { value = GameManager.Instance.NoiseGenerator.GetNoise(worldPos.x, worldPos.y, worldPos.z).Remap(-1, 1, 0, 1) + (GameManager.Instance.YMultiplier * (worldPos.y - (GameManager.Instance.ChunksPerColumn / 2 * GameManager.Instance.ChunkSize))); } else { value = GameManager.Instance.NoiseGenerator2.GetNoise(worldPos.x, worldPos.y, worldPos.z).Remap(-1, 1, 0, 1) + (GameManager.Instance.YMultiplier * (worldPos.y - (GameManager.Instance.ChunksPerColumn / 2 * GameManager.Instance.ChunkSize))); } } if (value >= GameManager.Instance.CutoffValue) { this.surfaceData[x, y, z] = 0; } else { this.surfaceData[x, y, z] = 1; } }); }); }); }
/// <summary> /// Checks if the specified face of the block at the given position is visible. /// </summary> /// <param name="internalPos">The internal position of the block to check face visibility for.</param> /// <param name="chunkPos">The chunk position of the block to check face visibility for.</param> /// <param name="side">The side of the block to check face visibility for.</param> /// <returns>Returns true if that face is visible.</returns> private static bool CheckFaceVisibility(Vector3Int internalPos, Vector3Int chunkPos, Side side, out int lightingValue) { // TODO: When getting face visibility, if face is visible also get lighting values from nearby block lightingValue = 0; Vector3Int worldPos = internalPos.InternalPosToWorldPos(chunkPos); if (World.TryGetChunk(chunkPos, out Chunk chunk) == false) { return(false); } if (side == Side.Bottom) { if (internalPos.y > 0) { Block block = chunk.GetBlock(internalPos + new Vector3Int(0, -1, 0)); return(block.Transparency == Block.TransparencyEnum.Transparent || block.Transparency == Block.TransparencyEnum.SemiTransparent); } else // internalPos.y == 0 { Vector3Int bottomNeighborWorldPos = worldPos; bottomNeighborWorldPos += new Vector3Int(0, -1, 0); if (World.TryGetBlockFromWorldPos(bottomNeighborWorldPos, out Block block)) { return(block.Transparency == Block.TransparencyEnum.Transparent || block.Transparency == Block.TransparencyEnum.SemiTransparent); } return(false); } } else if (side == Side.Top) { if (internalPos.y < GameManager.Instance.ChunkSize - 1) { Block block = chunk.GetBlock(internalPos + new Vector3Int(0, 1, 0)); return(block.Transparency == Block.TransparencyEnum.Transparent || block.Transparency == Block.TransparencyEnum.SemiTransparent); } else // internalPos.y == GameManager.Instance.ChunkSize - 1 { Vector3Int topNeighborWorldPos = worldPos; topNeighborWorldPos += new Vector3Int(0, 1, 0); if (World.TryGetBlockFromWorldPos(topNeighborWorldPos, out Block block)) { return(block.Transparency == Block.TransparencyEnum.Transparent || block.Transparency == Block.TransparencyEnum.SemiTransparent); } return(true); } } else if (side == Side.Front) { if (internalPos.x > 0) { Block block = chunk.GetBlock(internalPos + new Vector3Int(-1, 0, 0)); return(block.Transparency == Block.TransparencyEnum.Transparent || block.Transparency == Block.TransparencyEnum.SemiTransparent); } else // internalPos.x == 0 { Vector3Int frontNeighborWorldPos = worldPos; frontNeighborWorldPos += new Vector3Int(-1, 0, 0); if (World.TryGetBlockFromWorldPos(frontNeighborWorldPos, out Block block)) { return(block.Transparency == Block.TransparencyEnum.Transparent || block.Transparency == Block.TransparencyEnum.SemiTransparent); } return(false); } } else if (side == Side.Back) { if (internalPos.x < GameManager.Instance.ChunkSize - 1) { Block block = chunk.GetBlock(internalPos + new Vector3Int(1, 0, 0)); return(block.Transparency == Block.TransparencyEnum.Transparent || block.Transparency == Block.TransparencyEnum.SemiTransparent); } else // internalPos.x == GameManager.Instance.ChunkSize - 1 { Vector3Int backNeighborWorldPos = worldPos; backNeighborWorldPos += new Vector3Int(1, 0, 0); if (World.TryGetBlockFromWorldPos(backNeighborWorldPos, out Block block)) { return(block.Transparency == Block.TransparencyEnum.Transparent || block.Transparency == Block.TransparencyEnum.SemiTransparent); } return(false); } } else if (side == Side.Left) { if (internalPos.z > 0) { Block block = chunk.GetBlock(internalPos + new Vector3Int(0, 0, -1)); return(block.Transparency == Block.TransparencyEnum.Transparent || block.Transparency == Block.TransparencyEnum.SemiTransparent); } else// internalPos.z == 0 { Vector3Int leftNeighborWorldPos = worldPos; leftNeighborWorldPos += new Vector3Int(0, 0, -1); if (World.TryGetBlockFromWorldPos(leftNeighborWorldPos, out Block block)) { return(block.Transparency == Block.TransparencyEnum.Transparent || block.Transparency == Block.TransparencyEnum.SemiTransparent); } return(false); } } else if (side == Side.Right) { if (internalPos.z < GameManager.Instance.ChunkSize - 1) { Block block = chunk.GetBlock(internalPos + new Vector3Int(0, 0, 1)); return(block.Transparency == Block.TransparencyEnum.Transparent || block.Transparency == Block.TransparencyEnum.SemiTransparent); } else // internalPos.z == GameManager.Instance.ChunkSize - 1 { Vector3Int rightNeighborWorldPos = worldPos; rightNeighborWorldPos += new Vector3Int(0, 0, 1); if (World.TryGetBlockFromWorldPos(rightNeighborWorldPos, out Block block)) { return(block.Transparency == Block.TransparencyEnum.Transparent || block.Transparency == Block.TransparencyEnum.SemiTransparent); } return(false); } } else { return(false); } }
/// <summary> /// Creates the mesh data for the block at the given internal position within the chunk at the given chunk position. /// </summary> /// <param name="block">The block type to create mesh for.</param> /// <param name="internalPos">The internal position of the block to create a mesh for.</param> /// <param name="chunkPos">The chunk position of the block to create a mesh for.</param> /// <returns>Returns the mesh data created for the block.</returns> public static MeshData CreateMesh(Block block, Vector3Int internalPos, Vector3Int chunkPos) { // TODO: Add support for block rotation so blocks with different faces can be placed in any orientation, or at least additional orientations. // TODO: Add lighting data into UV2 for mesh and use it in shader to determine brightness of texture. MeshData meshData = new MeshData(); bool topVis = CheckFaceVisibility(internalPos, chunkPos, Side.Top, out _); bool bottomVis = CheckFaceVisibility(internalPos, chunkPos, Side.Bottom, out _); bool frontVis = CheckFaceVisibility(internalPos, chunkPos, Side.Front, out _); bool backVis = CheckFaceVisibility(internalPos, chunkPos, Side.Back, out _); bool rightVis = CheckFaceVisibility(internalPos, chunkPos, Side.Right, out _); bool leftVis = CheckFaceVisibility(internalPos, chunkPos, Side.Left, out _); Vector3Int worldPos = internalPos.InternalPosToWorldPos(chunkPos); int rotation = Mathf.RoundToInt(GameManager.Instance.CaveWormPositionNoiseGenerator.GetNoise(worldPos.x, worldPos.y, worldPos.z).Remap(-1, 1, 0, 3)); BlockType blockType = BlockType.BlockTypes[block.ID]; // Top Face if (topVis) { string uvName = ((blockType.UniqueFaces & BlockType.UniqueFacesEnum.Top) == BlockType.UniqueFacesEnum.Top) ? blockType.BlockName + "_" + blockType.TopTextureName : blockType.BlockName; Vector2[] uvs = ((blockType.RandomFaces & BlockType.RandomFacesEnum.Top) == BlockType.RandomFacesEnum.Top) ? UVMap.GetUVs(uvName).RotateUVs(rotation) : UVMap.GetUVs(uvName); meshData.Merge(new MeshData(topFaceVerts, topFaceTriangles, uvs, defaultUVs)); } // Bottom Face if (bottomVis) { string uvName = ((blockType.UniqueFaces & BlockType.UniqueFacesEnum.Bottom) == BlockType.UniqueFacesEnum.Bottom) ? blockType.BlockName + "_" + blockType.BottomTextureName : blockType.BlockName; Vector2[] uvs = ((blockType.RandomFaces & BlockType.RandomFacesEnum.Bottom) == BlockType.RandomFacesEnum.Bottom) ? UVMap.GetUVs(uvName).RotateUVs(rotation) : UVMap.GetUVs(uvName); meshData.Merge(new MeshData(bottomFaceVerts, bottomFaceTriangles, uvs, defaultUVs)); } // Front Face if (frontVis) { if (blockType.BlockName == "Grass" && World.TryGetBlockFromWorldPos(internalPos.InternalPosToWorldPos(chunkPos) + new Vector3Int(0, -1, 1), out Block neighborBlock) == true && BlockType.BlockTypes[neighborBlock.ID].BlockName == "Grass") { string uvName = blockType.BlockName; Vector2[] uvs = UVMap.GetUVs(uvName).RotateUVs(rotation); meshData.Merge(new MeshData(frontFaceVerts, frontFaceTriangles, uvs, defaultUVs)); } else { string uvName = ((blockType.UniqueFaces & BlockType.UniqueFacesEnum.Front) == BlockType.UniqueFacesEnum.Front) ? blockType.BlockName + "_" + blockType.FrontTextureName : blockType.BlockName; Vector2[] uvs = ((blockType.RandomFaces & BlockType.RandomFacesEnum.Front) == BlockType.RandomFacesEnum.Front) ? UVMap.GetUVs(uvName).RotateUVs(rotation) : UVMap.GetUVs(uvName).RotateUVs(3); meshData.Merge(new MeshData(frontFaceVerts, frontFaceTriangles, uvs, defaultUVs)); } } // Back Face if (backVis) { if (blockType.BlockName == "Grass" && World.TryGetBlockFromWorldPos(internalPos.InternalPosToWorldPos(chunkPos) + new Vector3Int(0, -1, -1), out Block neighborBlock) == true && BlockType.BlockTypes[neighborBlock.ID].BlockName == "Grass") { string uvName = blockType.BlockName; Vector2[] uvs = UVMap.GetUVs(uvName).RotateUVs(rotation); meshData.Merge(new MeshData(backFaceVerts, backFaceTriangles, uvs, defaultUVs)); } else { string uvName = ((blockType.UniqueFaces & BlockType.UniqueFacesEnum.Back) == BlockType.UniqueFacesEnum.Back) ? blockType.BlockName + "_" + blockType.BackTextureName : blockType.BlockName; Vector2[] uvs = ((blockType.RandomFaces & BlockType.RandomFacesEnum.Back) == BlockType.RandomFacesEnum.Back) ? UVMap.GetUVs(uvName).RotateUVs(rotation) : UVMap.GetUVs(uvName).RotateUVs(3); meshData.Merge(new MeshData(backFaceVerts, backFaceTriangles, uvs, defaultUVs)); } } // Right Face if (rightVis) { if (blockType.BlockName == "Grass" && World.TryGetBlockFromWorldPos(internalPos.InternalPosToWorldPos(chunkPos) + new Vector3Int(1, -1, 0), out Block neighborBlock) == true && BlockType.BlockTypes[neighborBlock.ID].BlockName == "Grass") { string uvName = blockType.BlockName; Vector2[] uvs = UVMap.GetUVs(uvName).RotateUVs(rotation); meshData.Merge(new MeshData(rightFaceVerts, rightFaceTriangles, uvs, defaultUVs)); } else { string uvName = ((blockType.UniqueFaces & BlockType.UniqueFacesEnum.Right) == BlockType.UniqueFacesEnum.Right) ? blockType.BlockName + "_" + blockType.RightTextureName : blockType.BlockName; Vector2[] uvs = ((blockType.RandomFaces & BlockType.RandomFacesEnum.Right) == BlockType.RandomFacesEnum.Right) ? UVMap.GetUVs(uvName).RotateUVs(rotation) : UVMap.GetUVs(uvName).RotateUVs(3); meshData.Merge(new MeshData(rightFaceVerts, rightFaceTriangles, uvs, defaultUVs)); } } // Left Face if (leftVis) { if (blockType.BlockName == "Grass" && World.TryGetBlockFromWorldPos(internalPos.InternalPosToWorldPos(chunkPos) + new Vector3Int(-1, -1, 0), out Block neighborBlock) == true && BlockType.BlockTypes[neighborBlock.ID].BlockName == "Grass") { string uvName = blockType.BlockName; Vector2[] uvs = UVMap.GetUVs(uvName).RotateUVs(rotation); meshData.Merge(new MeshData(leftFaceVerts, leftFaceTriangles, uvs, defaultUVs)); } else { string uvName = ((blockType.UniqueFaces & BlockType.UniqueFacesEnum.Left) == BlockType.UniqueFacesEnum.Left) ? blockType.BlockName + "_" + blockType.LeftTextureName : blockType.BlockName; Vector2[] uvs = ((blockType.RandomFaces & BlockType.RandomFacesEnum.Left) == BlockType.RandomFacesEnum.Left) ? UVMap.GetUVs(uvName).RotateUVs(rotation) : UVMap.GetUVs(uvName).RotateUVs(3); meshData.Merge(new MeshData(leftFaceVerts, leftFaceTriangles, uvs, defaultUVs)); } } meshData.OffsetPosition(new Vector3(internalPos.x - 0.5f, internalPos.y - 0.5f, internalPos.z - 0.5f)); return(meshData); }