示例#1
0
        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);
        }
示例#2
0
        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);
        }
示例#3
0
        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);
        }