using UnityEngine; using System.Collections.Generic; using System; using System.Text.RegularExpressions; public class MeshGenerator : MonoBehaviour { public string jsonConfig = @"{ ""mesh"": [ { ""revertSeam"": 0, ""vertices"": [ 0, 0, 0, 1, 1, 0, 1, 0, 0 ], ""indices"": [ 0, 1, 2 ] }, { ""revertSeam"": 0, ""vertices"": [ 0, 0, 0, 0, 1, 0, 1, 1, 0 ], ""indices"": [ 0, 1, 2 ] index++; } ], ""instances"": [ { ""meshidx"": 0, ""uniforms"" : { ""vTransform"" : [0, 0, 0], ""vLocalTransform"": [""seamX / 2.0"", ""seamY / 2.0""], ""vSeamOffset"": [0, 0], ""vTextureSize"": [1, 1] }, ""texture"": ""data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAIAAAACCAYAAABytg0kAAAAAXNSR0IArs4c6QAAABRJREFUGFdj/M/A8J+BgYGBEcYAACwBA/9pGIu9AAAAAElFTkSuQmCC"" }, { ""meshidx"": 1, ""uniforms"" : { ""vTransform"" : [0, 0, 0], ""vLocalTransform"": [""seamX / 2.0"", ""seamY + 0.2 * y + seamY / 2.0""], ""vSeamOffset"": [0, 0], ""vTextureSize"": [1, 1] }, ""texture"": ""data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAIAAAACCAYAAABytg0kAAAAAXNSR0IArs4c6QAAABRJREFUGFdjZPjP8J+BgYGBEcYAACoDA/9cU2MPAAAAAElFTkSuQmCC"" }, { ""meshidx"": 0, ""uniforms"" : { ""vTransform"" : [0.5, 0, 0], ""vLocalTransform"": [""seamX / 2.0"", ""y + seamY + seamY / 2.0""], ""vSeamOffset"": [0, 0], ""vTextureSize"": [1, 1] }, ""texture"": ""data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAIAAAACCAYAAABytg0kAAAAAXNSR0IArs4c6QAAABRJREFUGFdjZGD4/5+BgYGBEcYAACgFA/86LIEuAAAAAElFTkSuQmCC"" }, { ""meshidx"": 1, ""uniforms"" : { ""vTransform"" : [0.5, 0, 0], ""vLocalTransform"": [""seamX / 2.0"", ""seamY / 2.0""], ""vSeamOffset"": [0, 0], ""vTextureSize"": [1, 1] }, ""texture"": ""data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAIAAAACCAYAAABytg0kAAAAAXNSR0IArs4c6QAAABRJREFUGFdjZPj//z8DAwMDI4wBAD7uBf32jHwdAAAAAElFTkSuQmCC"" } ] }"; private Material[] tileMaterials; [System.Serializable] public class MeshData { public int revertSeam; public List vertices; public List indices; } [System.Serializable] public class InstanceData { public int meshidx; public Dictionary uniforms; public string texture; } [System.Serializable] public class ConfigData { public List mesh; public List instances; } void Start() { GenerateMeshes(); } void GenerateMeshes() { Debug.Log("GenerateMeshes Start"); ConfigData config = JsonUtility.FromJson(jsonConfig); if (config == null || config.mesh == null || config.instances == null) { Debug.LogError("Invalid JSON configuration."); return; } Dictionary meshes = new Dictionary(); for (int i = 0; i < config.mesh.Count; i++) { MeshData meshData = config.mesh[i]; Mesh mesh = CreateMesh(meshData); meshes.Add(i, mesh); } InitTileMaterial(config.instances.Count); for (int i = 0; i < config.instances.Count; i++) { InstanceData instanceData = config.instances[i]; if (!meshes.ContainsKey(instanceData.meshidx)) { Debug.LogError($"Mesh index {instanceData.meshidx} not found."); continue; } Mesh mesh = meshes[instanceData.meshidx]; CreateCombainMesh(mesh, instanceData, i); } } Mesh CreateMesh(MeshData meshData) { Mesh mesh = new Mesh(); // Convert List to Vector3[] Vector3[] vertices = new Vector3[meshData.vertices.Count / 3]; for (int i = 0; i < meshData.vertices.Count; i += 3) { vertices[i / 3] = new Vector3(meshData.vertices[i], meshData.vertices[i + 1], meshData.vertices[i + 2]); } mesh.vertices = vertices; // Convert List to int[] mesh.triangles = meshData.indices.ToArray(); // Calculate UVs (simple mapping) Vector2[] uvs = new Vector2[vertices.Length]; for (int i = 0; i < vertices.Length; i++) { uvs[i] = new Vector2(vertices[i].x, vertices[i].y); } mesh.uv = uvs; mesh.RecalculateNormals(); // Calculate normals for proper lighting return mesh; } void InitTileMaterial(int size) { tileMaterials = new Material[size]; } void CreateCombainMesh(Mesh mesh, InstanceData instanceData, int index) { tileMaterials[index] = new Material(Shader.Find("Universal Render Pipeline/Lit")); Texture2D texture = LoadTextureFromBase64(instanceData.texture); tileMaterials[index].mainTexture = texture; // 对当前创建的贴图按照配置重新修改位置,旋转,缩放等信息 // ApplyTransforms(tileMaterials[index], instanceData.uniforms); } // void CreateInstance(Mesh mesh, InstanceData instanceData) // { // GameObject instanceObject = new GameObject("Instance"); // MeshFilter meshFilter = instanceObject.AddComponent(); // MeshRenderer meshRenderer = instanceObject.AddComponent(); // meshFilter.mesh = mesh; // // Material material = new Material(Shader.Find("Universal Render Pipeline/Lit")); // Material material = new Material(UniversalRenderPipeline.asset?.defaultShader); // Texture2D texture = LoadTextureFromBase64(instanceData.texture); // if (texture != null) // { // material.mainTexture = texture; // } // meshRenderer.material = material; // // Apply transforms from uniforms // ApplyTransforms(instanceObject, instanceData.uniforms); // } Texture2D LoadTextureFromBase64(string base64String) { if (string.IsNullOrEmpty(base64String)) return null; // Remove the data:image/...;base64, prefix string base64Data = Regex.Match(base64String, @"data:image/(?.+?);base64,(?.+)").Groups["data"].Value; if (string.IsNullOrEmpty(base64Data)) { Debug.LogError("Invalid base64 string format."); return null; } try { byte[] textureBytes = Convert.FromBase64String(base64Data); Texture2D texture = new Texture2D(1, 1); // Create a default texture if (texture.LoadImage(textureBytes)) { return texture; } else { Debug.LogError("Failed to load texture from base64 string."); return null; } } catch (FormatException) { Debug.LogError("Invalid base64 string."); return null; } } void ApplyTransforms(GameObject instanceObject, Dictionary uniforms) { if (uniforms == null) return; if (uniforms.ContainsKey("vTransform")) { List vTransform = ConvertObjectToList(uniforms["vTransform"]); if (vTransform != null && vTransform.Count == 3) { instanceObject.transform.position = new Vector3(vTransform[0], vTransform[1], vTransform[2]); } } if (uniforms.ContainsKey("vLocalTransform")) { List vLocalTransform = ConvertObjectToList(uniforms["vLocalTransform"]); if (vLocalTransform != null && vLocalTransform.Count == 2) { float seamX = 0.1f; float seamY = 0.1f; float x = 1f; float y = 1f; float localX = EvaluateExpression(vLocalTransform[0], seamX, seamY, x, y); float localY = EvaluateExpression(vLocalTransform[1], seamX, seamY, x, y); instanceObject.transform.localPosition = new Vector3(localX, localY, 0); } } } float EvaluateExpression(string expression, float seamX, float seamY, float x, float y) { // Replace variables and evaluate the expression expression = expression.Replace("seamX", seamX.ToString()).Replace("seamY", seamY.ToString()).Replace("x", x.ToString()).Replace("y", y.ToString()); try { return (float)new System.Data.DataTable().Compute(expression, ""); } catch (Exception e) { Debug.LogError($"Error evaluating expression: {expression}, {e.Message}"); return 0f; } } List ConvertObjectToList(object obj) { if (obj is List list) { List result = new List(); foreach (object item in list) { if (item is T convertedItem) { result.Add(convertedItem); } else { Debug.LogError($"Cannot convert item {item} to type {typeof(T)}"); return null; } } return result; } Debug.LogError($"Cannot convert object {obj} to List<{typeof(T)}>"); return null; } }