public override void OnInspectorGUI() { DrawDefaultInspector(); MultiTextureMaterial mat = (MultiTextureMaterial)target; mat.textureIndex = EditorGUILayout.Popup(mat.textureIndex, mat.textureNames); }
private void CreateUnityMesh() { for (uint i = 0; i < num_sprites; i++) { Mesh meshUnity = new Mesh(); Vector3[] vertices = new Vector3[4]; vertices[0] = new Vector3(-sprites[i].size.x / 2f, -sprites[i].size.y / 2f, 0); vertices[1] = new Vector3(sprites[i].size.x / 2f, -sprites[i].size.y / 2f, 0); vertices[2] = new Vector3(-sprites[i].size.x / 2f, sprites[i].size.y / 2f, 0); vertices[3] = new Vector3(sprites[i].size.x / 2f, sprites[i].size.y / 2f, 0); Vector3[] normals = new Vector3[4]; normals[0] = Vector3.forward; normals[1] = Vector3.forward; normals[2] = Vector3.forward; normals[3] = Vector3.forward; Vector2[] uvs = new Vector2[4]; uvs[0] = new Vector2(0, 0); uvs[1] = new Vector2(1, 0); uvs[2] = new Vector2(0, 1); uvs[3] = new Vector2(1, 1); int[] triangles = new int[] { 0, 2, 1, 1, 2, 3 }; meshUnity.vertices = vertices; meshUnity.normals = normals; meshUnity.triangles = triangles; meshUnity.uv = uvs; GameObject spr_gao = new GameObject(name + " - Sprite " + i); spr_gao.transform.SetParent(gao.transform); MeshFilter mf = spr_gao.AddComponent <MeshFilter>(); mf.mesh = meshUnity; MeshRenderer mr = spr_gao.AddComponent <MeshRenderer>(); if (sprites[i].r3mat != null) { Material unityMat = sprites[i].r3mat.Material; bool receiveShadows = (sprites[i].r3mat.properties & VisualMaterial.property_receiveShadows) != 0; //if (num_uvMaps > 1) unityMat.SetFloat("_UVSec", 50f); //if (r3mat.Material.GetColor("_EmissionColor") != Color.black) print("Mesh with emission: " + name); mr.material = unityMat; if (!receiveShadows) { mr.receiveShadows = false; } if (sprites[i].r3mat.off_animTextures.Count > 0) { MultiTextureMaterial mtmat = mr.gameObject.AddComponent <MultiTextureMaterial>(); mtmat.r3mat = sprites[i].r3mat; mtmat.mat = mr.material; } } if (sprites[i].r3mat != null) { mr.material = sprites[i].r3mat.Material; } } }
private void CreateUnityMesh() { /*if (mesh.bones != null) { * for (int j = 0; j < mesh.bones.num_bones; j++) { * Transform b = mesh.bones.bones[j]; * b.transform.SetParent(gao.transform); * mesh.bones.bindPoses[j] = mesh.bones.bones[j].worldToLocalMatrix * gao.transform.localToWorldMatrix; * } * }*/ VisualMaterial.Hint materialHints = Mesh.lookAtMode != 0 ? VisualMaterial.Hint.Billboard : VisualMaterial.Hint.None; //VisualMaterial.Hint materialHints = VisualMaterial.Hint.None; uint num_textures = 0; if (visualMaterial != null) { num_textures = visualMaterial.num_textures; } long num_triangles_main = ((num_connected_vertices > 2 ? num_connected_vertices - 2 : 0) + num_disconnected_triangles) * (backfaceCulling ? 1 : 2); uint triangle_size = 3 * (uint)(backfaceCulling ? 1 : 2); uint triangles_index = 0; if (num_triangles_main > 0) { Vector3[] new_vertices = new Vector3[num_mapping_entries]; Vector3[] new_normals = new Vector3[num_mapping_entries]; Vector4[][] new_uvs = new Vector4[num_textures + (vertexColors != null ? 1 : 0)][]; // Thanks to Unity we can only store the blend weights as a third component of the UVs BoneWeight[] new_boneWeights = Mesh.bones != null ? new BoneWeight[num_mapping_entries] : null; for (int um = 0; um < num_textures; um++) { new_uvs[um] = new Vector4[num_mapping_entries]; } if (vertexColors != null) { new_uvs[num_textures] = new Vector4[num_mapping_entries]; for (int i = 0; i < num_mapping_entries; i++) { new_uvs[num_textures][i] = new Vector4(vertexColors[i].r, vertexColors[i].g, vertexColors[i].b, vertexColors[i].a); } } for (int j = 0; j < num_mapping_entries; j++) { new_vertices[j] = Mesh.vertices[mapping_vertices[j]]; if (Mesh.normals != null) { new_normals[j] = Mesh.normals[mapping_vertices[j]]; } if (new_boneWeights != null) { new_boneWeights[j] = Mesh.bones.weights[mapping_vertices[j]]; } for (int um = 0; um < num_textures; um++) { uint uvMap = (uint)visualMaterial.textures[um].uvFunction % num_uvMaps; //MapLoader.Loader.print(visualMaterial.textures[um].uvFunction + " - " + num_uvMaps); new_uvs[um][j] = uvs[mapping_uvs[uvMap][j]]; if (Mesh.blendWeights != null && Mesh.blendWeights[visualMaterial.textures[um].blendIndex] != null) { if (um == 0) { materialHints |= VisualMaterial.Hint.Transparent; } new_uvs[um][j].z = Mesh.blendWeights[visualMaterial.textures[um].blendIndex][mapping_vertices[j]]; } else { new_uvs[um][j].z = 1; } } } int[] triangles = new int[num_triangles_main * triangle_size]; if (num_connected_vertices > 2) { for (int j = 0; j < num_connected_vertices - 2; j++, triangles_index += triangle_size) { if (j % 2 == 0) { triangles[triangles_index + 0] = connected_vertices[j + 0]; triangles[triangles_index + 1] = connected_vertices[j + 2]; triangles[triangles_index + 2] = connected_vertices[j + 1]; } else { triangles[triangles_index + 0] = connected_vertices[j + 0]; triangles[triangles_index + 1] = connected_vertices[j + 1]; triangles[triangles_index + 2] = connected_vertices[j + 2]; } if (!backfaceCulling) { triangles[triangles_index + 3] = triangles[triangles_index + 0]; triangles[triangles_index + 4] = triangles[triangles_index + 2]; triangles[triangles_index + 5] = triangles[triangles_index + 1]; } } } if (num_connected_vertices < 2) { num_connected_vertices = 0; } if (num_disconnected_triangles > 0) { //print("Loading disconnected triangles at " + String.Format("0x{0:X}", fs.Position)); for (int j = 0; j < num_disconnected_triangles; j++, triangles_index += triangle_size) { triangles[triangles_index + 0] = disconnected_triangles[(j * 3) + 0]; triangles[triangles_index + 2] = disconnected_triangles[(j * 3) + 1]; triangles[triangles_index + 1] = disconnected_triangles[(j * 3) + 2]; if (!backfaceCulling) { triangles[triangles_index + 3] = triangles[triangles_index + 0]; triangles[triangles_index + 4] = triangles[triangles_index + 2]; triangles[triangles_index + 5] = triangles[triangles_index + 1]; } } } if (mesh_main == null) { mesh_main = new Mesh(); mesh_main.vertices = new_vertices; if (Mesh.normals != null) { mesh_main.normals = new_normals; } mesh_main.triangles = triangles; if (new_boneWeights != null) { mesh_main.boneWeights = new_boneWeights; mesh_main.bindposes = Mesh.bones.bindPoses; } for (int i = 0; i < new_uvs.Length; i++) { mesh_main.SetUVs(i, new_uvs[i].ToList()); } } else { mesh_main = CopyMesh(mesh_main); } if (new_boneWeights != null) { mr_main = gao.AddComponent <SkinnedMeshRenderer>(); s_mr_main = (SkinnedMeshRenderer)mr_main; s_mr_main.bones = Mesh.bones.bones; s_mr_main.rootBone = Mesh.bones.bones[0]; s_mr_main.sharedMesh = CopyMesh(mesh_main); BoxCollider bc = gao.AddComponent <BoxCollider>(); bc.center = s_mr_main.bounds.center; bc.size = s_mr_main.bounds.size; } else { MeshFilter mf = gao.AddComponent <MeshFilter>(); mf.sharedMesh = mesh_main; mr_main = gao.AddComponent <MeshRenderer>(); MeshCollider mc = gao.AddComponent <MeshCollider>(); mc.isTrigger = false; mc.sharedMesh = mesh_main; } } if (num_disconnected_triangles_spe > 0) { Vector3[] new_vertices_spe = new Vector3[num_disconnected_triangles_spe * 3]; Vector3[] new_normals_spe = new Vector3[num_disconnected_triangles_spe * 3]; Vector3[][] new_uvs_spe = new Vector3[num_textures][]; BoneWeight[] new_boneWeights_spe = Mesh.bones != null ? new BoneWeight[num_disconnected_triangles_spe * 3] : null; for (int um = 0; um < num_textures; um++) { new_uvs_spe[um] = new Vector3[num_disconnected_triangles_spe * 3]; } int[] triangles_spe = new int[num_disconnected_triangles_spe * triangle_size]; triangles_index = 0; for (int um = 0; um < num_textures; um++) { for (int j = 0; j < num_disconnected_triangles_spe * 3; j++) { uint uvMap = (uint)visualMaterial.textures[um].uvFunction % num_uvMaps; if (uvs != null) { new_uvs_spe[um][j] = uvs[mapping_uvs_spe[uvMap][j]]; } new_uvs_spe[um][j].z = 1; /*int i0 = reader.ReadInt16(), m0 = (j * 3) + 0; // Old index, mapped index * int i1 = reader.ReadInt16(), m1 = (j * 3) + 1; * int i2 = reader.ReadInt16(), m2 = (j * 3) + 2; * new_uvs_spe[um][m0] = uvs[i0]; * new_uvs_spe[um][m1] = uvs[i1]; * new_uvs_spe[um][m2] = uvs[i2];*/ } } //print("Loading disconnected triangles at " + String.Format("0x{0:X}", fs.Position)); for (int j = 0; j < num_disconnected_triangles_spe; j++, triangles_index += triangle_size) { int i0 = disconnected_triangles_spe[(j * 3) + 0], m0 = (j * 3) + 0; // Old index, mapped index int i1 = disconnected_triangles_spe[(j * 3) + 1], m1 = (j * 3) + 1; int i2 = disconnected_triangles_spe[(j * 3) + 2], m2 = (j * 3) + 2; new_vertices_spe[m0] = Mesh.vertices[i0]; new_vertices_spe[m1] = Mesh.vertices[i1]; new_vertices_spe[m2] = Mesh.vertices[i2]; if (Mesh.normals != null) { new_normals_spe[m0] = Mesh.normals[i0]; new_normals_spe[m1] = Mesh.normals[i1]; new_normals_spe[m2] = Mesh.normals[i2]; } if (new_boneWeights_spe != null) { new_boneWeights_spe[m0] = Mesh.bones.weights[i0]; new_boneWeights_spe[m1] = Mesh.bones.weights[i1]; new_boneWeights_spe[m2] = Mesh.bones.weights[i2]; } if (Mesh.blendWeights != null) { for (int um = 0; um < num_textures; um++) { if (Mesh.blendWeights[visualMaterial.textures[um].blendIndex] != null) { if (um == 0) { materialHints |= VisualMaterial.Hint.Transparent; } new_uvs_spe[um][m0].z = Mesh.blendWeights[visualMaterial.textures[um].blendIndex][i0]; new_uvs_spe[um][m1].z = Mesh.blendWeights[visualMaterial.textures[um].blendIndex][i1]; new_uvs_spe[um][m2].z = Mesh.blendWeights[visualMaterial.textures[um].blendIndex][i2]; } } } triangles_spe[triangles_index + 0] = m0; triangles_spe[triangles_index + 1] = m2; triangles_spe[triangles_index + 2] = m1; if (!backfaceCulling) { triangles_spe[triangles_index + 3] = triangles_spe[triangles_index + 0]; triangles_spe[triangles_index + 4] = triangles_spe[triangles_index + 2]; triangles_spe[triangles_index + 5] = triangles_spe[triangles_index + 1]; } } //if (mr_main == null) { GameObject gao_spe = (mr_main == null ? gao : new GameObject("[SPE]")); if (gao_spe != gao) { gao_spe.transform.SetParent(gao.transform); } else { gao.name = "[SPE] " + gao.name; } if (mesh_spe == null) { mesh_spe = new Mesh(); mesh_spe.vertices = new_vertices_spe; mesh_spe.normals = new_normals_spe; mesh_spe.triangles = triangles_spe; if (new_boneWeights_spe != null) { mesh_spe.boneWeights = new_boneWeights_spe; mesh_spe.bindposes = Mesh.bones.bindPoses; } for (int i = 0; i < num_textures; i++) { mesh_spe.SetUVs(i, new_uvs_spe[i].ToList()); } } else { mesh_spe = CopyMesh(mesh_spe); } //mesh.SetUVs(0, new_uvs_spe.ToList()); /*mesh.uv = new_uvs_spe;*/ if (new_boneWeights_spe != null) { mr_spe = gao_spe.AddComponent <SkinnedMeshRenderer>(); s_mr_spe = (SkinnedMeshRenderer)mr_spe; s_mr_spe.bones = Mesh.bones.bones; s_mr_spe.rootBone = Mesh.bones.bones[0]; s_mr_spe.sharedMesh = CopyMesh(mesh_spe); BoxCollider bc = gao_spe.AddComponent <BoxCollider>(); bc.center = s_mr_spe.bounds.center; bc.size = s_mr_spe.bounds.size; } else { MeshFilter mf = gao_spe.AddComponent <MeshFilter>(); mf.sharedMesh = mesh_spe; mr_spe = gao_spe.AddComponent <MeshRenderer>(); MeshCollider mc = gao_spe.AddComponent <MeshCollider>(); mc.isTrigger = false; mc.sharedMesh = mesh_spe; } //} } if (visualMaterial != null) { //gao.name += " " + visualMaterial.offset + " - " + (visualMaterial.textures.Count > 0 ? visualMaterial.textures[0].offset.ToString() : "NULL" ); Material unityMat = visualMaterial.GetMaterial(materialHints); if (vertexColors != null & unityMat != null) { unityMat.SetVector("_Tex2Params", new Vector4(60, 0, 0, 0)); } bool receiveShadows = (visualMaterial.properties & VisualMaterial.property_receiveShadows) != 0; bool scroll = visualMaterial.ScrollingEnabled; /*if (num_uvMaps > 1) { * unityMat.SetFloat("_UVSec", 1f); * } else if (scroll) { * for (int i = num_uvMaps; i < visualMaterial.textures.Count; i++) { * if (visualMaterial.textures[i].ScrollingEnabled) { * unityMat.SetFloat("_UVSec", 1f); * break; * } * } * }*/ //if (r3mat.Material.GetColor("_EmissionColor") != Color.black) print("Mesh with emission: " + name); if (mr_main != null) { mr_main.sharedMaterial = unityMat; //mr_main.UpdateGIMaterials(); if (!receiveShadows) { mr_main.receiveShadows = false; } if (visualMaterial.animTextures.Count > 0) { MultiTextureMaterial mtmat = mr_main.gameObject.AddComponent <MultiTextureMaterial>(); mtmat.visMat = visualMaterial; mtmat.mat = mr_main.sharedMaterial; } /*if (scroll) { * ScrollingTexture scrollComponent = mr_main.gameObject.AddComponent<ScrollingTexture>(); * scrollComponent.visMat = visualMaterial; * scrollComponent.mat = mr_main.material; * }*/ } if (mr_spe != null) { mr_spe.sharedMaterial = unityMat; //mr_spe.UpdateGIMaterials(); if (!receiveShadows) { mr_spe.receiveShadows = false; } if (visualMaterial.animTextures.Count > 0) { MultiTextureMaterial mtmat = mr_spe.gameObject.AddComponent <MultiTextureMaterial>(); mtmat.visMat = visualMaterial; mtmat.mat = mr_spe.sharedMaterial; } /*if (scroll) { * ScrollingTexture scrollComponent = mr_spe.gameObject.AddComponent<ScrollingTexture>(); * scrollComponent.visMat = visualMaterial; * scrollComponent.mat = mr_spe.material; * }*/ } } }
void UpdateAnimations() { if (cont.LoadState == Controller.State.Finished) { /*if(MapLoader.Loader.visualMaterials != null) { * for (int i = 0; i < MapLoader.Loader.visualMaterials.Count; i++) { * VisualMaterial vm = MapLoader.Loader.visualMaterials[i]; * if (vm.animTextures.Count > 0 && !vm.IsLockedAnimatedTexture) { * vm.currentAnimTexture %= vm.animTextures.Count; * vm.animTextures[vm.currentAnimTexture].currentTime += updateCounter * modifier; * while (vm.animTextures[vm.currentAnimTexture].currentTime > vm.animTextures[vm.currentAnimTexture].time) { * float rest = vm.animTextures[vm.currentAnimTexture].currentTime - vm.animTextures[vm.currentAnimTexture].time; * vm.animTextures[vm.currentAnimTexture].currentTime = 0; * if (vm.animTextures[vm.currentAnimTexture].time <= 0) break; * vm.currentAnimTexture = (vm.currentAnimTexture + 1) % vm.animTextures.Count; * vm.animTextures[vm.currentAnimTexture].currentTime = rest; * } * } * } * }*/ for (int i = 0; i < materials.Count; i++) { MultiTextureMaterial mtm = materials[i]; if (mtm != null) { if (mtm.visMat != null) { VisualMaterial vm = mtm.visMat; if (vm.animTextures.Count > 0 && !vm.IsLockedAnimatedTexture) { vm.currentAnimTexture %= vm.animTextures.Count; vm.animTextures[vm.currentAnimTexture].currentTime += updateCounter * modifier; float time = vm.animTextures[vm.currentAnimTexture].time; if (!UnitySettings.IsRaymapGame && time <= 0) { time = defaultTime; } while (vm.animTextures[vm.currentAnimTexture].currentTime > time) { time = vm.animTextures[vm.currentAnimTexture].time; if (!UnitySettings.IsRaymapGame && time <= 0) { time = defaultTime; } float rest = vm.animTextures[vm.currentAnimTexture].currentTime - time; vm.animTextures[vm.currentAnimTexture].currentTime = 0; if (time <= 0) { break; } vm.currentAnimTexture = (vm.currentAnimTexture + 1) % vm.animTextures.Count; vm.animTextures[vm.currentAnimTexture].currentTime = rest; } } } else if (mtm.visMatROM != null) { OpenSpace.ROM.VisualMaterial vm = mtm.visMatROM; if (vm.num_textures > 0) // && !vm.IsLockedAnimatedTexture) { { mtm.CurrentTextureROM %= vm.num_textures; mtm.CurrentTextureROMTime += updateCounter * modifier; float animTime = vm.textures.Value.vmTex[mtm.CurrentTextureROM].time / 30f; while (mtm.CurrentTextureROMTime > animTime) { float rest = mtm.CurrentTextureROMTime - animTime; //mtm.CurrentTextureROMTime = 0; if (animTime <= 0) { break; } mtm.CurrentTextureROM = (mtm.CurrentTextureROM + 1) % vm.num_textures; mtm.CurrentTextureROMTime = rest; animTime = vm.textures.Value.vmTex[mtm.CurrentTextureROM].time / 30f; } } } } } materials.RemoveAll(m => m == null || m.gameObject == null); } }
public void Register(MultiTextureMaterial mat) { materials.Add(mat); }
private void CreateUnityMesh() { for (uint i = 0; i < num_sprites; i++) { bool mirrorX = false; bool mirrorY = false; GameObject spr_gao = new GameObject("SpriteElement" + i); spr_gao.transform.SetParent(gao.transform); MeshFilter mf = spr_gao.AddComponent <MeshFilter>(); MeshRenderer mr = spr_gao.AddComponent <MeshRenderer>(); BoxCollider bc = spr_gao.AddComponent <BoxCollider>(); bc.size = new Vector3(0, sprites[i].info_scale.y * 2, sprites[i].info_scale.x * 2); spr_gao.layer = LayerMask.NameToLayer("Visual"); if (sprites[i].visualMaterial != null) { if (Controller.Settings.game != Settings.Game.R2Revolution && sprites[i].visualMaterial.textures != null && sprites[i].visualMaterial.textures.Count > 0) { TextureInfo mainTex = sprites[i].visualMaterial.textures[0].texture; if (mainTex != null && mainTex.IsMirrorX) { mirrorX = true; } if (mainTex != null && mainTex.IsMirrorY) { mirrorY = true; } } //Material unityMat = sprites[i].visualMaterial.MaterialBillboard; Material unityMat = sprites[i].visualMaterial.GetMaterial(VisualMaterial.Hint.Billboard); bool receiveShadows = (sprites[i].visualMaterial.properties & VisualMaterial.property_receiveShadows) != 0; //if (num_uvMaps > 1) unityMat.SetFloat("_UVSec", 50f); //if (r3mat.Material.GetColor("_EmissionColor") != Color.black) print("Mesh with emission: " + name); mr.sharedMaterial = unityMat; /*mr.material.SetFloat("_ScaleX", sprites[i].info_scale.x); * mr.material.SetFloat("_ScaleY", sprites[i].info_scale.y);*/ if (!receiveShadows) { mr.receiveShadows = false; } if (sprites[i].visualMaterial.animTextures.Count > 0) { MultiTextureMaterial mtmat = mr.gameObject.AddComponent <MultiTextureMaterial>(); mtmat.visMat = sprites[i].visualMaterial; mtmat.mat = mr.sharedMaterial; } } else { Material transMat = new Material(Controller.VisualMaterialManager.baseTransparentMaterial); Texture2D tex = new Texture2D(1, 1); tex.SetPixel(0, 0, new Color(0, 0, 0, 0)); transMat.SetTexture("_Tex0", tex); mr.sharedMaterial = transMat; } if (sprites[i].meshUnity == null) { sprites[i].meshUnity = new Mesh(); Vector3[] vertices = new Vector3[4]; vertices[0] = new Vector3(0, -sprites[i].info_scale.y, -sprites[i].info_scale.x); vertices[1] = new Vector3(0, -sprites[i].info_scale.y, sprites[i].info_scale.x); vertices[2] = new Vector3(0, sprites[i].info_scale.y, -sprites[i].info_scale.x); vertices[3] = new Vector3(0, sprites[i].info_scale.y, sprites[i].info_scale.x); Vector3[] normals = new Vector3[4]; normals[0] = Vector3.forward; normals[1] = Vector3.forward; normals[2] = Vector3.forward; normals[3] = Vector3.forward; Vector3[] uvs = new Vector3[4]; uvs[0] = new Vector3(0, 0 - (mirrorY ? 1 : 0), 1); uvs[1] = new Vector3(1 + (mirrorX ? 1 : 0), 0 - (mirrorY ? 1 : 0), 1); uvs[2] = new Vector3(0, 1, 1); uvs[3] = new Vector3(1 + (mirrorX ? 1 : 0), 1, 1); int[] triangles = new int[] { 0, 2, 1, 1, 2, 3 }; sprites[i].meshUnity.vertices = vertices; sprites[i].meshUnity.normals = normals; sprites[i].meshUnity.triangles = triangles; sprites[i].meshUnity.SetUVs(0, uvs.ToList()); } mf.sharedMesh = sprites[i].meshUnity; } }
public Material GetMaterial(Hint hints, GameObject gao = null) { Material mat; bool billboard = (hints & Hint.Billboard) == Hint.Billboard; if (textures.Value != null && num_textures > 0) { TextureInfo texInfo = textures.Value.vmTex[0].texRef.Value.texInfo; if (texInfo.RenderTransparent || texInfo.RenderWater1 || texInfo.RenderWater2) { if (texInfo.AlphaIsTransparency || texInfo.RenderWater1 || texInfo.RenderWater2) { mat = new Material(MapLoader.Loader.baseTransparentMaterial); } else { mat = new Material(MapLoader.Loader.baseLightMaterial); } } else { mat = new Material(MapLoader.Loader.baseMaterial); } mat.SetInt("_NumTextures", 1); string textureName = "_Tex0"; mat.SetTexture(textureName, textures.Value.vmTex[0].texRef.Value.texInfo.Value.Texture); mat.SetVector(textureName + "Params", new Vector4(0, (scrollSpeedX != 0 || scrollSpeedY != 0) ? 1f : 0f, 0f, 0f)); mat.SetVector(textureName + "Params2", new Vector4( 0f, 0f, ScrollX, ScrollY)); } else { mat = new Material(MapLoader.Loader.baseMaterial); } Vector4 ambient, diffuse; if (Settings.s.platform == Settings.Platform.N64) { ambient = new Vector4(0.25f, 0.25f, 0.25f, 1f); diffuse = new Vector4(r / 255f, g / 255f, b / 255f, a / 255f); } else { ambient = ParseColorRGBA5551(ambientCoef) + new Vector4(0.25f, 0.25f, 0.25f, 1f); diffuse = ParseColorRGBA5551(diffuseCoef) + new Vector4(0, 0, 0, 1f); } mat.SetVector("_AmbientCoef", ambient); mat.SetVector("_DiffuseCoef", diffuse); if (billboard) { mat.SetFloat("_Billboard", 1f); } if (gao != null && num_textures > 1) { MultiTextureMaterial mtmat = gao.AddComponent <MultiTextureMaterial>(); mtmat.visMatROM = this; mtmat.mat = mat; } return(mat); }
private void CreateUnityMesh() { /*if (mesh.bones != null) { * for (int j = 0; j < mesh.bones.num_bones; j++) { * Transform b = mesh.bones.bones[j]; * b.transform.SetParent(gao.transform); * mesh.bones.bindPoses[j] = mesh.bones.bones[j].worldToLocalMatrix * gao.transform.localToWorldMatrix; * } * }*/ Renderer mr_main = null, mr_spe = null; long num_triangles_main = ((num_connected_vertices > 2 ? num_connected_vertices - 2 : 0) + num_disconnected_triangles) * (backfaceCulling ? 1 : 2); uint triangle_size = 3 * (uint)(backfaceCulling ? 1 : 2); uint triangles_index = 0; if (num_triangles_main > 0) { Vector3[] new_vertices = new Vector3[num_mapping_entries]; Vector3[] new_normals = new Vector3[num_mapping_entries]; Vector3[][] new_uvs = new Vector3[num_uvMaps][]; // Thanks to Unity we can only store the blend weights as a third component of the UVs BoneWeight[] new_boneWeights = mesh.bones != null ? new BoneWeight[num_mapping_entries] : null; for (int um = 0; um < num_uvMaps; um++) { new_uvs[um] = new Vector3[num_mapping_entries]; } for (int j = 0; j < num_mapping_entries; j++) { new_vertices[j] = mesh.vertices[mapping_vertices[j]]; new_normals[j] = mesh.normals[mapping_vertices[j]]; if (new_boneWeights != null) { new_boneWeights[j] = mesh.bones.weights[mapping_vertices[j]]; } for (int um = 0; um < num_uvMaps; um++) { new_uvs[um][j] = uvs[mapping_uvs[um][j]]; if (mesh.blendWeights != null) { new_uvs[um][j].z = mesh.blendWeights[mapping_vertices[j]]; } } } int[] triangles = new int[num_triangles_main * triangle_size]; if (num_connected_vertices > 2) { for (int j = 0; j < num_connected_vertices - 2; j++, triangles_index += triangle_size) { if (j % 2 == 0) { triangles[triangles_index + 0] = connected_vertices[j + 0]; triangles[triangles_index + 1] = connected_vertices[j + 2]; triangles[triangles_index + 2] = connected_vertices[j + 1]; } else { triangles[triangles_index + 0] = connected_vertices[j + 0]; triangles[triangles_index + 1] = connected_vertices[j + 1]; triangles[triangles_index + 2] = connected_vertices[j + 2]; } if (!backfaceCulling) { triangles[triangles_index + 3] = triangles[triangles_index + 0]; triangles[triangles_index + 4] = triangles[triangles_index + 2]; triangles[triangles_index + 5] = triangles[triangles_index + 1]; } } } if (num_connected_vertices < 2) { num_connected_vertices = 0; } if (num_disconnected_triangles > 0) { //print("Loading disconnected triangles at " + String.Format("0x{0:X}", fs.Position)); for (int j = 0; j < num_disconnected_triangles; j++, triangles_index += triangle_size) { triangles[triangles_index + 0] = disconnected_triangles[(j * 3) + 0]; triangles[triangles_index + 2] = disconnected_triangles[(j * 3) + 1]; triangles[triangles_index + 1] = disconnected_triangles[(j * 3) + 2]; if (!backfaceCulling) { triangles[triangles_index + 3] = triangles[triangles_index + 0]; triangles[triangles_index + 4] = triangles[triangles_index + 2]; triangles[triangles_index + 5] = triangles[triangles_index + 1]; } } } mesh_main = new Mesh(); mesh_main.vertices = new_vertices; mesh_main.normals = new_normals; mesh_main.triangles = triangles; if (new_boneWeights != null) { mesh_main.boneWeights = new_boneWeights; mesh_main.bindposes = mesh.bones.bindPoses; } for (int i = 0; i < num_uvMaps; i++) { mesh_main.SetUVs(i, new_uvs[i].ToList()); } if (new_boneWeights != null) { mr_main = gao.AddComponent <SkinnedMeshRenderer>(); s_mr_main = (SkinnedMeshRenderer)mr_main; s_mr_main.bones = mesh.bones.bones; s_mr_main.rootBone = mesh.bones.bones[0]; s_mr_main.sharedMesh = CopyMesh(mesh_main); } else { MeshFilter mf = gao.AddComponent <MeshFilter>(); mf.mesh = mesh_main; mr_main = gao.AddComponent <MeshRenderer>(); } } if (num_disconnected_triangles_spe > 0) { Vector3[] new_vertices_spe = new Vector3[num_disconnected_triangles_spe * 3]; Vector3[] new_normals_spe = new Vector3[num_disconnected_triangles_spe * 3]; Vector3[][] new_uvs_spe = new Vector3[num_uvMaps][]; BoneWeight[] new_boneWeights_spe = mesh.bones != null ? new BoneWeight[num_disconnected_triangles_spe * 3] : null; for (int um = 0; um < num_uvMaps; um++) { new_uvs_spe[um] = new Vector3[num_disconnected_triangles_spe * 3]; } int[] triangles_spe = new int[num_disconnected_triangles_spe * triangle_size]; triangles_index = 0; for (int um = 0; um < num_uvMaps; um++) { for (int j = 0; j < num_disconnected_triangles_spe * 3; j++) { new_uvs_spe[um][j] = uvs[mapping_uvs_spe[um][j]]; /*int i0 = reader.ReadInt16(), m0 = (j * 3) + 0; // Old index, mapped index * int i1 = reader.ReadInt16(), m1 = (j * 3) + 1; * int i2 = reader.ReadInt16(), m2 = (j * 3) + 2; * new_uvs_spe[um][m0] = uvs[i0]; * new_uvs_spe[um][m1] = uvs[i1]; * new_uvs_spe[um][m2] = uvs[i2];*/ } } //print("Loading disconnected triangles at " + String.Format("0x{0:X}", fs.Position)); for (int j = 0; j < num_disconnected_triangles_spe; j++, triangles_index += triangle_size) { int i0 = disconnected_triangles_spe[(j * 3) + 0], m0 = (j * 3) + 0; // Old index, mapped index int i1 = disconnected_triangles_spe[(j * 3) + 1], m1 = (j * 3) + 1; int i2 = disconnected_triangles_spe[(j * 3) + 2], m2 = (j * 3) + 2; new_vertices_spe[m0] = mesh.vertices[i0]; new_vertices_spe[m1] = mesh.vertices[i1]; new_vertices_spe[m2] = mesh.vertices[i2]; new_normals_spe[m0] = mesh.normals[i0]; new_normals_spe[m1] = mesh.normals[i1]; new_normals_spe[m2] = mesh.normals[i2]; if (new_boneWeights_spe != null) { new_boneWeights_spe[m0] = mesh.bones.weights[i0]; new_boneWeights_spe[m1] = mesh.bones.weights[i1]; new_boneWeights_spe[m2] = mesh.bones.weights[i2]; } if (mesh.blendWeights != null) { for (int um = 0; um < num_uvMaps; um++) { new_uvs_spe[um][m0].z = mesh.blendWeights[i0]; new_uvs_spe[um][m1].z = mesh.blendWeights[i1]; new_uvs_spe[um][m2].z = mesh.blendWeights[i2]; } } triangles_spe[triangles_index + 0] = m0; triangles_spe[triangles_index + 1] = m2; triangles_spe[triangles_index + 2] = m1; if (!backfaceCulling) { triangles_spe[triangles_index + 3] = triangles_spe[triangles_index + 0]; triangles_spe[triangles_index + 4] = triangles_spe[triangles_index + 2]; triangles_spe[triangles_index + 5] = triangles_spe[triangles_index + 1]; } } //if (mr_main == null) { GameObject gao_spe = (mr_main == null ? gao : new GameObject("[SPE] " + name)); if (gao_spe != gao) { gao_spe.transform.SetParent(gao.transform); } else { gao.name = "[SPE] " + gao.name; } mesh_spe = new Mesh(); mesh_spe.vertices = new_vertices_spe; mesh_spe.normals = new_normals_spe; mesh_spe.triangles = triangles_spe; if (new_boneWeights_spe != null) { mesh_spe.boneWeights = new_boneWeights_spe; mesh_spe.bindposes = mesh.bones.bindPoses; } for (int i = 0; i < num_uvMaps; i++) { mesh_spe.SetUVs(i, new_uvs_spe[i].ToList()); } //mesh.SetUVs(0, new_uvs_spe.ToList()); /*mesh.uv = new_uvs_spe;*/ if (new_boneWeights_spe != null) { mr_spe = gao_spe.AddComponent <SkinnedMeshRenderer>(); s_mr_spe = (SkinnedMeshRenderer)mr_spe; s_mr_spe.bones = mesh.bones.bones; s_mr_spe.rootBone = mesh.bones.bones[0]; s_mr_spe.sharedMesh = CopyMesh(mesh_spe); } else { MeshFilter mf = gao_spe.AddComponent <MeshFilter>(); mf.mesh = mesh_spe; mr_spe = gao_spe.AddComponent <MeshRenderer>(); } //} } if (r3mat != null) { Material unityMat = r3mat.Material; bool receiveShadows = (r3mat.properties & VisualMaterial.property_receiveShadows) != 0; if (num_uvMaps > 1) { unityMat.SetFloat("_UVSec", 50f); } //if (r3mat.Material.GetColor("_EmissionColor") != Color.black) print("Mesh with emission: " + name); if (mr_main != null) { mr_main.material = unityMat; //mr_main.UpdateGIMaterials(); if (!receiveShadows) { mr_main.receiveShadows = false; } if (r3mat.off_animTextures.Count > 0) { MultiTextureMaterial mtmat = mr_main.gameObject.AddComponent <MultiTextureMaterial>(); mtmat.r3mat = r3mat; mtmat.mat = mr_main.material; } } if (mr_spe != null) { mr_spe.material = unityMat; //mr_spe.UpdateGIMaterials(); if (!receiveShadows) { mr_spe.receiveShadows = false; } if (r3mat.off_animTextures.Count > 0) { MultiTextureMaterial mtmat = mr_spe.gameObject.AddComponent <MultiTextureMaterial>(); mtmat.r3mat = r3mat; mtmat.mat = mr_spe.material; } } } }
private void CreateUnityMesh() { /*if (mesh.bones != null) { * for (int j = 0; j < mesh.bones.num_bones; j++) { * Transform b = mesh.bones.bones[j]; * b.transform.SetParent(gao.transform); * mesh.bones.bindPoses[j] = mesh.bones.bones[j].worldToLocalMatrix * gao.transform.localToWorldMatrix; * } * }*/ VisualMaterial.Hint materialHints = geo.lookAtMode != 0 ? VisualMaterial.Hint.Billboard : VisualMaterial.Hint.None; //VisualMaterial.Hint materialHints = VisualMaterial.Hint.None; uint num_textures = 0; if (visualMaterial != null) { num_textures = visualMaterial.num_textures; } uint triangle_size = 3 * (uint)(backfaceCulling ? 1 : 2); // Create mesh from unoptimized data if (num_triangles > 0) { uint triangles_index = 0; Vector3[] new_vertices = new Vector3[num_triangles * 3]; Vector3[] new_normals = new Vector3[num_triangles * 3]; Vector3[][] new_uvs = new Vector3[num_textures][]; BoneWeight[] new_boneWeights = geo.bones != null ? new BoneWeight[num_triangles * 3] : null; for (int um = 0; um < num_textures; um++) { new_uvs[um] = new Vector3[num_triangles * 3]; } int[] unityTriangles = new int[num_triangles * triangle_size]; triangles_index = 0; for (int um = 0; um < num_textures; um++) { for (int j = 0; j < num_triangles * 3; j++) { uint uvMap = (uint)visualMaterial.textures[um].uvFunction % num_uvMaps; if (uvs != null) { new_uvs[um][j] = uvs[mapping_uvs[uvMap][j] % uvs.Length]; // modulo because R2 iOS has some corrupt uvs if (MapLoader.Loader.blockyMode && normals != null) { new_uvs[um][j] = uvs[mapping_uvs[uvMap][j - (j % 3)]]; } } new_uvs[um][j].z = 1; /*int i0 = reader.ReadInt16(), m0 = (j * 3) + 0; // Old index, mapped index * int i1 = reader.ReadInt16(), m1 = (j * 3) + 1; * int i2 = reader.ReadInt16(), m2 = (j * 3) + 2; * new_uvs_spe[um][m0] = uvs[i0]; * new_uvs_spe[um][m1] = uvs[i1]; * new_uvs_spe[um][m2] = uvs[i2];*/ } } //print("Loading disconnected triangles at " + String.Format("0x{0:X}", fs.Position)); for (int j = 0; j < num_triangles; j++, triangles_index += triangle_size) { int i0 = triangles[(j * 3) + 0], m0 = (j * 3) + 0; // Old index, mapped index int i1 = triangles[(j * 3) + 1], m1 = (j * 3) + 1; int i2 = triangles[(j * 3) + 2], m2 = (j * 3) + 2; if (i1 > geo.vertices.Length) { MapLoader.Loader.print(geo.vertices.Length); } new_vertices[m0] = geo.vertices[i0]; new_vertices[m1] = geo.vertices[i1]; new_vertices[m2] = geo.vertices[i2]; if (geo.normals != null) { new_normals[m0] = geo.normals[i0]; new_normals[m1] = geo.normals[i1]; new_normals[m2] = geo.normals[i2]; } if (MapLoader.Loader.blockyMode && normals != null) { new_normals[m0] = normals[j]; new_normals[m1] = normals[j]; new_normals[m2] = normals[j]; } if (new_boneWeights != null) { new_boneWeights[m0] = geo.bones.weights[i0]; new_boneWeights[m1] = geo.bones.weights[i1]; new_boneWeights[m2] = geo.bones.weights[i2]; } if (geo.blendWeights != null) { for (int um = 0; um < num_textures; um++) { if (geo.blendWeights[visualMaterial.textures[um].blendIndex] != null) { if (um == 0) { materialHints |= VisualMaterial.Hint.Transparent; } new_uvs[um][m0].z = geo.blendWeights[visualMaterial.textures[um].blendIndex][i0]; new_uvs[um][m1].z = geo.blendWeights[visualMaterial.textures[um].blendIndex][i1]; new_uvs[um][m2].z = geo.blendWeights[visualMaterial.textures[um].blendIndex][i2]; } } } unityTriangles[triangles_index + 0] = m0; unityTriangles[triangles_index + 1] = m2; unityTriangles[triangles_index + 2] = m1; if (!backfaceCulling) { unityTriangles[triangles_index + 3] = unityTriangles[triangles_index + 0]; unityTriangles[triangles_index + 4] = unityTriangles[triangles_index + 2]; unityTriangles[triangles_index + 5] = unityTriangles[triangles_index + 1]; } } if (unityMesh == null) { unityMesh = new Mesh(); unityMesh.vertices = new_vertices; unityMesh.normals = new_normals; unityMesh.triangles = unityTriangles; if (new_boneWeights != null) { unityMesh.boneWeights = new_boneWeights; unityMesh.bindposes = geo.bones.bindPoses; } for (int i = 0; i < num_textures; i++) { unityMesh.SetUVs(i, new_uvs[i].ToList()); } } else { unityMesh = CopyMesh(unityMesh); } //mesh.SetUVs(0, new_uvs_spe.ToList()); /*mesh.uv = new_uvs_spe;*/ if (new_boneWeights != null) { mr = gao.AddComponent <SkinnedMeshRenderer>(); s_mr = (SkinnedMeshRenderer)mr; s_mr.bones = geo.bones.bones; s_mr.rootBone = geo.bones.bones[0]; s_mr.sharedMesh = CopyMesh(unityMesh); BoxCollider bc = gao.AddComponent <BoxCollider>(); bc.center = s_mr.bounds.center; bc.size = s_mr.bounds.size; } else { MeshFilter mf = gao.AddComponent <MeshFilter>(); mf.sharedMesh = unityMesh; mr = gao.AddComponent <MeshRenderer>(); MeshCollider mc = gao.AddComponent <MeshCollider>(); mc.isTrigger = false; mc.sharedMesh = unityMesh; } //} } // Create mesh from optimized data long OPT_num_triangles_total = ((OPT_num_triangleStrip > 2 ? OPT_num_triangleStrip - 2 : 0) + OPT_num_disconnectedTriangles) * (backfaceCulling ? 1 : 2); if (OPT_num_triangles_total > 0 && num_triangles <= 0) { uint triangles_index = 0; Vector3[] new_vertices = new Vector3[OPT_num_mapping_entries]; Vector3[] new_normals = new Vector3[OPT_num_mapping_entries]; Vector4[][] new_uvs = new Vector4[num_textures + (vertexColors != null ? 1 : 0)][]; // Thanks to Unity we can only store the blend weights as a third component of the UVs BoneWeight[] new_boneWeights = geo.bones != null ? new BoneWeight[OPT_num_mapping_entries] : null; for (int um = 0; um < num_textures; um++) { new_uvs[um] = new Vector4[OPT_num_mapping_entries]; } if (vertexColors != null) { new_uvs[num_textures] = new Vector4[OPT_num_mapping_entries]; for (int i = 0; i < OPT_num_mapping_entries; i++) { new_uvs[num_textures][i] = new Vector4(vertexColors[i].r, vertexColors[i].g, vertexColors[i].b, vertexColors[i].a); } } for (int j = 0; j < OPT_num_mapping_entries; j++) { new_vertices[j] = geo.vertices[OPT_mapping_vertices[j]]; if (geo.normals != null) { new_normals[j] = geo.normals[OPT_mapping_vertices[j]]; } if (new_boneWeights != null) { new_boneWeights[j] = geo.bones.weights[OPT_mapping_vertices[j]]; } for (int um = 0; um < num_textures; um++) { uint uvMap = (uint)visualMaterial.textures[um].uvFunction % num_uvMaps; //MapLoader.Loader.print(visualMaterial.textures[um].uvFunction + " - " + num_uvMaps); new_uvs[um][j] = uvs[OPT_mapping_uvs[uvMap][j]]; if (geo.blendWeights != null && geo.blendWeights[visualMaterial.textures[um].blendIndex] != null) { if (um == 0) { materialHints |= VisualMaterial.Hint.Transparent; } new_uvs[um][j].z = geo.blendWeights[visualMaterial.textures[um].blendIndex][OPT_mapping_vertices[j]]; } else { new_uvs[um][j].z = 1; } } } int[] unityTriangles = new int[OPT_num_triangles_total * triangle_size]; if (OPT_num_triangleStrip > 2) { for (int j = 0; j < OPT_num_triangleStrip - 2; j++, triangles_index += triangle_size) { if (j % 2 == 0) { unityTriangles[triangles_index + 0] = OPT_triangleStrip[j + 0]; unityTriangles[triangles_index + 1] = OPT_triangleStrip[j + 2]; unityTriangles[triangles_index + 2] = OPT_triangleStrip[j + 1]; } else { unityTriangles[triangles_index + 0] = OPT_triangleStrip[j + 0]; unityTriangles[triangles_index + 1] = OPT_triangleStrip[j + 1]; unityTriangles[triangles_index + 2] = OPT_triangleStrip[j + 2]; } if (!backfaceCulling) { unityTriangles[triangles_index + 3] = unityTriangles[triangles_index + 0]; unityTriangles[triangles_index + 4] = unityTriangles[triangles_index + 2]; unityTriangles[triangles_index + 5] = unityTriangles[triangles_index + 1]; } } } if (OPT_num_triangleStrip < 2) { OPT_num_triangleStrip = 0; } if (OPT_num_disconnectedTriangles > 0) { //print("Loading disconnected triangles at " + String.Format("0x{0:X}", fs.Position)); for (int j = 0; j < OPT_num_disconnectedTriangles; j++, triangles_index += triangle_size) { unityTriangles[triangles_index + 0] = OPT_disconnectedTriangles[(j * 3) + 0]; unityTriangles[triangles_index + 2] = OPT_disconnectedTriangles[(j * 3) + 1]; unityTriangles[triangles_index + 1] = OPT_disconnectedTriangles[(j * 3) + 2]; if (!backfaceCulling) { unityTriangles[triangles_index + 3] = unityTriangles[triangles_index + 0]; unityTriangles[triangles_index + 4] = unityTriangles[triangles_index + 2]; unityTriangles[triangles_index + 5] = unityTriangles[triangles_index + 1]; } } } if (OPT_unityMesh == null) { OPT_unityMesh = new Mesh(); OPT_unityMesh.vertices = new_vertices; if (geo.normals != null) { OPT_unityMesh.normals = new_normals; } OPT_unityMesh.triangles = unityTriangles; if (new_boneWeights != null) { OPT_unityMesh.boneWeights = new_boneWeights; OPT_unityMesh.bindposes = geo.bones.bindPoses; } for (int i = 0; i < new_uvs.Length; i++) { OPT_unityMesh.SetUVs(i, new_uvs[i].ToList()); } } else { OPT_unityMesh = CopyMesh(OPT_unityMesh); } GameObject OPT_gao = (OPT_mr == null ? gao : new GameObject("[Optimized] " + name)); if (OPT_gao != gao) { OPT_gao.transform.SetParent(gao.transform); } else { gao.name = "[Optimized] " + gao.name; } if (new_boneWeights != null) { OPT_mr = OPT_gao.AddComponent <SkinnedMeshRenderer>(); OPT_s_mr = (SkinnedMeshRenderer)OPT_mr; OPT_s_mr.bones = geo.bones.bones; OPT_s_mr.rootBone = geo.bones.bones[0]; OPT_s_mr.sharedMesh = CopyMesh(OPT_unityMesh); BoxCollider bc = OPT_gao.AddComponent <BoxCollider>(); bc.center = OPT_s_mr.bounds.center; bc.size = OPT_s_mr.bounds.size; } else { MeshFilter mf = OPT_gao.AddComponent <MeshFilter>(); mf.sharedMesh = OPT_unityMesh; OPT_mr = OPT_gao.AddComponent <MeshRenderer>(); MeshCollider mc = OPT_gao.AddComponent <MeshCollider>(); mc.isTrigger = false; mc.sharedMesh = OPT_unityMesh; } } if (visualMaterial != null) { //gao.name += " " + visualMaterial.offset + " - " + (visualMaterial.textures.Count > 0 ? visualMaterial.textures[0].offset.ToString() : "NULL" ); Material unityMat = visualMaterial.GetMaterial(materialHints); if (vertexColors != null & unityMat != null) { unityMat.SetVector("_Tex2Params", new Vector4(60, 0, 0, 0)); } bool receiveShadows = (visualMaterial.properties & VisualMaterial.property_receiveShadows) != 0; bool scroll = visualMaterial.ScrollingEnabled; /*if (num_uvMaps > 1) { * unityMat.SetFloat("_UVSec", 1f); * } else if (scroll) { * for (int i = num_uvMaps; i < visualMaterial.textures.Count; i++) { * if (visualMaterial.textures[i].ScrollingEnabled) { * unityMat.SetFloat("_UVSec", 1f); * break; * } * } * }*/ //if (r3mat.Material.GetColor("_EmissionColor") != Color.black) print("Mesh with emission: " + name); if (OPT_mr != null) { OPT_mr.sharedMaterial = unityMat; //mr_main.UpdateGIMaterials(); if (!receiveShadows) { OPT_mr.receiveShadows = false; } if (visualMaterial.animTextures.Count > 0) { MultiTextureMaterial mtmat = OPT_mr.gameObject.AddComponent <MultiTextureMaterial>(); mtmat.visMat = visualMaterial; mtmat.mat = OPT_mr.material; } /*if (scroll) { * ScrollingTexture scrollComponent = mr_main.gameObject.AddComponent<ScrollingTexture>(); * scrollComponent.visMat = visualMaterial; * scrollComponent.mat = mr_main.material; * }*/ } if (mr != null) { mr.sharedMaterial = unityMat; //mr_spe.UpdateGIMaterials(); if (!receiveShadows) { mr.receiveShadows = false; } if (visualMaterial.animTextures.Count > 0) { MultiTextureMaterial mtmat = mr.gameObject.AddComponent <MultiTextureMaterial>(); mtmat.visMat = visualMaterial; mtmat.mat = mr.material; } /*if (scroll) { * ScrollingTexture scrollComponent = mr_spe.gameObject.AddComponent<ScrollingTexture>(); * scrollComponent.visMat = visualMaterial; * scrollComponent.mat = mr_spe.material; * }*/ } } }