private void LoadFLVER2(FLVER2 flver, bool useSecondUV, Dictionary <string, int> boneIndexRemap = null, bool ignoreStaticTransforms = false) { lock (_lock_submeshes) { Submeshes = new List <FlverSubmeshRenderer>(); } foreach (var submesh in flver.Meshes) { // Blacklist some materials that don't have good shaders and just make the viewer look like a mess MTD mtd = null;// InterrootLoader.GetMTD(Path.GetFileName(flver.Materials[submesh.MaterialIndex].MTD)); if (mtd != null) { if (mtd.ShaderPath.Contains("FRPG_Water_Env")) { continue; } if (mtd.ShaderPath.Contains("FRPG_Water_Reflect.spx")) { continue; } } var smm = new FlverSubmeshRenderer(this, flver, submesh, useSecondUV, boneIndexRemap, ignoreStaticTransforms); Bounds = new BoundingBox(); lock (_lock_submeshes) { Submeshes.Add(smm); Bounds = BoundingBox.CreateMerged(Bounds, smm.Bounds); } } }
public static void ReloadMtds() { IBinder mtdBinder = null; if (AssetLocator.Type == GameType.DarkSoulsIII || AssetLocator.Type == GameType.Sekiro) { mtdBinder = BND4.Read(AssetLocator.GetAssetPath($@"mtd\allmaterialbnd.mtdbnd.dcx")); } if (mtdBinder == null) { return; } _mtds = new Dictionary <string, MTD>(); foreach (var f in mtdBinder.Files) { var mtdname = Path.GetFileNameWithoutExtension(f.Name); // Because *certain* mods contain duplicate entries for the same material if (!_mtds.ContainsKey(mtdname)) { _mtds.Add(mtdname, MTD.Read(f.Bytes)); } } }
public void InitializeFromMTD(MTD mtd, string virtualPath) { VirtualPath = virtualPath; ShaderPath = mtd.ShaderPath; Textures = new List <TextureDefinition>(); foreach (var tex in mtd.Textures) { var def = new TextureDefinition(); def.Name = tex.Type; def.UVNumber = tex.UVNumber; def.ShaderDataIndex = tex.ShaderDataIndex; if (tex.Extended) { def.TexturePath = tex.Path; } // Calculate the uv set index int uvoffset = 1; for (int j = 1; j < tex.UVNumber; j++) { if (!mtd.Textures.Any(t => (t.UVNumber == j))) { uvoffset++; } } def.UVIndex = tex.UVNumber - uvoffset; if (tex.Type.ToUpper() == "G_LIGHTMAP" || tex.Type.ToUpper() == "G_DOLTEXTURE1" || tex.Type.ToUpper() == "G_GITEXTURE") { LightmapUVIndex = def.UVIndex; } Textures.Add(def); } }
private void CmbMTD_SelectedIndexChanged(object sender, EventArgs e) { dgvParams.DataSource = null; dgvTextures.DataSource = null; MTDWrapper item = cmbMTD.SelectedItem as MTDWrapper; mtd = item.MTD; LoadMTD(mtd); }
public Model(FLVER0 flver) { Type = ModelType.ModelTypeFlver; Submeshes = new List <FlverSubmeshRenderer>(); var subBoundsPoints = new List <Vector3>(); foreach (var submesh in flver.Meshes) { // Blacklist some materials that don't have good shaders and just make the viewer look like a mess MTD mtd = null;// InterrootLoader.GetMTD(Path.GetFileName(flver.Materials[submesh.MaterialIndex].MTD)); if (mtd != null) { if (mtd.ShaderPath.Contains("FRPG_Water_Env")) { continue; } if (mtd.ShaderPath.Contains("FRPG_Water_Reflect.spx")) { continue; } } if (submesh.ToTriangleList().Length > 0) { var smm = new FlverSubmeshRenderer(this, flver, submesh); Submeshes.Add(smm); subBoundsPoints.Add(smm.Bounds.Min); subBoundsPoints.Add(smm.Bounds.Max); } } //DEBUG// //Console.WriteLine($"{flver.Meshes[0].DefaultBoneIndex}"); //Console.WriteLine(); //Console.WriteLine(); //foreach (var mat in flver.Materials) //{ // Console.WriteLine($"{mat.Name}: {mat.MTD}"); //} ///////// if (Submeshes.Count == 0) { Bounds = new BoundingBox(); IsVisible = false; } else { Bounds = BoundingBox.CreateFromPoints(subBoundsPoints); } }
private void LoadMTD(MTD mtd) { txtDescription.DataBindings.Clear(); txtDescription.DataBindings.Add("Text", mtd, "Description"); txtDescriptionTranslated.Text = MTDTranslations.GetTranslation(mtd.Description); txtShader.DataBindings.Clear(); txtShader.DataBindings.Add("Text", mtd, "ShaderPath"); dgvTextures.DataSource = mtd.Textures; bool extended = mtd.Textures.Any(t => t.Extended); dgvTexturesFloatsCol.Visible = extended; dgvTexturesPathCol.Visible = extended; dgvParams.DataSource = mtd.Params; }
public static void LoadMTDBND() { MtdDict.Clear(); MTDBND = null; if (GameType == GameTypes.SDT) { MTDBND = BND4.Read(GetInterrootPath($@"mtd\allmaterialbnd.mtdbnd.dcx")); foreach (var f in MTDBND.Files) { var key = Utils.GetShortIngameFileName(f.Name); if (!MtdDict.ContainsKey(key)) { MtdDict.Add(key, MTD.Read(f.Bytes)); } else { MtdDict[key] = MTD.Read(f.Bytes); } } } }
private void Awake() { if (_instance == null) { _instance = this; transform.SetParent(null); DontDestroyOnLoad(this); } else { if (_instance != this) { if (GetComponents <Component>().Length <= 2) { Destroy(gameObject); } else { Destroy(this); } } } }
public FlverSubmeshRenderer(Model parent, FLVER flvr, FLVER.Mesh mesh) { Parent = parent; var shortMaterialName = MiscUtil.GetFileNameWithoutDirectoryOrExtension(flvr.Materials[mesh.MaterialIndex].MTD); if (shortMaterialName.EndsWith("_Alp") || shortMaterialName.Contains("_Edge") || shortMaterialName.Contains("_Decal") || shortMaterialName.Contains("_Cloth") || shortMaterialName.Contains("_al") || shortMaterialName.Contains("BlendOpacity")) { DrawStep = GFXDrawStep.AlphaEdge; } else { DrawStep = GFXDrawStep.Opaque; } bool hasLightmap = false; foreach (var matParam in flvr.Materials[mesh.MaterialIndex].Textures) { var paramNameCheck = matParam.Type.ToUpper(); // DS3/BB if (paramNameCheck == "G_DIFFUSETEXTURE") { TexNameDiffuse = matParam.Path; } else if (paramNameCheck == "G_SPECULARTEXTURE") { TexNameSpecular = matParam.Path; } else if (paramNameCheck == "G_BUMPMAPTEXTURE") { TexNameNormal = matParam.Path; } else if (paramNameCheck == "G_DOLTEXTURE1") { TexNameDOL1 = matParam.Path; hasLightmap = true; } else if (paramNameCheck == "G_DOLTEXTURE2") { TexNameDOL2 = matParam.Path; } // DS1 params else if (paramNameCheck == "G_DIFFUSE") { TexNameDiffuse = matParam.Path; } else if (paramNameCheck == "G_SPECULAR") { TexNameSpecular = matParam.Path; } else if (paramNameCheck == "G_BUMPMAP") { TexNameNormal = matParam.Path; } else if (paramNameCheck == "G_LIGHTMAP") { TexNameDOL1 = matParam.Path; hasLightmap = true; } // Alternate material params that work as diffuse } // MTD lookup MTD mtd = InterrootLoader.GetMTD(flvr.Materials[mesh.MaterialIndex].MTD); var MeshVertices = new VertexPositionColorNormalTangentTexture[mesh.Vertices.Count]; for (int i = 0; i < mesh.Vertices.Count; i++) { var vert = mesh.Vertices[i]; MeshVertices[i] = new VertexPositionColorNormalTangentTexture(); MeshVertices[i].Position = new Vector3(vert.Position.X, vert.Position.Y, vert.Position.Z); if (vert.Normal != null && vert.Tangents != null && vert.Tangents.Count > 0) { MeshVertices[i].Normal = Vector3.Normalize(new Vector3(vert.Normal.X, vert.Normal.Y, vert.Normal.Z)); MeshVertices[i].Tangent = Vector3.Normalize(new Vector3(vert.Tangents[0].X, vert.Tangents[0].Y, vert.Tangents[0].Z)); MeshVertices[i].Binormal = Vector3.Cross(Vector3.Normalize(MeshVertices[i].Normal), Vector3.Normalize(MeshVertices[i].Tangent)) * vert.Tangents[0].W; } if (vert.UVs.Count > 0) { MeshVertices[i].TextureCoordinate = new Vector2(vert.UVs[0].X, vert.UVs[0].Y); if (vert.UVs.Count > 1 && hasLightmap) { if (mtd == null) { // Really stupid heuristic to determine light map UVs without reading mtd files or something if (vert.UVs.Count > 2 && flvr.Materials[mesh.MaterialIndex].Textures.Count > 11) { MeshVertices[i].TextureCoordinate2 = new Vector2(vert.UVs[2].X, vert.UVs[2].Y); } else { MeshVertices[i].TextureCoordinate2 = new Vector2(vert.UVs[1].X, vert.UVs[1].Y); } } else { // Better heuristic with MTDs int uvindex = mtd.Textures.Find(tex => tex.Type.ToUpper() == "G_LIGHTMAP" || tex.Type.ToUpper() == "G_DOLTEXTURE1").UVNumber; int uvoffset = 1; for (int j = 1; j < uvindex; j++) { if (!mtd.Textures.Any(t => (t.UVNumber == j))) { uvoffset++; } } uvindex -= uvoffset; if (vert.UVs.Count > uvindex) { MeshVertices[i].TextureCoordinate2 = new Vector2(vert.UVs[uvindex].X, vert.UVs[uvindex].Y); } else { MeshVertices[i].TextureCoordinate2 = new Vector2(vert.UVs[1].X, vert.UVs[1].Y); } } } else { MeshVertices[i].TextureCoordinate2 = Vector2.Zero; } } else { MeshVertices[i].TextureCoordinate = Vector2.Zero; MeshVertices[i].TextureCoordinate2 = Vector2.Zero; } } VertexCount = MeshVertices.Length; MeshFacesets = new List <FlverSubmeshRendererFaceSet>(); foreach (var faceset in mesh.FaceSets) { bool is32bit = faceset.IndexSize == 0x20; var newFaceSet = new FlverSubmeshRendererFaceSet() { BackfaceCulling = faceset.CullBackfaces, IsTriangleStrip = faceset.TriangleStrip, IndexBuffer = new IndexBuffer( GFX.Device, is32bit ? IndexElementSize.ThirtyTwoBits : IndexElementSize.SixteenBits, faceset.Vertices.Length, BufferUsage.WriteOnly), IndexCount = faceset.Vertices.Length, }; if (faceset.Flags == FLVER.FaceSet.FSFlags.LodLevel1) { newFaceSet.LOD = 1; HasNoLODs = false; } else if (faceset.Flags == FLVER.FaceSet.FSFlags.LodLevel2) { newFaceSet.LOD = 2; HasNoLODs = false; } if (is32bit) { newFaceSet.IndexBuffer.SetData(faceset.Vertices); } else { newFaceSet.IndexBuffer.SetData(faceset.Vertices.Select(x => (ushort)x).ToArray()); } MeshFacesets.Add(newFaceSet); } Bounds = BoundingBox.CreateFromPoints(MeshVertices.Select(x => x.Position)); VertBuffer = new VertexBuffer(GFX.Device, typeof(VertexPositionColorNormalTangentTexture), MeshVertices.Length, BufferUsage.WriteOnly); VertBuffer.SetData(MeshVertices); VertBufferBinding = new VertexBufferBinding(VertBuffer, 0, 0); TryToLoadTextures(); }
public MTDWrapper(MTD mtd, string name) { MTD = mtd; Name = name; }
private void LoadFile(string path, bool silent = false) { statusStripMTDPath.Text = ""; if (!File.Exists(path)) { ShowError($"File not found:\r\n{path}", silent); return; } string filename = Path.GetFileName(path); string extension = SFUtil.GetRealExtension(filename); cmbMTD.Enabled = false; cmbMTD.Items.Clear(); mtdBnd = null; mtd = null; var mtdItems = new List <MTDWrapper>(); try { if (MTD.Is(path)) { mtdItems.Add(new MTDWrapper(MTD.Read(path), filename)); } else if (BND3.Is(path)) { mtdBnd = BND3.Read(path); foreach (BinderFile file in mtdBnd.Files) { if (MTD.Is(file.Bytes)) { mtdItems.Add(new MTDWrapper(MTD.Read(file.Bytes), file.Name)); } } } else if (BND4.Is(path)) { mtdBnd = BND4.Read(path); foreach (BinderFile file in mtdBnd.Files) { if (MTD.Is(file.Bytes)) { mtdItems.Add(new MTDWrapper(MTD.Read(file.Bytes), file.Name)); } } } else { ShowError($"Unrecognized file type:\r\n{path}", silent); return; } } catch (Exception ex) { ShowError($"Failed to load file:\r\n{path}\r\n{ex}", silent); return; } statusStripMTDPath.Text = path; mtdItems.Sort((i1, i2) => i1.Name.CompareTo(i2.Name)); cmbMTD.Items.AddRange(mtdItems.ToArray()); cmbMTD.SelectedIndex = 0; if (mtdItems.Count > 1) { cmbMTD.Enabled = true; } }