public V_group(uint start_, uint stop_, uint size_, int[] bones_, string[] names_, int triangle_count_, int[] triangles_) { this = new V_group(); start = start_; stop = stop_; size = size_; bones = bones_; boneNames = names_; triangle_count = triangle_count_; triangles = triangles_; }
public override void OnImportAsset(AssetImportContext ctx) { string fileName = System.IO.Path.GetFileNameWithoutExtension(ctx.assetPath); string fName_ = System.IO.Path.GetFileName(ctx.assetPath); string current_dir_rel = System.IO.Path.GetDirectoryName(ctx.assetPath); string current_dir_abs = System.IO.Path.GetFullPath(current_dir_rel); //location string fName = Path.Combine(current_dir_abs, fName_); string dirName = System.IO.Path.GetFileName(current_dir_abs); FF7R_Utilities utils = new FF7R_Utilities(); string[] the_files = utils.model_files(current_dir_abs); string model_dir = the_files[2]; string file_a = the_files[0]; string file_b = utils.get_largest_file(model_dir); if (fName == file_a && fName == file_b) { string c_name = the_files[3]; MonoBehaviour.print($"Name: {c_name}"); //MonoBehaviour.print($"fName : {fName}"); //MonoBehaviour.Debug.Log($"fName : {fName}"); //MonoBehaviour.print($"file_a: {file_a}"); //MonoBehaviour.print($"file_b: {file_b}"); byte[] fname = File.ReadAllBytes(fName); FileData md = new FileData(fname); byte[] fname_2 = File.ReadAllBytes(the_files[1]); FileData ua = new FileData(fname_2); var go = new GameObject(fileName); ctx.AddObjectToAsset(fileName, go); ctx.SetMainObject(go); QualitySettings.skinWeights = SkinWeights.Unlimited; /* ??? * ModelImporter.skinWeights = ModelImporterSkinWeights.Custom; * ModelImporter.maxBonesPerVertex = 8; */ // uasset byte check = (byte)ua.readByte(); if (check == 193) { ua.Endian = Endianness.Little; } else { ua.Endian = Endianness.Big; } ua.seek(3, 1); int version = ua.readInt(); int thing1 = ua.readInt(); int serialVersion = ua.readInt(); int unk = ua.readInt(); int headerCount = ua.readInt(); for (int v = 0; v < headerCount; v++) { int v0 = ua.readInt(); int v1 = ua.readInt(); int v2 = ua.readInt(); int v3 = ua.readInt(); int unk_a = ua.readInt(); } int uassetFileSize = ua.readInt(); int unk0 = ua.readInt(); int packageGroup = ua.readInt(); int packageFlags = ua.readInt(); int unk1 = ua.readByte(); int stringCount = ua.readInt(); int stringOffset = ua.readInt(); ua.seek(stringOffset, 0); List <string> names = new List <string>(); for (int y = 0; y < stringCount; y++) { int size = ua.readInt(); size -= 1; string name = ua.readString(size); int null_0 = ua.readByte(); int unk_b = ua.readInt(); names.Add(name); } // uexp int start = md.getStart(); if (start == 0) { MonoBehaviour.print("Couldn't find beginning of data\n\n"); throw new Exception(); } md.seek(start, 0); MonoBehaviour.print("start: " + start); MonoBehaviour.print("\n\n\n\n"); int materialCount = md.readInt(); MonoBehaviour.print("materialCount: " + materialCount); List <string> materials = new List <string>(); for (int j = 0; j < materialCount; j++) { int val0 = md.readInt(); int stringIndex = md.readInt(); int zero0 = md.readInt(); int one = md.readInt(); int zero1 = md.readInt(); float fm0 = md.readFloat(); float fm1 = md.readFloat(); float fm2 = md.readFloat(); int zero2 = md.readInt(); materials.Add(names[stringIndex]); } List <Joint> joint_data = new List <Joint>(); int boneCount = md.readInt(); List <string> boneNAMES = new List <string>(); MonoBehaviour.print("boneCount: " + boneCount); MonoBehaviour.print("\n"); for (int j = 0; j < boneCount; ++j) { int string_index = md.readInt(); int unk_c = md.readInt(); int parent = md.readInt(); string jointName = names[string_index]; Joint new_joint = new Joint(jointName, parent); joint_data.Add(new_joint); boneNAMES.Add(jointName); } int boneCount2 = md.readInt(); List <string> skl_n = new List <string>(); Transform[] BNArr = new Transform[boneNAMES.Count]; Matrix4x4[] bindPoses = new Matrix4x4[boneNAMES.Count]; for (int k = 0; k < boneCount2; k++) { float qx = md.readFloat(); float qy = md.readFloat(); float qz = md.readFloat(); float qw = md.readFloat(); float px = md.readFloat(); float py = md.readFloat(); float pz = md.readFloat(); float sx = md.readFloat(); float sy = md.readFloat(); float sz = md.readFloat(); string boneName = joint_data[k].name; int BNparent = joint_data[k].parent; skl_n.Add(boneName); BNArr[k] = new GameObject(boneName).transform; if (BNparent != -1) { BNArr[k].parent = BNArr[BNparent]; } BNArr[k].localRotation = new Quaternion(qx, qy, qz, qw); BNArr[k].localPosition = new Vector3(px, py, pz); //BNArr[k].localScale = new Vector3(sx, sy, sz); bindPoses[k] = BNArr[k].worldToLocalMatrix; } int boneCount3 = md.readInt(); md.seek(boneCount3 * 12, 1); List <V_group> vertexGroups = new List <V_group>(); int unk10 = md.readInt(); int unk11 = md.readByte(); int unk12 = md.readByte(); uint groupCount = (uint)md.readInt(); for (int m = 0; m < groupCount; ++m) { int z1 = md.readShort(); ushort ID = (ushort)md.readShort(); int null_a = md.readInt(); int tri_count = md.readInt(); md.seek(16, 1); //# pragma region bone palette uint start_g = (uint)md.readInt(); uint count = (uint)md.readInt(); string[] bone_names = new string[count]; int[] bone_IDs = new int[count]; for (int bn = 0; bn < count; ++bn) { int bid = md.readShort(); bone_IDs[bn] = bid; bone_names[bn] = joint_data[bid].name; } //# pragma endregion bone palette uint size = (uint)md.readInt(); uint stop = start_g + size; md.seek(34, 1); int FFx4 = md.readInt(); uint flag = (uint)md.readInt(); if (flag == 1) // extra data for this group { uint count_f = (uint)md.readInt(); md.seek((int)count_f * 16, 1); } else { int null_gr = md.readInt(); } int[] tris = new int[tri_count * 3]; V_group new_vgroup = new V_group(start_g, stop, size, bone_IDs, bone_names, tri_count, tris); vertexGroups.Add(new_vgroup); } //groupCount int unkByte = md.readByte(); uint stride = (uint)md.readInt(); uint fCount = (uint)md.readInt(); int[] faces = new int[fCount]; if (stride == 4) { foreach (V_group vg in vertexGroups) { for (int x = 0; x < vg.triangle_count; x++) { int yt = x * 3; int f0 = md.readInt(); int f1 = md.readInt(); int f2 = md.readInt(); faces[yt] = f2; faces[yt + 1] = f1; faces[yt + 2] = f0; vg.triangles[yt] = f2; vg.triangles[yt + 1] = f1; vg.triangles[yt + 2] = f0; } } } else if (stride == 2) { foreach (V_group vg in vertexGroups) { for (int x = 0; x < vg.triangle_count; x++) { int yt = x * 3; int f0 = md.readInt(); int f1 = md.readInt(); int f2 = md.readInt(); faces[yt] = f2; faces[yt + 1] = f1; faces[yt + 2] = f0; vg.triangles[yt] = f2; vg.triangles[yt + 1] = f1; vg.triangles[yt + 2] = f0; } } } int unkCount = md.readInt(); md.seek(unkCount * 2, 1); int unk25 = md.readInt(); int vertexCount = md.readInt(); int boneCount4 = md.readInt(); md.seek(boneCount4 * 2, 1); int null0 = md.readInt(); int null1 = md.readInt(); int uv_count = md.readInt(); int unk3 = md.readShort(); int uv_count2 = md.readInt(); int null2 = md.readInt(); float unk4 = md.readFloat(); float unk5 = md.readFloat(); float unk6 = md.readFloat(); int null3 = md.readInt(); int null4 = md.readInt(); int null5 = md.readInt(); int vStride = md.readInt(); int vCount = md.readInt(); int vertexCount2 = vCount * 3; int uvCount = vCount * 3; Vector2[] UVs0 = new Vector2[vCount]; Vector2[] UVs1 = new Vector2[vCount]; Vector2[] UVs2 = new Vector2[vCount]; Vector2[] UVs3 = new Vector2[vCount]; Vector3[] vArray = new Vector3[vCount]; for (int v = 0; v < vCount; ++v) { float nt0 = md.readByte() / 255.0f; float nt1 = md.readByte() / 255.0f; float nt2 = md.readByte() / 255.0f; float nt3 = md.readByte() / 255.0f; float nt4 = md.readByte() / 255.0f; float nt5 = md.readByte() / 255.0f; float nt6 = md.readByte() / 255.0f; float nt7 = md.readByte() / 255.0f; float px = md.readFloat(); float py = md.readFloat(); float pz = md.readFloat(); Vector3 pts = new Vector3(px, py, pz); vArray[v] = pts; if (uv_count > 0) { float u0 = md.readHalfFloat(); float v0 = md.readHalfFloat() * -1.0f + 1.0f; Vector2 uv_0 = new Vector2(u0, v0); UVs0[v] = uv_0; } if (uv_count > 1) { float u1 = md.readHalfFloat(); float v1 = md.readHalfFloat() * -1.0f + 1.0f; Vector2 uv_1 = new Vector2(u1, v1); UVs1[v] = uv_1; } if (uv_count > 2) { float u2 = md.readHalfFloat(); float v2 = md.readHalfFloat() * -1.0f + 1.0f; Vector2 uv_2 = new Vector2(u2, v2); UVs2[v] = uv_2; } if (uv_count > 3) { float u3 = md.readHalfFloat(); float v3 = md.readHalfFloat() * -1.0f + 1.0f; Vector2 uv_3 = new Vector2(u3, v3); UVs3[v] = uv_3; } } int unkS = md.readShort(); int extraBoneWeights = md.readInt(); int wCount = md.readInt(); int w_stride = md.readInt(); int wCount2 = md.readInt(); int subStride = w_stride / 2; int bw_count = vCount * subStride; byte[] bonesPerVertex = new byte[wCount]; for (int wz = 0; wz < wCount; ++wz) { bonesPerVertex[wz] = (byte)subStride; } var bonesPerVertexArray = new NativeArray <byte>(bonesPerVertex, Allocator.Temp); BoneWeight1[] weightsT = new BoneWeight1[bw_count]; foreach (V_group q in vertexGroups) { int[] boneIDs = q.bones; string[] b_names = q.boneNames; int start_ = (int)q.start; int stop_ = (int)q.stop; for (int j = start_; j < stop_; ++j) { int jd = j * subStride; int[] b_temp = new int[subStride]; for (int wc = 0; wc < subStride; ++wc) { int b0 = md.readByte(); b_temp[wc] = boneIDs[b0]; } for (int wd = 0; wd < subStride; ++wd) { float w0 = md.readByte() / 255.0f; weightsT[jd + wd].boneIndex = b_temp[wd]; weightsT[jd + wd].weight = w0; } } } string meshName = "Test"; var go2 = new GameObject(meshName); go2.AddComponent <Animation> (); go2.AddComponent <SkinnedMeshRenderer> (); SkinnedMeshRenderer rend = go2.GetComponent <SkinnedMeshRenderer> (); Mesh ff7r = new Mesh(); ff7r.indexFormat = UnityEngine.Rendering.IndexFormat.UInt32; ff7r.vertices = vArray; //ff7r.triangles = faces; ff7r.uv = UVs0; ff7r.uv2 = UVs1; ff7r.uv3 = UVs2; Material[] dumbMaterials = new Material[(int)groupCount]; ff7r.subMeshCount = (int)groupCount; for (int v = 0; v < groupCount; ++v) { ff7r.SetTriangles(vertexGroups[v].triangles, v); dumbMaterials[v] = matSetup(new Color(0.4f, 0.4f, 0.4f, 1)); dumbMaterials[v].name = materials[v]; } ff7r.name = meshName; rend.sharedMesh = ff7r; rend.sharedMaterials = dumbMaterials; var weightsArray = new NativeArray <BoneWeight1>(weightsT, Allocator.Temp); ff7r.bindposes = bindPoses; ff7r.SetBoneWeights(bonesPerVertexArray, weightsArray); rend.bones = BNArr; rend.rootBone = BNArr[0]; rend.rootBone.transform.Rotate(-90.0f, 0.0f, 0.0f, Space.World); float t = 0.01f; Vector3 s = rend.rootBone.transform.localScale; rend.rootBone.transform.localScale = new Vector3(s.x * t, s.y * t, s.z * t); rend.updateWhenOffscreen = true; } }