public Vector2[] CreateUV(PreMesh pmesh) { Vector2[] UV = new Vector2[pmesh.Verticies.Length]; float scaleFactor = .4f; for (int index = 0; index < pmesh.Triangles.Length; index += 3) { // Get the three vertices bounding this triangle. Vector3 v1 = pmesh.Verticies[pmesh.Triangles[index]]; Vector3 v2 = pmesh.Verticies[pmesh.Triangles[index + 1]]; Vector3 v3 = pmesh.Verticies[pmesh.Triangles[index + 2]]; // Compute a vector perpendicular to the face. Vector3 normal = Vector3.Cross(v3 - v1, v2 - v1); // Form a rotation that points the z+ axis in this perpendicular direction. // Multiplying by the inverse will flatten the triangle into an xy plane. Quaternion rotation = Quaternion.Inverse(Quaternion.LookRotation(normal)); // Assign the uvs, applying a scale factor to control the texture tiling. UV[pmesh.Triangles[index]] = (Vector2)(rotation * v1) * scaleFactor; UV[pmesh.Triangles[index + 1]] = (Vector2)(rotation * v2) * scaleFactor; UV[pmesh.Triangles[index + 2]] = (Vector2)(rotation * v3) * scaleFactor; } return(UV); }
public PreLoadedChunk(Vec2i cPos, PreMesh terrain, ChunkData cDat) { Position = cPos; TerrainMesh = terrain; VoxelMesh = new Dictionary <Voxel, PreMesh>(); ChunkData = cDat; }
void GenerateSurface() { List <PreMesh> preMeshes = new List <PreMesh>(); for (int x = 0; x < Width; x++) { for (int y = 0; y < Height; y++) { preMeshes.Add(CreateTopPanel(x, y, Global.GetTexture(this[x, y].Material))); } } Mesh.mesh = PreMesh.ToMesh(preMeshes); }
public static Mesh CreateMesh(PreMesh pmesh) { Mesh mesh = new Mesh(); mesh.vertices = pmesh.Verticies; mesh.triangles = pmesh.Triangles; if (pmesh.Colours != null) { mesh.colors = pmesh.Colours; } if (pmesh.UV != null) { mesh.uv = pmesh.UV; } if (pmesh.Normals != null) { mesh.normals = pmesh.Normals; } return(mesh); }
private PreMesh GenerateSmoothTerrain(ChunkData chunk, int LOD = 1) { int size = World.ChunkSize / LOD; Color[,] colourMap = new Color[size + 1, size + 1]; ClearBuffers(); ChunkData[] neighbors = GetNeighbors(new Vec2i(chunk.X, chunk.Z)); for (int x = 0; x <= size; x++) { for (int z = 0; z <= size; z++) { float height = 0; if (x == size && z == size) { if (neighbors != null && neighbors[1] != null) { height = neighbors[1].BaseHeight; if (neighbors[1].Heights != null) { height = neighbors[1].Heights[0, 0]; } colourMap[x, z] = neighbors[1].GetTile(0, 0).GetColor(); } else { //height = chunk.Heights != null ? chunk.Heights[x - 1, z - 1] : height; colourMap[x, z] = chunk.GetTile((x - 1) * LOD, (z - 1) * LOD).GetColor(); } } else if (x == size) { if (neighbors != null && neighbors[2] != null) { height = neighbors[2].BaseHeight; if (neighbors[2].Heights != null) { height = neighbors[2].Heights[0, z *LOD]; } colourMap[x, z] = neighbors[2].GetTile(0, z * LOD).GetColor(); } else { height = chunk.Heights != null ? chunk.Heights[(x - 1) * LOD, z *LOD] : height; colourMap[x, z] = chunk.GetTile((x - 1) * LOD, z * LOD).GetColor(); } } else if (z == size) { if (neighbors != null && neighbors[0] != null) { height = neighbors[0].BaseHeight; if (neighbors[0].Heights != null) { height = neighbors[0].Heights[x * LOD, 0]; } colourMap[x, z] = neighbors[0].GetTile(x * LOD, 0).GetColor(); } else { // height = chunk.Heights != null ? chunk.Heights[x, z - 1] : height; colourMap[x, z] = chunk.GetTile(x * LOD, (z - 1) * LOD).GetColor(); } } else { if (chunk.Heights != null) { height = chunk.Heights[x * LOD, z *LOD]; } colourMap[x, z] = chunk.GetTile(x * LOD, z * LOD).GetColor(); } CurrentColours.Add(colourMap[x, z]); CurrentVerticies.Add(new Vector3(x * LOD, height, z * LOD)); /* * for (int y = 0; y < height + 1; y++) * { * int idx = x + y * (World.ChunkSize + 1) + z * (World.ChunkHeight + 1) * (World.ChunkSize + 1); * * //cube[idx] = -2; * }*/ } } int vert = 0; int tris = 0; for (int z = 0; z < size; z++) { for (int x = 0; x < size; x++) { CurrentTriangles.Add(vert + 1); CurrentTriangles.Add(vert + size + 1); CurrentTriangles.Add(vert + 0); CurrentTriangles.Add(vert + size + 2); CurrentTriangles.Add(vert + size + 1); CurrentTriangles.Add(vert + 1); vert++; tris += 6; } vert++; } //We iterate each triangle /* for (int i = 0; i < CurrentTriangles.Count; i += 3) * { * int tri1 = CurrentTriangles[i]; * int tri2 = CurrentTriangles[i + 1]; * int tri3 = CurrentTriangles[i + 2]; * /*Vector3 vec1 = CurrentVerticies[i]; * Vector3 vec2 = CurrentVerticies[i+1]; * Vector3 vec3 = CurrentVerticies[i+2]; * * //We find the average/mid point of this triangle * Vector3 mid = (CurrentVerticies[tri1] + CurrentVerticies[tri2] + CurrentVerticies[tri3]) / 3; * //Vector3 mid = (vec1 + vec2 + vec3) / 3; * Vec2i tMid = Vec2i.FromVector3(mid); * Color c = colourMap[tMid.x, tMid.z]; * * CurrentColours.Add(c); * CurrentColours.Add(c); * CurrentColours.Add(c); * } * Debug.Log("Colours: " + CurrentColours.Count + " vert: " + CurrentVerticies.Count);*/ PreMesh pmesh = new PreMesh(); pmesh.Verticies = CurrentVerticies.ToArray(); pmesh.Triangles = CurrentTriangles.ToArray(); pmesh.Colours = CurrentColours.ToArray(); return(pmesh); }
/// <summary> /// Creates a pre loaded chunk from chunk data. /// This entire function is run in a thread /// </summary> /// <param name="cData"></param> /// <returns></returns> private PreLoadedChunk GeneratePreLoadedChunk(ChunkData chunk, int lod = 1) { //We create a thread safe mesh for the terrain // PreMesh terrainMesh = GenerateMarchingCubesTerrain(chunk); PreMesh terrainMesh = GenerateSmoothTerrain(chunk); Debug.Log("[ChunkLoader] Terrain mesh for " + chunk + " created - " + CurrentVerticies.Count + " verticies", Debug.CHUNK_LOADING); //Create the base pre-loaded chunk PreLoadedChunk preChunk = new PreLoadedChunk(new Vec2i(chunk.X, chunk.Z), terrainMesh, chunk); //if we have no voxel data, return just the terrain map if (chunk.VoxelData == null) { return(preChunk); } foreach (Voxel v in MiscUtils.GetValues <Voxel>()) { if (v == Voxel.none) { continue; } //If the chunk has this type of voxel in it if (chunk.VoxelData.VoxelTypeBounds.TryGetValue(v, out VoxelBounds vb)) { //Clear all lists to prepair CurrentVerticies.Clear(); CurrentTriangles.Clear(); CurrentColours.Clear(); CurrentUVs.Clear(); //Generate the voxel mesh //MarchingCubes.Generate(chunk.VoxelData.Voxels, vb, v, World.ChunkSize+1, World.ChunkHeight+1, World.ChunkSize+1, CurrentVerticies, CurrentTriangles); //MarchingCubes.Generate(chunk.VoxelData.Voxels, vb, v, World.ChunkSize + 1, chunk.VoxelData.TotalHeight(), World.ChunkSize + 1, CurrentVerticies, CurrentTriangles); MarchingCubes.Generate(chunk.VoxelData.AllVoxels, vb, v, World.ChunkSize + 1, chunk.VoxelData.TotalHeight(), World.ChunkSize + 1, CurrentVerticies, CurrentTriangles); PreMesh voxelMesh = new PreMesh(); voxelMesh.Verticies = CurrentVerticies.ToArray(); voxelMesh.Triangles = CurrentTriangles.ToArray(); voxelMesh.UV = CreateUV(voxelMesh); //Add it the the pre loaded chunk preChunk.VoxelMesh.Add(v, voxelMesh); } } if (chunk.WorldObjects != null) { /*lock (ObjectsToLoadLock) * { * Debug.Log("[ChunkLoader] Chunk " + chunk.X + "," + chunk.Z + " has " + chunk.WorldObjects.Count + " objects to load", Debug.CHUNK_LOADING); * * ObjectsToLoad.AddRange(chunk.WorldObjects); * }*/ } return(preChunk); }
public Vector2[] CreateUV(PreMesh pmesh) { return(CreateUV(pmesh, Vector2.zero, 0.5f)); }
private PreLoadedChunk GeneratePreLoadedChunk(ChunkData chunk) { //Null till we integrate fully //ChunkData2[] neighbors = null; ChunkData[] neighbors = GetNeighbors(new Vec2i(chunk.X, chunk.Z)); float[] cube = new float[(World.ChunkSize + 1) * (World.ChunkSize + 1) * (World.ChunkHeight + 1)]; Color[,] colourMap = new Color[World.ChunkSize + 1, World.ChunkSize + 1]; //We iterate through the whole chunk, and create a cub map and colour map based on the //height map and tile map for (int x = 0; x < World.ChunkSize + 1; x++) { for (int z = 0; z < World.ChunkSize + 1; z++) { float height = chunk.BaseHeight; if (x == World.ChunkSize && z == World.ChunkSize) { if (neighbors != null && neighbors[1] != null) { height = neighbors[1].BaseHeight; if (neighbors[1].Heights != null) { height = neighbors[1].Heights[0, 0]; } colourMap[x, z] = neighbors[1].GetTile(0, 0).GetColor(); } else { height = chunk.Heights != null ? chunk.Heights[x - 1, z - 1] : height; colourMap[x, z] = chunk.GetTile(x - 1, z - 1).GetColor(); } } else if (x == World.ChunkSize) { if (neighbors != null && neighbors[2] != null) { height = neighbors[2].BaseHeight; if (neighbors[2].Heights != null) { height = neighbors[2].Heights[0, z]; } colourMap[x, z] = neighbors[2].GetTile(0, z).GetColor(); } else { height = chunk.Heights != null ? chunk.Heights[x - 1, z] : height; colourMap[x, z] = chunk.GetTile(x - 1, z).GetColor(); } } else if (z == World.ChunkSize) { if (neighbors != null && neighbors[0] != null) { height = neighbors[0].BaseHeight; if (neighbors[0].Heights != null) { height = neighbors[0].Heights[x, 0]; } colourMap[x, z] = neighbors[0].GetTile(x, 0).GetColor(); } else { height = chunk.Heights != null ? chunk.Heights[x, z - 1] : height; colourMap[x, z] = chunk.GetTile(x, z - 1).GetColor(); } } else { if (chunk.Heights != null) { height = chunk.Heights[x, z]; } colourMap[x, z] = chunk.GetTile(x, z).GetColor(); } for (int y = 0; y < height + 1; y++) { int idx = x + y * (World.ChunkSize + 1) + z * (World.ChunkHeight + 1) * (World.ChunkSize + 1); cube[idx] = -2; } } } CurrentVerticies.Clear(); CurrentTriangles.Clear(); CurrentColours.Clear(); //March the terrain map MarchingCubes.Generate(cube, World.ChunkSize + 1, World.ChunkHeight + 1, World.ChunkSize + 1, CurrentVerticies, CurrentTriangles); /*for (int i = 0; i < CurrentTriangles.Count; i += 3) * { * int tri1 = CurrentTriangles[i]; * int tri2 = CurrentTriangles[i + 1]; * int tri3 = CurrentTriangles[i + 2]; * * //We find the average/mid point of this triangle * Vector3 mid = (CurrentVerticies[tri1] + CurrentVerticies[tri2] + CurrentVerticies[tri3]) / 3; * Vec2i tMid = Vec2i.FromVector3(mid); * Color c = colourMap[tMid.x, tMid.z]; * * CurrentColours.Add(c); * CurrentColours.Add(c); * CurrentColours.Add(c); * }*/ for (int i = 0; i < CurrentVerticies.Count; i++) { int x = (int)CurrentVerticies[i].x; int z = (int)CurrentVerticies[i].z; CurrentColours.Add(colourMap[x, z]); } //We create a thread safe mesh for the terrain PreMesh terrainMesh = new PreMesh(); terrainMesh.Verticies = CurrentVerticies.ToArray(); terrainMesh.Triangles = CurrentTriangles.ToArray(); terrainMesh.Colours = CurrentColours.ToArray(); terrainMesh.UV = CreateUV(terrainMesh); //Debug.Log("[ChunkLoader] Terrain mesh for " + chunk + " created - " + CurrentVerticies.Count + " verticies"); //Create the base pre-loaded chunk PreLoadedChunk preChunk = new PreLoadedChunk(new Vec2i(chunk.X, chunk.Z), terrainMesh, chunk); Debug.Log("Pre loaded chunk started, now for voxels"); //if we have no voxel data, return just the terrain map if (chunk.VoxelData == null) { Debug.Log("Chunk has no voxels"); return(preChunk); } foreach (Voxel v in MiscUtils.GetValues <Voxel>()) { if (v == Voxel.none) { continue; } if (!chunk.VoxelData.HasVoxel(v)) { // Debug.Log("Chunk " + chunk + " does not have the voxel " + v); continue; } CurrentVerticies.Clear(); CurrentTriangles.Clear(); CurrentColours.Clear(); CurrentUVs.Clear(); // Debug.Log("starting march"); //Generate the voxel mesh MarchingCubes.Generate(chunk.VoxelData.Voxels, null, v, World.ChunkSize + 1, World.ChunkHeight + 1, World.ChunkSize + 1, CurrentVerticies, CurrentTriangles); PreMesh voxelMesh = new PreMesh(); voxelMesh.Verticies = CurrentVerticies.ToArray(); voxelMesh.Triangles = CurrentTriangles.ToArray(); voxelMesh.UV = CreateUV(voxelMesh); //Add it the the pre loaded chunk preChunk.VoxelMesh.Add(v, voxelMesh); /* * //If the chunk has this type of voxel in it * if (chunk.VoxelData.VoxelTypeBounds.TryGetValue(v, out VoxelBounds vb)) * { * //Clear all lists to prepair * CurrentVerticies.Clear(); * CurrentTriangles.Clear(); * CurrentColours.Clear(); * CurrentUVs.Clear(); * Debug.Log("starting march"); * * //Generate the voxel mesh * MarchingCubes.Generate(chunk.VoxelData.Voxels, vb, v, World.ChunkSize+1, World.ChunkHeight+1, World.ChunkSize+1, CurrentVerticies, CurrentTriangles); * PreMesh voxelMesh = new PreMesh(); * voxelMesh.Verticies = CurrentVerticies.ToArray(); * voxelMesh.Triangles = CurrentTriangles.ToArray(); * voxelMesh.UV = CreateUV(voxelMesh); * //Add it the the pre loaded chunk * preChunk.VoxelMesh.Add(v, voxelMesh); * }*/ } return(preChunk); }
/// <summary> /// Creates a pre loaded chunk from chunk data. /// This entire function is run in a thread /// </summary> /// <param name="cData"></param> /// <returns></returns> private PreLoadedChunk GeneratePreLoadedChunk(ChunkData chunk, int lod = 1) { //We create a thread safe mesh for the terrain // PreMesh terrainMesh = GenerateMarchingCubesTerrain(chunk); ChunkData[] neighbors = ChunkRegionManager.GetNeighbors(new Vec2i(chunk.X, chunk.Z)); PreMesh terrainMesh = GenerateSmoothTerrain(chunk, neighbors, lod); terrainMesh.RecalculateNormals(); Debug.Log("[ChunkLoader] Terrain mesh for " + chunk + " created - " + CurrentVerticies.Count + " verticies", Debug.CHUNK_LOADING); //Create the base pre-loaded chunk PreLoadedChunk preChunk = new PreLoadedChunk(new Vec2i(chunk.X, chunk.Z), terrainMesh, chunk); //if we have no voxel data, return just the terrain map if (chunk.VoxelData == null) { return(preChunk); } int maxHeight = 0; if (neighbors != null) { foreach (ChunkData cd in neighbors) { if (cd != null && cd.VoxelData != null) { if (maxHeight < cd.VoxelData.TotalHeight()) { maxHeight = cd.VoxelData.TotalHeight(); } } } } //If the chunk hasn't had its boundry points defined, we do it now if (!chunk.VoxelData.HasBoundryVoxels) { for (int y = 0; y < maxHeight; y++) { for (int i = 0; i < World.ChunkSize; i++) { if (neighbors[0] != null && neighbors[0].VoxelData != null) { VoxelNode node = neighbors[0].VoxelData.GetVoxelNode(i, y, 0); if (node.IsNode) { chunk.VoxelData.SetVoxelNode(i, y, World.ChunkSize, node); } } if (neighbors[2] != null && neighbors[2].VoxelData != null) { VoxelNode node = neighbors[2].VoxelData.GetVoxelNode(0, y, i); if (node.IsNode) { chunk.VoxelData.SetVoxelNode(World.ChunkSize, y, i, node); } } } if (neighbors[1] != null && neighbors[1].VoxelData != null) { VoxelNode node = neighbors[1].VoxelData.GetVoxelNode(0, y, 0); if (node.IsNode) { chunk.VoxelData.SetVoxelNode(World.ChunkSize, y, World.ChunkSize, node); } } } chunk.VoxelData.HasBoundryVoxels = true; } //Next we generate all relevent voxel meshes foreach (Voxel v in MiscUtils.GetValues <Voxel>()) { if (v == Voxel.none) { continue; } //If the chunk has this type of voxel in it if (chunk.VoxelData.VoxelTypeBounds.TryGetValue(v, out VoxelBounds vb)) { //Clear all lists to prepair CurrentVerticies.Clear(); CurrentTriangles.Clear(); CurrentColours.Clear(); CurrentUVs.Clear(); //Generate the voxel mesh //MarchingCubes.Generate(chunk.VoxelData.Voxels, vb, v, World.ChunkSize+1, World.ChunkHeight+1, World.ChunkSize+1, CurrentVerticies, CurrentTriangles); //MarchingCubes.Generate(chunk.VoxelData.Voxels, vb, v, World.ChunkSize + 1, chunk.VoxelData.TotalHeight(), World.ChunkSize + 1, CurrentVerticies, CurrentTriangles); //MarchingCubes.Generate(chunk.VoxelData.AllVoxels, vb, v, World.ChunkSize + 1, chunk.VoxelData.TotalHeight(), World.ChunkSize + 1, CurrentVerticies, CurrentTriangles); MarchingCubes.Generate(chunk.VoxelData.AllVoxels, vb, v, World.ChunkSize + 1, chunk.VoxelData.TotalHeight(), World.ChunkSize + 1, CurrentVerticies, CurrentTriangles); PreMesh voxelMesh = new PreMesh(); voxelMesh.Verticies = CurrentVerticies.ToArray(); voxelMesh.Triangles = CurrentTriangles.ToArray(); voxelMesh.UV = CreateUV(voxelMesh); voxelMesh.RecalculateNormals(); //Add it the the pre loaded chunk preChunk.VoxelMesh.Add(v, voxelMesh); } } /* * if(chunk.WorldObjects != null) * { * * lock (ObjectsToLoadLock) * { * Debug.Log("[ChunkLoader] Chunk " + chunk.X + "," + chunk.Z + " has " + chunk.WorldObjects.Count + " objects to load", Debug.CHUNK_LOADING); * ObjectsToLoad.AddRange(chunk.WorldObjects); * } * * }*/ return(preChunk); }
private PreMesh GenerateMarchingCubesTerrain(ChunkData chunk) { ChunkData[] neighbors = ChunkRegionManager.GetNeighbors(new Vec2i(chunk.X, chunk.Z)); float[] cube = new float[(World.ChunkSize + 1) * (World.ChunkSize + 1) * (World.ChunkHeight + 1)]; Color[,] colourMap = new Color[World.ChunkSize + 1, World.ChunkSize + 1]; //We iterate through the whole chunk, and create a cub map and colour map based on the //height map and tile map for (int x = 0; x < World.ChunkSize + 1; x++) { for (int z = 0; z < World.ChunkSize + 1; z++) { float height = chunk.BaseHeight; if (x == World.ChunkSize && z == World.ChunkSize) { if (neighbors != null && neighbors[1] != null) { height = neighbors[1].BaseHeight; if (neighbors[1].Heights != null) { height = neighbors[1].Heights[0, 0]; } colourMap[x, z] = neighbors[1].GetTile(0, 0).GetColor(); } else { height = chunk.Heights != null ? chunk.Heights[x - 1, z - 1] : height; colourMap[x, z] = chunk.GetTile(x - 1, z - 1).GetColor(); } } else if (x == World.ChunkSize) { if (neighbors != null && neighbors[2] != null) { height = neighbors[2].BaseHeight; if (neighbors[2].Heights != null) { height = neighbors[2].Heights[0, z]; } colourMap[x, z] = neighbors[2].GetTile(0, z).GetColor(); } else { height = chunk.Heights != null ? chunk.Heights[x - 1, z] : height; colourMap[x, z] = chunk.GetTile(x - 1, z).GetColor(); } } else if (z == World.ChunkSize) { if (neighbors != null && neighbors[0] != null) { height = neighbors[0].BaseHeight; if (neighbors[0].Heights != null) { height = neighbors[0].Heights[x, 0]; } colourMap[x, z] = neighbors[0].GetTile(x, 0).GetColor(); } else { height = chunk.Heights != null ? chunk.Heights[x, z - 1] : height; colourMap[x, z] = chunk.GetTile(x, z - 1).GetColor(); } } else { if (chunk.Heights != null) { height = chunk.Heights[x, z]; } colourMap[x, z] = chunk.GetTile(x, z).GetColor(); } for (int y = 0; y < height + 1; y++) { int idx = x + y * (World.ChunkSize + 1) + z * (World.ChunkHeight + 1) * (World.ChunkSize + 1); cube[idx] = -2; } } } CurrentVerticies.Clear(); CurrentTriangles.Clear(); CurrentColours.Clear(); //March the terrain map MarchingCubes.Generate(cube, World.ChunkSize + 1, World.ChunkHeight + 1, World.ChunkSize + 1, CurrentVerticies, CurrentTriangles); //We iterate each triangle for (int i = 0; i < CurrentTriangles.Count; i += 3) { int tri1 = CurrentTriangles[i]; int tri2 = CurrentTriangles[i + 1]; int tri3 = CurrentTriangles[i + 2]; //We find the average/mid point of this triangle Vector3 mid = (CurrentVerticies[tri1] + CurrentVerticies[tri2] + CurrentVerticies[tri3]) / 3; Vec2i tMid = Vec2i.FromVector3(mid); Color c = colourMap[tMid.x, tMid.z]; CurrentColours.Add(c); CurrentColours.Add(c); CurrentColours.Add(c); } /* * for (int i = 0; i < CurrentVerticies.Count; i++) * { * int x = (int)CurrentVerticies[i].x; * int z = (int)CurrentVerticies[i].z; * CurrentColours.Add(colourMap[x, z]); * * }*/ //We create a thread safe mesh for the terrain PreMesh terrainMesh = new PreMesh(); terrainMesh.Verticies = CurrentVerticies.ToArray(); terrainMesh.Triangles = CurrentTriangles.ToArray(); terrainMesh.Colours = CurrentColours.ToArray(); return(terrainMesh); }