/* * ------------- * Big ol parser code. * Maybe I should split it out? Probably not worth the effort * Translated from the original MaxScript import * -------------- */ public static AMF ParseAMF(string path) { AMF amf = new AMF(); using (BinaryReader reader = new BinaryReader(File.Open(path, FileMode.Open))) { Debug.Log("File length:" + reader.BaseStream.Length); readHeader(reader, amf); Debug.Log(amf.header + " " + amf.version + " " + amf.modelName); //tvRegions.Nodes.Clear() EditorUtility.DisplayProgressBar("Parsing " + path, "[0/5] Parsing nodes...", 0); readNodes(reader, amf); EditorUtility.DisplayProgressBar("Parsing " + path, "[1/5] Parsing Markers...", (1f / 5f)); readMarkers(reader, amf); EditorUtility.DisplayProgressBar("Parsing " + path, "[2/5] Parsing Regions...", (2f / 5f)); readRegions(reader, amf); EditorUtility.DisplayProgressBar("Parsing " + path, "[3/5] Parsing Shaders...", (3f / 5f)); readShaders(reader, amf); //loadRegions(tvRegions) } return(amf); }
public void AMF_EncodeNamedNumberTest() { AVal name = AVal.AVC("name"); double val = -2.3456; // 0xC0 02 C3 C9 EE CB FB 16 byte[] buf = new byte[100]; int enc = 0, pend = buf.Length; int len = 2 + 4 + 1 + 8; // "name".len + "name" + AMF_NUMBER + 8 enc = AMF.AMF_EncodeNamedNumber(buf, enc, pend, name, val); Assert.AreEqual(len, enc); Assert.AreEqual(0x00, buf[0]); Assert.AreEqual(0x04, buf[1]); Assert.AreEqual('n', buf[2]); Assert.AreEqual('a', buf[3]); Assert.AreEqual('m', buf[4]); Assert.AreEqual('e', buf[5]); Assert.AreEqual((byte)AMFDataType.AMF_NUMBER, buf[6]); Assert.AreEqual(0xC0, buf[7]); Assert.AreEqual(0x02, buf[8]); Assert.AreEqual(0xC3, buf[9]); Assert.AreEqual(0xC9, buf[10]); Assert.AreEqual(0xEE, buf[11]); Assert.AreEqual(0xCB, buf[12]); Assert.AreEqual(0xFB, buf[13]); Assert.AreEqual(0x16, buf[14]); }
public void AMF_EncodeNamedStringTest2() { AVal name = AVal.AVC("name"), val = AVal.AVC("val"); byte[] buf = new byte[100]; int offset = 20; int enc = offset, pend = buf.Length; int len = 2 + 4 + 1 + 2 + 3; // "name".len + "name" + AMF_STRING + "val".len + "val" enc = AMF.AMF_EncodeNamedString(buf, enc, pend, name, val); Assert.AreEqual(len + offset, enc); Assert.AreEqual(0x00, buf[0 + offset]); Assert.AreEqual(0x04, buf[1 + offset]); Assert.AreEqual('n', buf[2 + offset]); Assert.AreEqual('a', buf[3 + offset]); Assert.AreEqual('m', buf[4 + offset]); Assert.AreEqual('e', buf[5 + offset]); Assert.AreEqual((byte)AMFDataType.AMF_STRING, buf[6 + offset]); Assert.AreEqual(0x00, buf[7 + offset]); Assert.AreEqual(0x03, buf[8 + offset]); Assert.AreEqual('v', buf[9 + offset]); Assert.AreEqual('a', buf[10 + offset]); Assert.AreEqual('l', buf[11 + offset]); Assert.AreEqual(0x00, buf[12 + offset]); }
static void readMarkers(BinaryReader reader, AMF amf, bool skip = false) { int groupCount = reader.ReadInt32(); Debug.Log("Groups Of Markers:[" + groupCount + "]"); long groupAddress = reader.ReadInt32(); long fPos = reader.BaseStream.Position; amf.markerGroups = new List <AMF_MarkerGroup>(); if (groupCount > 0 && !skip) { reader.BaseStream.Seek(groupAddress, SeekOrigin.Begin); for (int i = 0; i < groupCount; i++) { AMF_MarkerGroup amg = new AMF_MarkerGroup(); amg.name = "#" + reader.ReadCString(); long markerCount = reader.ReadInt32(); long markerAddress = reader.ReadInt32(); long cPos = reader.BaseStream.Position; amg.markers = new List <AMF_Marker>(); if (markerCount > 0) { reader.BaseStream.Seek(markerAddress, SeekOrigin.Begin); for (int j = 0; j < markerCount; j++) { amg.markers.Add(new AMF_Marker(reader)); } } amf.markerGroups.Add(amg); reader.BaseStream.Seek(cPos, SeekOrigin.Begin); } reader.BaseStream.Seek(fPos, SeekOrigin.Begin); } }
public void AMF_EncodeStringTest2() { AVal app = AVal.AVC("appp"); byte[] buf = new byte[4]; int enc = 0, pend = buf.Length; enc = AMF.AMF_EncodeString(buf, enc, pend, app); Assert.AreEqual(0, enc); }
public void AMF_DecodeInt32Test() { uint expected = 0x12345678; var buf = new byte[100]; AMF.AMF_EncodeInt32(buf, 0, buf.Length, expected); var actual = AMF.AMF_DecodeInt32(buf); Assert.AreEqual(expected, actual); }
public void memcpyTest() { var src = new byte[] { 0x01, 0x23, 0x45, 0x67, 0x89 }; var dst = new byte[src.Length]; AMF.memcpy(dst, 0, src, 3); Assert.AreEqual(src[0], dst[0]); Assert.AreEqual(src[1], dst[1]); Assert.AreEqual(src[2], dst[2]); Assert.AreEqual(0x00, dst[3]); }
public void AMF_DecodeNumberTest() { double expected = -2.3456, actual; var buf = new byte[100]; int enc = 0; var pend = buf.Length; AMF.AMF_EncodeNumber(buf, enc, pend, expected); actual = AMF.AMF_DecodeNumber(buf, 1); // skip AMFDatatype Assert.AreEqual(expected, actual); }
public void AMF_EncodeInt16Test() { short sval = 0x1234; byte[] buf = new byte[100]; int enc = 0, pend = buf.Length; enc = AMF.AMF_EncodeInt16(buf, enc, pend, (ushort)sval); Assert.AreEqual(2, enc); Assert.AreEqual(0x12, buf[0]); Assert.AreEqual(0x34, buf[1]); }
public void AMF_EncodeInt24Test() { int val = 0x123456; byte[] buf = new byte[100]; int enc = 0, pend = buf.Length; enc = AMF.AMF_EncodeInt24(buf, enc, pend, (uint)val); Assert.AreEqual(3, enc, "result"); Assert.AreEqual(0x12, buf[0], "0"); Assert.AreEqual(0x34, buf[1], "1"); Assert.AreEqual(0x56, buf[2], "2"); }
public void AMF_EncodeInt32Test() { int val = 0x12345678; byte[] buf = new byte[100]; int enc = 0, pend = buf.Length; enc = AMF.AMF_EncodeInt32(buf, enc, pend, (uint)val); Assert.AreEqual(4, enc); Assert.AreEqual(0x12, buf[0]); Assert.AreEqual(0x34, buf[1]); Assert.AreEqual(0x56, buf[2]); Assert.AreEqual(0x78, buf[3]); }
public void AMF_EncodeStringTest() { AVal app = AVal.AVC("app"); byte[] buf = new byte[50]; int output = 0, pend = buf.Length; output = AMF.AMF_EncodeString(buf, output, pend, app); Assert.AreEqual(6, output); Assert.AreEqual((byte)AMFDataType.AMF_STRING, buf[0]); Assert.AreEqual(0, buf[1]); Assert.AreEqual(3, buf[2]); Assert.AreEqual('a', buf[3]); Assert.AreEqual('p', buf[4]); Assert.AreEqual('p', buf[5]); }
public void AMF_DecodeStringTest() { var buf = new byte[100]; AVal str = AVal.AVC("foobar"); AMF.AMF_EncodeString(buf, 0, buf.Length, str); AVal actual; AMF.AMF_DecodeString(buf, 1, out actual); // Skip AMFDatatype flag Assert.AreEqual(6, actual.av_len); Assert.AreEqual('f', actual.av_val[0]); Assert.AreEqual('o', actual.av_val[1]); Assert.AreEqual('o', actual.av_val[2]); Assert.AreEqual('b', actual.av_val[3]); Assert.AreEqual('a', actual.av_val[4]); Assert.AreEqual('r', actual.av_val[5]); }
public void AMF_EncodeBooleanTest() { byte[] buf = new byte[100]; int enc = 0, pend = buf.Length; enc = AMF.AMF_EncodeBoolean(buf, enc, pend, false); Assert.AreEqual(2, enc); Assert.AreEqual((byte)AMFDataType.AMF_BOOLEAN, buf[0]); Assert.AreEqual(0x00, buf[1]); enc = 0; pend = buf.Length; enc = AMF.AMF_EncodeBoolean(buf, enc, pend, true); Assert.AreEqual(2, enc); Assert.AreEqual((byte)AMFDataType.AMF_BOOLEAN, buf[0]); Assert.AreEqual(0x01, buf[1]); }
public void AMF_EncodeNamedBooleanTest() { AVal name = AVal.AVC("name"); byte[] buf = new byte[100]; int enc = 0, pend = buf.Length; int len = 2 + 4 + 1 + 1; // "name".len + "name" + AMF_NUMBER + 8 enc = AMF.AMF_EncodeNamedBoolean(buf, enc, pend, name, true); Assert.AreEqual(len, enc); Assert.AreEqual(0x00, buf[0]); Assert.AreEqual(0x04, buf[1]); Assert.AreEqual('n', buf[2]); Assert.AreEqual('a', buf[3]); Assert.AreEqual('m', buf[4]); Assert.AreEqual('e', buf[5]); Assert.AreEqual((byte)AMFDataType.AMF_BOOLEAN, buf[6]); Assert.AreEqual(0x01, buf[7]); }
public void AMF_EncodeNumberTest() { double val = -2.3456; // 0xC0 02 C3 C9 EE CB FB 16 byte[] buf = new byte[100]; int enc = 0, pend = buf.Length; enc = AMF.AMF_EncodeNumber(buf, enc, pend, val); Assert.AreEqual(9, enc); Assert.AreEqual((byte)AMFDataType.AMF_NUMBER, buf[0]); Assert.AreEqual(0xC0, buf[1]); Assert.AreEqual(0x02, buf[2]); Assert.AreEqual(0xC3, buf[3]); Assert.AreEqual(0xC9, buf[4]); Assert.AreEqual(0xEE, buf[5]); Assert.AreEqual(0xCB, buf[6]); Assert.AreEqual(0xFB, buf[7]); Assert.AreEqual(0x16, buf[8]); }
static void readNodes(BinaryReader reader, AMF amf, bool skip = false) { int count = reader.ReadInt32(); Debug.Log("Node count:" + count); long address = (long)reader.ReadInt32(); long fPos = reader.BaseStream.Position; List <AMF_Node> nodes = new List <AMF_Node>(); if (count > 0 && !skip) { reader.BaseStream.Seek(address, SeekOrigin.Begin); for (int i = 0; i < count; i++) { nodes.Add(new AMF_Node(reader, i)); } reader.BaseStream.Seek(fPos, SeekOrigin.Begin); } amf.nodes = nodes; }
/* * * Create Bone Hierarchy */ List <Transform> CreateRigging(AMF amf) { List <Transform> bones = new List <Transform>(); //first past to instantiate references for (int i = 0; i < amf.nodes.Count; i++) { bones.Add(new GameObject(amf.nodes[i].name).transform); } //second pass to setup hierarchy for (int i = 0; i < amf.nodes.Count; i++) { if (amf.nodes[i].parentIndex > -1) { bones[i].parent = bones[amf.nodes[i].parentIndex]; Matrix4x4 flip = Matrix4x4.identity; flip.SetRow(0, new Vector4(-1, 0)); bones[i].localPosition = flip.MultiplyPoint3x4(amf.nodes[i].pos); //new Vector3(amf.nodes[i].pos.x,amf.nodes[i].pos.y,-amf.nodes[i].pos.z); bones[i].localRotation = new Quaternion(amf.nodes[i].rot.x, -amf.nodes[i].rot.y, -amf.nodes[i].rot.z, amf.nodes[i].rot.w); //amf.nodes[i].rot;// } } //third pass to reorder siblings. for (int i = 0; i < amf.nodes.Count; i++) { if (amf.nodes[i].siblingIndex > -1) { bones[i].parent.SetSiblingIndex(amf.nodes[i].siblingIndex); } } bones.Insert(0, new GameObject("Root").transform); bones[1].parent = bones[0]; bones[0].localScale = new Vector3(m_FileScaleFactor * globalScale, m_FileScaleFactor * globalScale, m_FileScaleFactor * globalScale); bones[0].localRotation = Quaternion.Euler(rigEulerRoot);//0,-90f,-90f); bones[0].localPosition = rigOffset; //bones[0].localPosition=Vector3.up; return(bones); }
static void readNodes(BinaryReader reader, AMF amf, bool skip = false) { int count = reader.ReadInt32(); Debug.Log("Node count:" + count); long address = (long)reader.ReadInt32(); //Debug.Log("Address:" + address); //Debug.Log("Current Pos:" + reader.BaseStream.Position); long fPos = reader.BaseStream.Position; List <AMF_Node> nodes = new List <AMF_Node>(); if (count > 0 && !skip) { reader.BaseStream.Seek(address, SeekOrigin.Begin); for (int i = 0; i < count; i++) { string name = reader.ReadCString(); short parentIndex = reader.ReadInt16(); short childIndex = reader.ReadInt16(); short siblingIndex = reader.ReadInt16(); Vector3 pos = new Vector3(reader.ReadSingle(), reader.ReadSingle(), reader.ReadSingle()); Quaternion rot = new Quaternion(reader.ReadSingle(), reader.ReadSingle(), reader.ReadSingle(), reader.ReadSingle()); name = i.ToString().PadLeft(3, '0') + name; nodes.Add(new AMF_Node(name, parentIndex, childIndex, siblingIndex, pos, rot)); } reader.BaseStream.Seek(fPos, SeekOrigin.Begin); } //if (count == 0) //{ // count = reader.ReadInt64(); // Debug.Log("Node count:" + count); // address = reader.ReadInt64(); // Debug.Log("Address:" + address); //} //Debug.Log(ReadCString(reader)); }
public void AMF_EncodeNamedStringTest() { AVal name = AVal.AVC("name"), val = AVal.AVC("val"); byte[] buf = new byte[100]; int enc = 0, pend = buf.Length; int len = 2 + 4 + 1 + 2 + 3; // "name".len + "name" + AMF_STRING + "val".len + "val" enc = AMF.AMF_EncodeNamedString(buf, enc, pend, name, val); Assert.AreEqual(len, enc); Assert.AreEqual(0x00, buf[0]); Assert.AreEqual(0x04, buf[1]); Assert.AreEqual('n', buf[2]); Assert.AreEqual('a', buf[3]); Assert.AreEqual('m', buf[4]); Assert.AreEqual('e', buf[5]); Assert.AreEqual((byte)AMFDataType.AMF_STRING, buf[6]); Assert.AreEqual(0x00, buf[7]); Assert.AreEqual(0x03, buf[8]); Assert.AreEqual('v', buf[9]); Assert.AreEqual('a', buf[10]); Assert.AreEqual('l', buf[11]); Assert.AreEqual(0x00, buf[12]); }
static void readShaders(BinaryReader reader, AMF amf, bool skip = false, bool dumpNames = false) { //ShaderInfo amf.shaderInfos = new List <AdjutantSharp.ShaderInfo>(); //ShaderTypes List <int> shaderTypes = new List <int>(); long sCount = reader.ReadInt32(); Debug.Log("Shader Count:" + sCount); long sAddress = reader.ReadInt32(); long fPos = reader.BaseStream.Position; int debugCount = 0; if (sCount > 0) { reader.BaseStream.Seek(sAddress, SeekOrigin.Begin); for (int i = 0; i < sCount; i++) { string sName = reader.ReadCString(); int sType = 0; if (sName.Substring(0, 1).Equals("*")) { sType = 1; sName = sName.Substring(1); } if (dumpNames) { if (sType == 0) { Console.Write("Regular"); } else { Console.Write("Terrain"); } Debug.Log("Shader:" + sName + " tints:" + (amf.version > 1.1f)); } shaderTypes.Add(sType); if (sType == 0) { amf.shaderInfos.Add(new RegularShader(sName, reader, amf.version > 1.1f, (dumpNames && debugCount < 1))); debugCount++; } else { amf.shaderInfos.Add(new TerrainShader(sName, reader)); if (dumpNames && amf.shaderInfos[i].sName.Equals("cust_wall")) { TerrainShader ts = (TerrainShader)amf.shaderInfos[i]; Debug.Log("cust_wall"); for (int maps = 0; maps < ts.baseMaps.Count; maps++) { Debug.Log("[" + maps + "]:" + ts.baseMaps[maps] + " [" + ts.baseTiles[maps].x + "," + ts.baseTiles[maps].y + "] " + ts.detMaps[maps] + " " + ts.detTiles[maps].ToString()); } Debug.Log("Blend tile:" + ts.blendPath + " " + ts.blendTile.ToString()); } } } } reader.BaseStream.Seek(fPos, SeekOrigin.Begin); }
static void readRegions(BinaryReader reader, AMF amf, bool skip = false) { int regionCount = reader.ReadInt32(); Debug.Log("Region Count:" + regionCount); long regionAddress = reader.ReadInt32(); long fPos = reader.BaseStream.Position; amf.regionInfo = new List <AMF_RegionInfo>(); //List <List<AMF_Permutations>> if (regionCount > 0 && !skip) { reader.BaseStream.Seek(regionAddress, SeekOrigin.Begin); for (int i = 0; i < regionCount; i++) { List <AMF_Permutations> permutations = new List <AMF_Permutations>(); string regionName = reader.ReadCString(); int pCount = reader.ReadInt32(); long pAddress = reader.ReadInt32(); long pPos = reader.BaseStream.Position; if (pCount > 0) { reader.BaseStream.Seek(pAddress, SeekOrigin.Begin); for (int j = 0; j < pCount; j++) { string pName = reader.ReadCString(); sbyte vTemp = reader.ReadSByte(); byte nIndex = reader.ReadByte(); int vCount = reader.ReadInt32(); long vAddress = reader.ReadInt32(); int fCount = reader.ReadInt32(); long fAddress = reader.ReadInt32(); int sCount = reader.ReadInt32(); long sAddress = reader.ReadInt32(); //Debug.LogFormat("vTemp {0}",vTemp.ToString()); int vFormat = vTemp & 15; int cFormat = (vTemp & 240) >> 4; float mult = 0f; //Debug.LogFormat("Parse Permutation: {0} - {1}v-{2}f-{3}s",pName,vCount,fCount,sCount); //transform = matrix3 1 ??? Matrix4x4 trnsfm = Matrix4x4.identity; if (amf.version > 0.1) { mult = reader.ReadSingle(); //NANI?! if (!float.IsNaN(mult)) { trnsfm = reader.ReadMatrix4x4(true); //new Matrix4x4(reader.ReadVector4(0f),reader.ReadVector4(0f),reader.ReadVector4(0f),reader.ReadVector4(0f)); //transform = new Matrix4x4(reader.ReadSingle(), reader.ReadSingle(), reader.ReadSingle(), 1.0f, reader.ReadSingle(), reader.ReadSingle(), reader.ReadSingle(), 1.0f, reader.ReadSingle(), reader.ReadSingle(), reader.ReadSingle(), 1.0f, reader.ReadSingle(), reader.ReadSingle(), reader.ReadSingle(), 1.0f); //3DS uses a 4x3 so we need to pad an extra column for the identity trnsfm.m33 = 1; } } long xPos = reader.BaseStream.Position; bool vDone = false; bool fDone = false; List <AMF_Vertex> vertices = new List <AMF_Vertex>(); Matrix4x4 vMat = Matrix4x4.identity; List <Vector3Int> faces = null; foreach (AMF_Permutations permX in permutations) { //do some weird copy verts thing if (permX.vAddress == vAddress && !vDone) { //not really a copy, it's actually just caclulating vMat //but I'm trying to preserve the original script as much //as possible before refactoring vMat = copyVertices(reader, permX.vertices, cFormat); vertices = permX.vertices; vDone = true; } if (permX.fAddress == fAddress && !fDone) { faces = permX.faces; fDone = true; } if (vDone && fDone) { break; } } List <Vector2> bounds = new List <Vector2>(); if (!vDone) { reader.BaseStream.Seek(vAddress, SeekOrigin.Begin); vMat = readVertices(reader, vFormat, cFormat, vCount, vertices, bounds); //verts list = readVertices vFormat,cFormat,vCount } if (!fDone) { reader.BaseStream.Seek(fAddress, SeekOrigin.Begin); //faces list = readFaces vCount,fCount faces = readFaces(reader, vCount, fCount); } reader.BaseStream.Seek(sAddress, SeekOrigin.Begin); List <AMF_Mesh> meshes = readMeshes(reader, sCount); /* Debug.LogFormat("vMat:{0}",vMat); * Debug.LogFormat("trnsfm:{0}",trnsfm); */ //meshes list = readMeshes sCount //vMat*trnsfm permutations.Add(new AMF_Permutations(pName, vFormat, nIndex, vertices, faces, meshes, vAddress, fAddress, mult, vMat * trnsfm, bounds, cFormat)); //permutations[j].DebugCheck(); reader.BaseStream.Seek(xPos, SeekOrigin.Begin); } } amf.regionInfo.Add(new AMF_RegionInfo(regionName, permutations)); reader.BaseStream.Seek(pPos, SeekOrigin.Begin); } } reader.BaseStream.Seek(fPos, SeekOrigin.Begin); }
static void readHeader(BinaryReader reader, AMF amf) { amf.header = System.Text.Encoding.UTF8.GetString(reader.ReadBytes(4)); amf.version = reader.ReadSingle(); amf.modelName = reader.ReadCString(); }
public override void OnImportAsset(AssetImportContext ctx) { /* if(amf!=null&&!shouldReimport) * return; */ Debug.Log("Attempting to import AMF:" + ctx.assetPath); EditorUtility.DisplayProgressBar("Parsing" + ctx.assetPath, "Parsing...", 0); this.amf = ParseAMF(ctx.assetPath); string workingDir = ctx.assetPath.Substring(0, ctx.assetPath.LastIndexOf("/") + 1); /* * Setup materials first */ Dictionary <string, Material> mats = new Dictionary <string, Material>(); Dictionary <string, AMFShaderInfo> matsHelpers = new Dictionary <string, AMFShaderInfo>(); System.IO.Directory.CreateDirectory(workingDir + "Materials/"); //System.IO.Directory.CreateDirectory(workingDir+"MaterialHelpers/"); AMFShaderInfo asi; float totalMats = amf.shaderInfos.Count; float matsComplete = 0; foreach (AdjutantSharp.ShaderInfo si in amf.shaderInfos) { EditorUtility.DisplayProgressBar("Setting up Materials...", si.sName, (matsComplete / totalMats)); asi = (AMFShaderInfo)AMFShaderInfo.CreateInstance(typeof(AMFShaderInfo)); asi.name = si.sName; asi.SaveData(si); if (!mats.ContainsKey(si.sName)) { string path = workingDir + "Materials/" + si.sName + ".mat"; Material material = (Material)AssetDatabase.LoadAssetAtPath(workingDir + "Materials/" + si.sName + ".mat", typeof(Material)); if (material == null) { asi.workingDir = workingDir; material = asi.CreateMaterial(); /* if(si.GetType()==typeof(RegularShader)){ * material=SetupRegularMaterial((RegularShader)si,workingDir); * }else{ * material=SetupTerrainMaterial((TerrainShader)si,workingDir); * } */ AssetDatabase.CreateAsset(material, workingDir + "Materials/" + si.sName + ".mat"); } mats.Add(si.sName, material); matsHelpers.Add(si.sName, asi); ctx.AddObjectToAsset("MaterialHelper-" + asi.sName, asi); ctx.DependsOnSourceAsset(workingDir + "Materials/" + si.sName + ".mat"); /* if(material!=null) * ctx.AddObjectToAsset(material.name,material); */ } matsComplete++; } /* * Create Meshes */ GameObject root = new GameObject(amf.modelName); //amf.name=amf.modelName+"-RawAMF"; ctx.AddObjectToAsset(amf.modelName, root); /* ctx.AddObjectToAsset(amf.name,amf); * EditorUtility.SetDirty(amf); */ ctx.SetMainObject(root); Dictionary <long, Mesh> meshList = ConvertMeshes(amf, mats, matsHelpers, root); EditorUtility.DisplayProgressBar("Parsing " + ctx.assetPath, "[5/5] Finishing up...", (5f / 5f)); foreach (Mesh m in meshList.Values) { ctx.AddObjectToAsset(m.name, m); } if (CreateSkinnedMeshes) { Avatar a = root.GetComponent <Animator>().avatar; ctx.AddObjectToAsset(a.name, a); } Debug.Log("AMF import complete"); EditorUtility.ClearProgressBar(); shouldReimport = false; }
/* * * Convert Meshes */ public Dictionary <long, Mesh> ConvertMeshes(AMF amf, Dictionary <string, Material> mats, Dictionary <string, AMFShaderInfo> matHelpers, GameObject root) { //List<Mesh> meshList = new List<Mesh>(); Dictionary <long, Mesh> meshCache = new Dictionary <long, Mesh>(); float meshComplete = 0; float totalMeshCount = 0; List <GameObject> meshNodes = new List <GameObject>(); List <Transform> nodes = null; if (CreateSkinnedMeshes) { nodes = CreateRigging(amf); nodes[0].parent = root.transform; Animator anim = root.AddComponent <Animator>(); //Transform rigRoot=root.GetComponentInChildren<SkinnedMeshRenderer>().rootBone; if (copyAvatar) { //ctx.AddObjectToAsset(m_LastHumanDescriptionAvatarSource.name,m_LastHumanDescriptionAvatarSource); anim.avatar = m_LastHumanDescriptionAvatarSource; } else { //EditorUtility.DisplayProgressBar("Parsing "+ctx.assetPath,"Creating Avatar",(5f/5f)); List <string> reports = new List <string>(); HumanDescription hd = new HumanDescription(); AvatarSetupTool.SkeletonBone[] skeletonBones; bool hasTranslationDOF; reports = AvatarSetupTool.SetupHumanSkeleton(nodes[0].parent.gameObject, ref hd.human, out skeletonBones, out hasTranslationDOF); hd.hasTranslationDoF = hasTranslationDOF; SkeletonBone[] sb = new SkeletonBone[skeletonBones.Length + 1]; Array.Copy(Array.ConvertAll(skeletonBones, (p => (SkeletonBone)p)), sb, sb.Length - 1); sb[sb.Length - 1].name = nodes[0].parent.name; sb[sb.Length - 1].position = nodes[0].parent.localPosition; sb[sb.Length - 1].rotation = nodes[0].parent.localRotation; sb[sb.Length - 1].scale = nodes[0].parent.localScale; hd.skeleton = sb; Avatar a; if (rigType == RigType.Humanoid) { a = AvatarBuilder.BuildHumanAvatar(nodes[0].parent.gameObject, hd); } else { a = AvatarBuilder.BuildGenericAvatar(nodes[0].parent.gameObject, nodes[0].parent.name); } a.name = root.name + "Avatar"; //ctx.AddObjectToAsset(a.name,a); anim.avatar = a; } } foreach (AMF_RegionInfo ri in amf.regionInfo) { totalMeshCount += ri.permutations.Count; } for (int ri = 0; ri < amf.regionInfo.Count; ri++) { GameObject riNode = new GameObject(amf.regionInfo[ri].name); GameObjectUtility.SetParentAndAlign(riNode, root); foreach (AMF_Permutations perm in amf.regionInfo[ri].permutations) { EditorUtility.DisplayProgressBar("Creating Meshes", perm.pName, (meshComplete / totalMeshCount)); Mesh temp; if (createDuplicateInstances || !meshCache.ContainsKey(perm.vAddress)) { temp = ConvertInstanceToMesh(perm); //we have to flip the normals due to the coordinate system translation temp.FlipNormals(); temp.RecalculateNormals(); if (GenerateLightmapUVs) { EditorUtility.DisplayProgressBar("Generating Lightmap UVs", perm.pName, (meshComplete / totalMeshCount)); uvSettings.angleError = angleError; uvSettings.areaError = areaError; uvSettings.hardAngle = hardAngle; uvSettings.packMargin = packMargin; Unwrapping.GenerateSecondaryUVSet(temp, uvSettings); } meshCache.Add(perm.vAddress, temp); } else { temp = meshCache[perm.vAddress]; } GameObject meshNode = new GameObject(perm.pName); Matrix4x4 matr = Matrix4x4.identity; if (!float.IsNaN(perm.mult)) { Matrix4x4 scalerM = new Matrix4x4(); scalerM.SetRow(0, new Vector4(100f * m_FileScaleFactor, 0)); scalerM.SetRow(1, new Vector4(0, 100f * m_FileScaleFactor)); scalerM.SetRow(2, new Vector4(0, 0, 100f * m_FileScaleFactor)); scalerM.SetRow(3, new Vector4(0, 0, 0, 1)); matr.SetRow(0, new Vector4(perm.mult, 0)); matr.SetRow(1, new Vector4(0, perm.mult)); matr.SetRow(2, new Vector4(0, 0, perm.mult)); matr.SetRow(3, new Vector4(0, 0, 0, 1)); matr *= perm.matrix4x4; matr *= scalerM; Matrix4x4 unityMatr = matr.Convert3DSMatrixToUnity(); meshNode.transform.localScale = unityMatr.ExtractScale(); meshNode.transform.localRotation = unityMatr.GetRotation(); meshNode.transform.localPosition = unityMatr.ExtractPosition(); } else { meshNode.transform.localScale = new Vector3(m_FileScaleFactor, m_FileScaleFactor, m_FileScaleFactor); } //GameObjectUtility.SetParentAndAlign(meshNode,riNode); //meshNode.transform.localToWorldMatrix=matr; Renderer mr; if (temp.boneWeights.Length > 0 && CreateSkinnedMeshes) { mr = meshNode.AddComponent <SkinnedMeshRenderer>(); meshNode.transform.localRotation = Quaternion.Euler(0, 90, 0); Matrix4x4[] bindPoses = new Matrix4x4[nodes.Count]; for (int m = 0; m < bindPoses.Length; m++) { bindPoses[m] = nodes[m].worldToLocalMatrix * meshNode.transform.localToWorldMatrix; } temp.bindposes = bindPoses; ((SkinnedMeshRenderer)mr).sharedMesh = temp; ((SkinnedMeshRenderer)mr).bones = nodes.ToArray(); ((SkinnedMeshRenderer)mr).rootBone = nodes[0]; } else { MeshFilter mf = meshNode.AddComponent <MeshFilter>(); mf.sharedMesh = temp; mr = meshNode.AddComponent <MeshRenderer>(); if (RecenterPivots && !splitSubmeshes) { //for safety, lets guard this against splitting submeshes. mf.RecenterPivot(); } } meshNode.transform.parent = riNode.transform; if (GenerateMeshCollidersOnClusters && amf.regionInfo[ri].name.Equals("Clusters")) { MeshCollider mc = meshNode.AddComponent <MeshCollider>(); mc.sharedMesh = temp; } Material[] materials = new Material[temp.subMeshCount]; List <AMFShaderInfo> si = new List <AMFShaderInfo>(); for (int i = 0; i < materials.Length; i++) { materials[i] = mats[amf.shaderInfos[perm.meshes[i].shaderIndex].sName]; si.Add(matHelpers[amf.shaderInfos[perm.meshes[i].shaderIndex].sName]); //si[i].SaveData(amf.shaderInfos[perm.meshes[i].shaderIndex]); } mr.sharedMaterials = materials; AMFMaterialHelper mh = meshNode.AddComponent <AMFMaterialHelper>(); mh.shaderSettings = si; //mh.SaveData(amf.shaderInfos[perm.meshes[0].shaderIndex]); //Debug.LogFormat("Transform: Pos:{0} Rot:{1} Scale:{2}",perm.matrix4x4.ExtractPosition(),perm.matrix4x4.ExtractRotation(),perm.matrix4x4.ExtractScale()); meshComplete++; meshNodes.Add(meshNode); } } //This is annoying to do this here, but we have to wait until after the mesh cache is fully populated before we start splitting submeshes out. if (splitSubmeshes) { meshCache.Clear(); long fakeKey = 0; foreach (GameObject go in meshNodes) { MeshFilter mf = go.GetComponent <MeshFilter>(); if (mf != null && mf.sharedMesh.subMeshCount > 1) { Renderer r = go.GetComponent <MeshRenderer>(); for (int i = 0; i < mf.sharedMesh.subMeshCount; i++) { int matIndex = Mathf.Min(i, r.sharedMaterials.Length); GameObject tempGo = new GameObject(go.name + "_" + r.sharedMaterials[matIndex].name); MeshFilter tempMF = tempGo.AddComponent <MeshFilter>(); tempMF.sharedMesh = mf.sharedMesh.ExtractSubmesh(i); tempGo.AddComponent <MeshRenderer>().sharedMaterial = r.sharedMaterials[matIndex]; GameObjectUtility.SetParentAndAlign(tempGo, go); if (RecenterPivots) { tempMF.RecenterPivot(); } meshCache.Add(fakeKey, tempGo.GetComponent <MeshFilter>().sharedMesh); fakeKey++; } DestroyImmediate(mf); DestroyImmediate(r); } else { if (RecenterPivots) { go.GetComponent <MeshFilter>().RecenterPivot(); } meshCache.Add(fakeKey, go.GetComponent <MeshFilter>().sharedMesh); fakeKey++; } } } return(meshCache); }
public override void OnImportAsset(AssetImportContext ctx) { Debug.Log("Attempting to import AMF:" + ctx.assetPath); progressString += ctx.assetPath; EditorUtility.DisplayProgressBar(progressString, "Parsing...", 0); AMF amf = ParseAMF(ctx.assetPath); string workingDir = ctx.assetPath.Substring(0, ctx.assetPath.LastIndexOf("/") + 1); /* * Setup materials first */ Dictionary <string, Material> mats = new Dictionary <string, Material>(); Dictionary <string, AMFShaderInfo> matsHelpers = new Dictionary <string, AMFShaderInfo>(); System.IO.Directory.CreateDirectory(workingDir + "Materials/"); //System.IO.Directory.CreateDirectory(workingDir+"MaterialHelpers/"); AMFShaderInfo asi; float totalMats = amf.shaderInfos.Count; float matsComplete = 0; foreach (AdjutantSharp.ShaderInfo si in amf.shaderInfos) { EditorUtility.DisplayProgressBar("Setting up Materials...", si.sName, (matsComplete / totalMats)); asi = (AMFShaderInfo)AMFShaderInfo.CreateInstance(typeof(AMFShaderInfo)); asi.name = si.sName; asi.SaveData(si); if (!mats.ContainsKey(si.sName)) { string path = workingDir + "Materials/" + si.sName + ".mat"; Material material = (Material)AssetDatabase.LoadAssetAtPath(workingDir + "Materials/" + si.sName + ".mat", typeof(Material)); if (material == null) { asi.workingDir = workingDir; material = asi.CreateMaterial(); /* if(si.GetType()==typeof(RegularShader)){ * material=SetupRegularMaterial((RegularShader)si,workingDir); * }else{ * material=SetupTerrainMaterial((TerrainShader)si,workingDir); * } */ AssetDatabase.CreateAsset(material, workingDir + "Materials/" + si.sName + ".mat"); } mats.Add(si.sName, material); matsHelpers.Add(si.sName, asi); ctx.AddObjectToAsset("MaterialHelper-" + asi.sName, asi); ctx.DependsOnSourceAsset(workingDir + "Materials/" + si.sName + ".mat"); /* if(material!=null) * ctx.AddObjectToAsset(material.name,material); */ } matsComplete++; } //EditorUtility.DisplayProgressBar(progressString,"[4/5] Creating Meshes...",(4f/5f)); /* * Create Meshes */ GameObject root = new GameObject(amf.modelName); ctx.AddObjectToAsset(amf.modelName, root); ctx.SetMainObject(root); Dictionary <long, Mesh> meshList = ConvertMeshes(amf, mats, matsHelpers, root); //root.transform.rotation=Quaternion.Euler(-90f,0f,0f); /* LoadRegions(amf,root); * List<Mesh> meshList=CreateMeshes(amf,root.transform,mats); */ UnwrapParam.SetDefaults(out uvSettings); EditorUtility.DisplayProgressBar(progressString, "[5/5] Finishing up...", (5f / 5f)); float lightCount = 0; float totalLight = meshList.Count; foreach (Mesh m in meshList.Values) { /* if(GenerateLightmapUVs){ * EditorUtility.DisplayProgressBar("Generating Lightmaps","["+lightCount+"/"+totalLight+"] Generating UVs...",(lightCount/totalLight)); * Unwrapping.GenerateSecondaryUVSet(m,uvSettings); * lightCount++; * } */ ctx.AddObjectToAsset(m.name, m); } Debug.Log("AMF import complete"); EditorUtility.ClearProgressBar(); }
/* * * Convert Meshes */ public Dictionary <long, Mesh> ConvertMeshes(AMF amf, Dictionary <string, Material> mats, Dictionary <string, AMFShaderInfo> matHelpers, GameObject root) { //List<Mesh> meshList = new List<Mesh>(); Dictionary <long, Mesh> meshCache = new Dictionary <long, Mesh>(); float meshComplete = 0; float totalMeshCount = 0; foreach (AMF_RegionInfo ri in amf.regionInfo) { totalMeshCount += ri.permutations.Count; } for (int ri = 0; ri < amf.regionInfo.Count; ri++) { GameObject riNode = new GameObject(amf.regionInfo[ri].name); GameObjectUtility.SetParentAndAlign(riNode, root); foreach (AMF_Permutations perm in amf.regionInfo[ri].permutations) { EditorUtility.DisplayProgressBar("Creating Meshes", perm.pName, (meshComplete / totalMeshCount)); Mesh temp; if (createDuplicateInstances || !meshCache.ContainsKey(perm.vAddress)) { temp = new Mesh(); temp.name = perm.pName; List <Vector3> verts = new List <Vector3>(); List <Vector2> uvs = new List <Vector2>(); List <int> badIndex = new List <int>(); int[] identity = new int[perm.vertices.Count]; //matr=matr.ConvertHandedness(); Matrix4x4 texMatrix = Matrix4x4.identity; for (int i = 0; i < perm.vertices.Count; i++) { Vector3 pos = perm.vertices[i].pos; identity[i] = i; //pos=perm.matrix4x4*pos; if (pos.IsBad()) { Debug.LogErrorFormat("Invalid vertex found: [{0}]" + perm.vertices[i].pos.ToString(), i); badIndex.Add(i); verts.Add(Vector3.zero); uvs.Add(Vector2.zero); } else { if (!float.IsNaN(perm.mult)) { Matrix4x4 flip = Matrix4x4.identity; flip.SetRow(0, new Vector4(-1, 0)); verts.Add(flip.MultiplyPoint3x4(pos)); } else { //verts.Add(Matrix4x4.identity.Convert3DSMatrixToUnity().MultiplyPoint3x4(pos)); Matrix4x4 flip = Matrix4x4.identity; flip.SetRow(0, new Vector4(-1, 0)); flip.SetRow(1, new Vector4(0, 0, 1)); flip.SetRow(2, new Vector4(0, -1)); verts.Add(flip.MultiplyPoint3x4(pos)); } uvs.Add(perm.vertices[i].tex); texMatrix = perm.vertices[i].tmat; } } temp.SetVertices(verts); temp.SetUVs(0, uvs); List <int> tris; int faceTotal = 0; temp.subMeshCount = perm.meshes.Count; /* temp.SetIndices(identity,MeshTopology.Points,0); */ // Debug.LogFormat("{0} adding submeshes",perm.pName); for (int s = 0; s < perm.meshes.Count; s++) { AMF_Mesh sinfo = perm.meshes[s]; faceTotal += sinfo.faceCount; tris = new List <int>(); // Debug.LogFormat("{0}:{1}-{2}",s,sinfo.startingFace,sinfo.faceCount); for (int f = 0; f < sinfo.faceCount; f++) { Vector3Int face = perm.faces[f + sinfo.startingFace]; if (badIndex.Contains(face.x) || badIndex.Contains(face.y) || badIndex.Contains(face.z)) { // Debug.LogWarning("Dumping face due to invalid vertex"); } else { tris.Add(face.x); tris.Add(face.y); tris.Add(face.z); } } //Debug.LogFormat("{0} Setting {1} triangles",s,tris.Count); temp.SetTriangles(tris, s); } if (perm.faces.Count != faceTotal) { Debug.LogErrorFormat("Faces mistmatch: {0}vs{1} {2}", perm.faces.Count, faceTotal, perm.pName); } //if(!float.IsNaN(perm.mult)){ temp.FlipNormals(); //} temp.RecalculateNormals(); if (GenerateLightmapUVs) { Unwrapping.GenerateSecondaryUVSet(temp); } meshCache.Add(perm.vAddress, temp); } else { temp = meshCache[perm.vAddress]; } GameObject meshNode = new GameObject(perm.pName); Matrix4x4 matr = Matrix4x4.identity; if (!float.IsNaN(perm.mult)) { Matrix4x4 scalerM = new Matrix4x4(); scalerM.SetRow(0, new Vector4(100f * importScale, 0)); scalerM.SetRow(1, new Vector4(0, 100f * importScale)); scalerM.SetRow(2, new Vector4(0, 0, 100f * importScale)); scalerM.SetRow(3, new Vector4(0, 0, 0, 1)); matr.SetRow(0, new Vector4(perm.mult, 0)); matr.SetRow(1, new Vector4(0, perm.mult)); matr.SetRow(2, new Vector4(0, 0, perm.mult)); matr.SetRow(3, new Vector4(0, 0, 0, 1)); matr *= perm.matrix4x4; matr *= scalerM; Matrix4x4 unityMatr = matr.Convert3DSMatrixToUnity(); meshNode.transform.localScale = unityMatr.ExtractScale(); meshNode.transform.localRotation = unityMatr.GetRotation(); meshNode.transform.localPosition = unityMatr.ExtractPosition(); } else { meshNode.transform.localScale = new Vector3(importScale, importScale, importScale); } //GameObjectUtility.SetParentAndAlign(meshNode,riNode); //meshNode.transform.localToWorldMatrix=matr; MeshFilter mf = meshNode.AddComponent <MeshFilter>(); mf.sharedMesh = temp; MeshRenderer mr = meshNode.AddComponent <MeshRenderer>(); meshNode.transform.parent = riNode.transform; if (GenerateMeshCollidersOnClusters && amf.regionInfo[ri].name.Equals("Clusters")) { MeshCollider mc = meshNode.AddComponent <MeshCollider>(); mc.sharedMesh = mf.sharedMesh; } Material[] materials = new Material[temp.subMeshCount]; List <AMFShaderInfo> si = new List <AMFShaderInfo>(); for (int i = 0; i < materials.Length; i++) { materials[i] = mats[amf.shaderInfos[perm.meshes[i].shaderIndex].sName]; si.Add(matHelpers[amf.shaderInfos[perm.meshes[i].shaderIndex].sName]); //si[i].SaveData(amf.shaderInfos[perm.meshes[i].shaderIndex]); } mr.sharedMaterials = materials; AMFMaterialHelper mh = meshNode.AddComponent <AMFMaterialHelper>(); mh.shaderSettings = si; //mh.SaveData(amf.shaderInfos[perm.meshes[0].shaderIndex]); //Debug.LogFormat("Transform: Pos:{0} Rot:{1} Scale:{2}",perm.matrix4x4.ExtractPosition(),perm.matrix4x4.ExtractRotation(),perm.matrix4x4.ExtractScale()); meshComplete++; } } return(meshCache); }