public MeshData GenerateMeshData(CnkLOD cnkData) { MeshData meshData = new MeshData(); uint vertCount = 0; for (int i = 0; i < 4; i++) { CnkLOD.RenderBatch renderBatch = cnkData.RenderBatches[i]; vertCount += renderBatch.VertexCount; } meshData.verts = new Vector3[vertCount]; meshData.uvs = new Vector2[vertCount]; // Verts and UVs uint offset = 0; for (int i = 0; i < 4; i++) { CnkLOD.RenderBatch renderBatch = cnkData.RenderBatches[i]; CalculateVertsAndUVs(offset, cnkData, renderBatch, i, meshData.verts, meshData.uvs); offset += renderBatch.VertexCount; } meshData.triangles = new int[4][]; // Triangles for (int i = 0; i < 4; i++) { CnkLOD.RenderBatch renderBatch = cnkData.RenderBatches[i]; meshData.triangles[i] = GetRenderBatchTriangles(cnkData, renderBatch); } return(meshData); }
private int[] GetRenderBatchTriangles(CnkLOD cnkData, CnkLOD.RenderBatch renderBatch) { int[] indices = new int[renderBatch.IndexCount]; for (int i = 0; i < renderBatch.IndexCount; i++) { indices[renderBatch.IndexCount - 1 - i] = Convert.ToInt32(cnkData.Indices[i + (int)renderBatch.IndexOffset] + renderBatch.VertexOffset); } return(indices); }
private void CalculateVertsAndUVs(uint offset, CnkLOD cnkData, CnkLOD.RenderBatch renderBatch, int index, Vector3[] verts, Vector2[] uvs) { for (int i = 0; i < renderBatch.VertexCount; i++) { int k = (int)(renderBatch.VertexOffset + i); double x = cnkData.Vertices[k].X + (index >> 1) * 64; double y = cnkData.Vertices[k].Y + (index % 2) * 64; double heightNear = (double)cnkData.Vertices[k].HeightNear / 64; verts[offset + i] = new Vector3((float)x, (float)heightNear, (float)y); uvs[offset + i] = new Vector2((float)y / 128, 1 - (float)x / 128); } }
public Material GetMaterial(CnkLOD chunkData) { Texture2D[] diffuseTextures = new Texture2D[chunkData.Textures.Count]; Texture2D[] specTextures = new Texture2D[chunkData.Textures.Count]; for (int i = 0; i < chunkData.Textures.Count; i++) { CnkLOD.Texture texture = chunkData.Textures[i]; Dds diffuse = texture.ColorNXMap; Dds spec = texture.SpecNyMap; Texture2D diffuseTex = new Texture2D(diffuse.Width, diffuse.Height, diffuse.TextureFormat, false); Texture2D specTex = new Texture2D(spec.Width, spec.Height, spec.TextureFormat, false); diffuseTex.LoadRawTextureData(diffuse.TextureData.Data); specTex.LoadRawTextureData(spec.TextureData.Data); diffuseTextures[i] = diffuseTex; specTextures[i] = specTex; } Texture2D materialDiffuse = new Texture2D(1024, 1024); materialDiffuse.PackTextures(diffuseTextures, 0, 2048, true); materialDiffuse.name = chunkData.Name + " Diffuse"; Texture2D materialSpec = new Texture2D(1024, 1024); materialSpec.PackTextures(specTextures, 0, 2048, true); materialSpec.name = chunkData.Name + " Specular"; Material material = new Material(source); material.SetTexture("_MainTex", materialDiffuse); material.SetTextureScale("_MainTex", new Vector2(1, -1)); material.SetTexture("_PackedSpecular", materialSpec); material.SetTextureScale("_PackedSpecular", new Vector2(1, -1)); return(material); }
//TODO Less Code Duplication. //TODO Update CNK0 Parsing. The current format seems to be incorrect. public void ImportTerrain(float progress0, float progress100) { int chunksProcessed = 0; string assetProcessing = ""; //CNK0 (Geo) //List<AssetRef> terrainAssetsCnk0 = AssetsByType[AssetRef.Types.CNK0]; //Parallel.AsyncForEach<AssetRef> parallelTask = System.Threading.Tasks.Parallel.ForEach; //IAsyncResult result = parallelTask.BeginInvoke(terrainAssetsCnk0, asset => //{ // if (asset == null) // { // return; // } // //Names // string assetName = asset.Name; // string assetDisplayName = BuildAssetName(assetName, asset.Pack.Name); // //De-serialize // using (MemoryStream terrainMemoryStream = asset.Pack.CreateAssetMemoryStreamByName(asset.Name)) // { // Cnk0 chunk = Cnk0.LoadFromStream(assetName, assetDisplayName, terrainMemoryStream); // if (chunk != null) // { // ChunkExporter.ExportChunk(this, chunk, ResourceDirectory + "/Terrain"); // assetProcessing = assetName; // } // Interlocked.Increment(ref chunksProcessed); // } //}, null, null); //while (!result.IsCompleted) //{ // ProgressBar(MathUtils.Remap01(chunksProcessed / ((float)terrainAssetsCnk0.Count), progress0, progress100), "Exporting Chunk: " + assetProcessing); //} //chunksProcessed = 0; //texturesProcessed = 0; //CNK1 (Geo) List <AssetRef> terrainAssetsCnk1 = AssetsByType[AssetRef.Types.CNK1]; object texLock = new object(); Parallel.AsyncForEach <AssetRef> parallelTask = System.Threading.Tasks.Parallel.ForEach; IAsyncResult result = parallelTask.BeginInvoke(terrainAssetsCnk1, asset => { Interlocked.Increment(ref chunksProcessed); if (asset == null) { return; } //Names string assetName = asset.Name; string assetDisplayName = BuildAssetName(assetName, asset.Pack.Name); //De-serialize using (MemoryStream terrainMemoryStream = asset.Pack.CreateAssetMemoryStreamByName(assetName)) { CnkLOD chunk = CnkLOD.LoadFromStream(assetName, assetDisplayName, terrainMemoryStream); if (chunk != null) { ChunkExporter.ExportChunk(this, chunk, ResourceDirectory + "/Terrain"); lock (texLock) { ChunkExporter.ExportTextures(this, chunk, ResourceDirectory + "/Terrain"); } } assetProcessing = assetName; } }, null, null); while (!result.IsCompleted) { ProgressBar(MathUtils.Remap01((float)chunksProcessed / terrainAssetsCnk1.Count, progress0, progress100), "Exporting Chunk: " + assetProcessing); } parallelTask.EndInvoke(result); ////CNK2 //ProgressBar(progress0 + MathUtils.RemapProgress(0.50f, progress0, progress100), "Exporting Terrain Data (LOD 2)..."); //List<Asset> terrainAssetsCnk2 = AssetsByType[Asset.Types.CNK2]; //int terrainAssetsCnk2Processed = 0; //Parallel.ForEach(terrainAssetsCnk2, asset => //{ // using (MemoryStream terrainMemoryStream = asset.Pack.CreateAssetMemoryStreamByName(asset.Name)) // { // CnkLOD chunk = CnkLOD.LoadFromStream(asset.Name, terrainMemoryStream); // } // Interlocked.Increment(ref terrainAssetsCnk2Processed); // //ProgressBar(MathUtils.RemapProgress((float)terrainAssetsCnk2Processed / (float)terrainAssetsCnk2.Count, progress0, progress100), "Exporting Chunk (LOD2): " + Path.GetFileName(asset.Name)); //}); ////CNK3 //ProgressBar(progress0 + MathUtils.RemapProgress(0.75f, progress0, progress100), "Exporting Terrain Data (LOD 3)..."); //List<Asset> terrainAssetsCnk3 = AssetsByType[Asset.Types.CNK3]; //int terrainAssetsCnk3Processed = 0; //Parallel.ForEach(terrainAssetsCnk3, asset => //{ // using (MemoryStream terrainMemoryStream = asset.Pack.CreateAssetMemoryStreamByName(asset.Name)) // { // CnkLOD chunk = CnkLOD.LoadFromStream(asset.Name, terrainMemoryStream); // } // Interlocked.Increment(ref terrainAssetsCnk3Processed); // //ProgressBar(MathUtils.RemapProgress((float)terrainAssetsCnk3Processed / (float)terrainAssetsCnk3.Count, progress0, progress100), "Exporting Chunk (LOD3): " + Path.GetFileName(asset.Name)); //}); }
public async Task <ForgelightChunk> CreateChunk(AssetRef assetRef, Transform parent) { await new WaitForBackgroundThread(); string chunkName = Path.GetFileNameWithoutExtension(assetRef.Name); // Mesh CnkLOD chunkData = assetManager.CreateAsset <CnkLOD>(assetRef); Assert.IsNotNull(chunkData); // Deserialization Mesh mesh; Material material; try { MeshData meshData = chunkMeshFactory.GenerateMeshData(chunkData); await new WaitForUpdate(); mesh = chunkMeshFactory.CreateMeshFromData(chunkData.Name, meshData); material = materialFactory.GetMaterial(chunkData); } catch (Exception e) { Debug.LogErrorFormat("An error occurred while creating chunk \"{0}\". See below for details.", assetRef.Name); Debug.LogException(e); assetManager.Dispose(chunkData); return(null); } assetManager.Dispose(chunkData); Assert.IsNotNull(mesh); Assert.IsNotNull(material); // GameObject Instance GameObject instance = new GameObject(chunkName); ForgelightChunk chunk = instance.AddComponent <ForgelightChunk>(); MeshFilter meshFilter = instance.AddComponent <MeshFilter>(); MeshRenderer meshRenderer = instance.AddComponent <MeshRenderer>(); // Assign deserialized data meshFilter.sharedMesh = mesh; // TODO Make a combined mesh instead of supplying the same material 4 times. Material[] materials = new Material[4]; for (int i = 0; i < materials.Length; i++) { materials[i] = material; } meshRenderer.sharedMaterials = materials; // Position the terrain instance string[] nameElements = chunkName.Split('_'); // Multiply the position on each axis by the size of the chunk, as we are given only chunk coordinates. int chunkPosX = (Convert.ToInt32(nameElements[2]) * CHUNK_POS_OFFSET); int chunkPosZ = (Convert.ToInt32(nameElements[1]) * CHUNK_POS_OFFSET); chunk.transform.SetParent(parent); chunk.transform.position = new Vector3(chunkPosX, 0, chunkPosZ); return(chunk); }