public void DepthPrepass(RenderState rstate, VMeshData data, ushort startVertex, Matrix4 world, MaterialAnimCollection mc) { if (Material == null) { return; } if (Material.Render.IsTransparent) { return; } if (lastmc != mc) { if (mc != null) { mc.Anims.TryGetValue(Material.Name, out ma); lastmc = mc; } else { ma = null; } } Material.Render.MaterialAnim = ma; Material.Render.World = world; Material.Render.ApplyDepthPrepass(rstate); data.VertexBuffer.Draw(PrimitiveTypes.TriangleList, startVertex + StartVertex, TriangleStart, primitiveCount); }
public override void Replace(string FileName) { string ext = Utils.GetExtension(FileName); if (ext == ".bfmaa") { MaterialAnim.Import(FileName); MaterialAnim.Name = Text; LoadAnim(MaterialAnim); } else if (ext == ".yaml") { MaterialAnim = YamlFmaa.FromYaml(FileName); MaterialAnim.Name = Text; LoadAnim(MaterialAnim); } else if (ext == ".gif" || ext == ".png" || ext == ".apng") { BNTX bntx = PluginRuntime.bntxContainers[0]; GifToTexturePatternAnimation anim = new GifToTexturePatternAnimation(FileName, bntx, this); MaterialAnim.Name = Text; LoadAnim(MaterialAnim); } UpdateEditor(); }
public static MaterialAnim FromJson(string json) { MaterialAnim anim = new MaterialAnim(); FromJson(anim, json); return(anim); }
public static MaterialAnim FromStruct(MaterialAnimHelper matAnim) { MaterialAnim anim = new MaterialAnim(); FromStruct(anim, matAnim); return(anim); }
public unsafe void DrawImmediate(int level, ResourceManager res, RenderState renderState, Matrix4x4 world, ref Lighting lights, MaterialAnimCollection mc, Material overrideMat = null) { if (Levels == null || Levels.Length < level) { return; } var l = Levels[level]; if (l == null) { return; } Mat4Source src; Mat4Source world2; src.World = world; Matrix4x4.Invert(world, out src.Normal); src.Normal = Matrix4x4.Transpose(src.Normal); for (int i = 0; i < l.Length; i++) { var dc = l[i]; MaterialAnim ma = null; Material mat = overrideMat; if (mat == null) { mat = dc.GetMaterial(res); if (mat != null) { ma = dc.GetMaterialAnim(mc); } else { mat = res.DefaultMaterial; } } WorldMatrixHandle handle; handle.Source = (Matrix4x4 *)&src; handle.ID = ulong.MaxValue; if (dc.HasScale) { world2.World = dc.Scale * world; Matrix4x4.Invert(world2.World, out world2.Normal); world2.Normal = Matrix4x4.Transpose(world2.Normal); handle.Source = (Matrix4x4 *)&world2; handle.ID = ulong.MaxValue; } Matrix4x4 tr = world; if (dc.HasScale) { tr = dc.Scale * world; } mat.Render.World = handle; mat.Render.MaterialAnim = ma; mat.Render.Use(renderState, dc.Buffer.VertexType, ref lights); dc.Buffer.Draw(PrimitiveTypes.TriangleList, dc.BaseVertex, dc.StartIndex, dc.PrimitiveCount); } }
public void DrawBuffer(int level, ResourceManager res, CommandBuffer buffer, Matrix4x4 world, ref Lighting lights, MaterialAnimCollection mc, Material overrideMat = null) { if (Levels == null || Levels.Length <= level) { return; } var l = Levels[level]; if (l == null) { return; } WorldMatrixHandle wm = buffer.WorldBuffer.SubmitMatrix(ref world); for (int i = 0; i < l.Length; i++) { var dc = l[i]; MaterialAnim ma = null; Material mat = overrideMat; if (mat == null) { mat = dc.GetMaterial(res); if (mat != null) { ma = dc.GetMaterialAnim(mc); } else { mat = res.DefaultMaterial; } } float z = 0; if (mat.Render.IsTransparent) { z = RenderHelpers.GetZ(world, mat.Render.Camera.Position, Center); } WorldMatrixHandle worldHandle = wm; if (dc.HasScale) { Matrix4x4 tr = dc.Scale * world; worldHandle = buffer.WorldBuffer.SubmitMatrix(ref tr); } buffer.AddCommand(mat.Render, ma, worldHandle, lights, dc.Buffer, PrimitiveTypes.TriangleList, dc.BaseVertex, dc.StartIndex, dc.PrimitiveCount, SortLayers.OBJECT, z ); } }
public static string ToJson(MaterialAnim anim) { MaterialAnimStuct animConv = new MaterialAnimStuct(); animConv.Name = anim.Name; animConv.Path = anim.Path; animConv.MaterialAnims = new List <MaterialAnimGroupStruct>(); animConv.FrameCount = anim.FrameCount; animConv.Loop = anim.Flags.HasFlag(MaterialAnim.MaterialAnimFlags.Looping); animConv.Baked = anim.Flags.HasFlag(MaterialAnim.MaterialAnimFlags.BakedCurve); foreach (var matAnim in anim.MaterialAnimDataList) { MaterialAnimGroupStruct matAnimConv = new MaterialAnimGroupStruct(); animConv.MaterialAnims.Add(matAnimConv); matAnimConv.Curves = new List <CurveAnimHelper>(); matAnimConv.Name = matAnim.Name; if (matAnim.Constants != null) { matAnimConv.Constants = matAnim.Constants.ToList(); } if (matAnim.BaseDataList != null) { matAnimConv.BaseDataList = matAnim.BaseDataList.ToList(); } if (matAnim.ParamAnimInfos != null) { matAnimConv.ParameterInfos = matAnim.ParamAnimInfos.ToList(); } if (matAnim.PatternAnimInfos != null) { matAnimConv.PatternAnimInfos = matAnim.PatternAnimInfos.ToList(); } foreach (var curve in matAnim.Curves) { string target = curve.AnimDataOffset.ToString(); var convCurve = CurveAnimHelper.FromCurve(curve, target, false); matAnimConv.Curves.Add(convCurve); } } foreach (var param in anim.UserData.Values) { animConv.UserData.Add($"{param.Type}|{param.Name}", param.GetData()); } JsonConvert.DefaultSettings = () => { var settings = new JsonSerializerSettings(); return(settings); }; return(JsonConvert.SerializeObject(animConv, Formatting.Indented)); }
public void DrawBuffer(CommandBuffer buffer, VMeshData data, int vertexOffset, ushort startVertex, int startIndex, Matrix4 world, ref Lighting light, MaterialAnimCollection mc, Material overrideMat = null) { if (MaterialCrc == 0) { return; } var mat = Material; if (mat == null) { mat = defaultMaterial; } if (overrideMat != null) { mat = overrideMat; } if (lastmc != mc) { if (mc != null) { mc.Anims.TryGetValue(mat.Name, out ma); lastmc = mc; } else { ma = null; } } float z = 0; if (mat.Render.IsTransparent) { z = RenderHelpers.GetZ(world, mat.Render.Camera.Position, CalculateAvg(data, startVertex)); } buffer.AddCommand( mat.Render, ma, world, light, data.VertexBuffer, PrimitiveTypes.TriangleList, startVertex + vertexOffset + StartVertex, startIndex + TriangleStart, primitiveCount, SortLayers.OBJECT, z ); }
public static void Pat02Ftxp(MaterialAnim matAnim, string FileName) { PAT0Node pat0 = new PAT0Node(); matAnim.FrameCount = pat0.FrameCount; matAnim.Name = pat0.Name; matAnim.Path = pat0.OriginalPath; matAnim.Loop = pat0.Loop; foreach (var entry in pat0.Children) { var Material = (PAT0EntryNode)entry; } }
public BFRES_MTA(MaterialAnim vis) { ImageKey = "image"; SelectedImageKey = "image"; Text = vis.Name; FrameCount = (uint)vis.FrameCount; foreach (MaterialAnimData matanim in vis.MaterialAnimDataList) { MatAnimEntry mat = new MatAnimEntry(); FMAANode matnode = new FMAANode(matanim); mat.Text = matanim.Name; for (int Frame = 0; Frame < vis.FrameCount; Frame++) { int CurTrack = 0; foreach (FMAATrack track in matnode.tracks) { MatAnimData md = new MatAnimData(); float value; if (matanim.Curves[CurTrack].CurveType == AnimCurveType.Cubic) { FMAAKey left = track.GetLeft(Frame); FMAAKey right = track.GetRight(Frame); value = Animation.Hermite(Frame, left.frame, right.frame, 0, 0, left.unk1, right.unk1); md.keys.Add(value); } mat.matCurves.Add(md); CurTrack++; } } matEntries.Add(mat); } }
public void AddCommand(RenderMaterial material, MaterialAnim anim, WorldMatrixHandle world, Lighting lights, VertexBuffer buffer, PrimitiveTypes primitive, int baseVertex, int start, int count, int layer, float z = 0, DfmSkinning skinning = null) { if (material.IsTransparent) { Transparents[transparentCommand++] = new RenderCommand() { Source = material, MaterialAnim = anim, Lights = lights, Buffer = buffer, BaseVertex = baseVertex, Start = start, Count = count, Primitive = primitive, CmdType = RenderCmdType.Material, World = world, SortLayer = layer, Z = z }; } else { if (skinning != null) { material.Bones = BonesBuffer; material.BufferOffset = skinning.BufferOffset; } else { material.Bones = null; } material.MaterialAnim = anim; material.World = world; material.Use(rstate, buffer.VertexType, ref lights); buffer.Draw(primitive, baseVertex, start, count); if (material.DoubleSided) { material.FlipNormals = true; material.UpdateFlipNormals(); rstate.CullFace = CullFaces.Front; buffer.Draw(primitive, baseVertex, start, count); rstate.CullFace = CullFaces.Back; material.FlipNormals = false; } } }
public void AddCommand(RenderMaterial material, MaterialAnim anim, WorldMatrixHandle world, Lighting lights, VertexBuffer buffer, PrimitiveTypes primitive, int baseVertex, int start, int count, int layer, float z = 0, DfmSkinning skinning = null) { if (material.IsTransparent) { Transparents[transparentCommand++] = new RenderCommand() { Key = RenderCommand.MakeKey(RenderType.Transparent, material.Key, layer, z, 0), Source = material, MaterialAnim = anim, Lights = lights, Buffer = buffer, BaseVertex = baseVertex, Start = start, Count = count, Primitive = primitive, CmdType = RenderCmdType.Material, World = world, }; } else { if (skinning != null) { material.Bones = BonesBuffer; material.BufferOffset = skinning.BufferOffset; } else { material.Bones = null; } material.MaterialAnim = anim; material.World = world; material.Use(rstate, buffer.VertexType, ref lights); if (material.DoubleSided) { rstate.Cull = false; } buffer.Draw(primitive, baseVertex, start, count); if (material.DoubleSided) { rstate.Cull = true; } } }
public static void FromJson(MaterialAnim anim, string json) { JsonConvert.DefaultSettings = () => { var settings = new JsonSerializerSettings(); return(settings); }; var animJson = JsonConvert.DeserializeObject <MaterialAnimStuct>(json); anim.Name = animJson.Name; anim.MaterialAnimDataList = new List <MaterialAnimData>(); anim.UserData = UserDataConvert.Convert(animJson.UserData); anim.FrameCount = animJson.FrameCount; if (animJson.Loop) { anim.Flags |= MaterialAnim.MaterialAnimFlags.Looping; } if (animJson.Baked) { anim.Flags |= MaterialAnim.MaterialAnimFlags.BakedCurve; } foreach (var matAnimJson in animJson.MaterialAnims) { MaterialAnimData matAnim = new MaterialAnimData(); anim.MaterialAnimDataList.Add(matAnim); matAnim.Name = matAnimJson.Name; matAnim.PatternAnimInfos = matAnimJson.PatternAnimInfos; matAnim.ParamAnimInfos = matAnimJson.ParameterInfos; matAnim.Constants = matAnimJson.Constants; matAnim.BaseDataList = matAnimJson.BaseDataList.ToArray(); foreach (var curveJson in matAnimJson.Curves) { var target = uint.Parse(curveJson.Target); var curve = CurveAnimHelper.GenerateCurve(curveJson, (uint)target, false); matAnim.Curves.Add(curve); } } }
public void Draw(RenderState rstate, VertexBuffer buff, ushort startVertex, Matrix4 world, Lighting light, MaterialAnimCollection mc) { if (lastmc != mc) { if (mc != null) { mc.Anims.TryGetValue(Material.Name, out ma); lastmc = mc; } else { ma = null; } } Material.Render.MaterialAnim = ma; Material.Render.World = world; Material.Render.Use(rstate, buff.VertexType, light); buff.Draw(PrimitiveTypes.TriangleList, startVertex + StartVertex, TriangleStart, primitiveCount); }
public void DepthPrepass(RenderState rstate, VMeshData data, int startVertex, int startIndex, Matrix4 world, MaterialAnimCollection mc) { if (MaterialCrc == 0) { return; } var m = Material; if (m == null) { m = materialLibrary.FindMaterial(0); } if (m == null) { return; } if (m.Render.IsTransparent) { return; } if (m.Render.DoubleSided) { return; //TODO: Fix depth prepass for double-sided } if (lastmc != mc) { if (mc != null) { mc.Anims.TryGetValue(m.Name, out ma); lastmc = mc; } else { ma = null; } } m.Render.MaterialAnim = ma; m.Render.World = world; m.Render.ApplyDepthPrepass(rstate); data.VertexBuffer.Draw(PrimitiveTypes.TriangleList, startVertex + StartVertex, startIndex + TriangleStart, primitiveCount); }
public static string ToYaml(string Name, MaterialAnim MatAnim, FMAA.AnimationType animType) { var serializerSettings = new SerializerSettings() { // EmitTags = false }; serializerSettings.DefaultStyle = YamlStyle.Any; serializerSettings.ComparerForKeySorting = null; serializerSettings.RegisterTagMapping("AnimConfig", typeof(AnimConfig)); var config = new AnimConfig(); config.ToYaml(MatAnim, animType); var serializer = new Serializer(serializerSettings); string yaml = serializer.Serialize(config, typeof(AnimConfig)); return(yaml); }
public void DrawImmediate(int level, ResourceManager res, RenderState renderState, Matrix4x4 world, ref Lighting lights, MaterialAnimCollection mc, Material overrideMat = null) { if (Levels == null || Levels.Length < level) { return; } var l = Levels[level]; if (l == null) { return; } for (int i = 0; i < l.Length; i++) { var dc = l[i]; MaterialAnim ma = null; Material mat = overrideMat; if (mat == null) { mat = dc.GetMaterial(res); if (mat != null) { ma = dc.GetMaterialAnim(mc); } else { mat = res.DefaultMaterial; } } Matrix4x4 tr = world; if (dc.HasScale) { tr = dc.Scale * world; } mat.Render.World = tr; mat.Render.MaterialAnim = ma; mat.Render.Use(renderState, dc.Buffer.VertexType, ref lights); dc.Buffer.Draw(PrimitiveTypes.TriangleList, dc.BaseVertex, dc.StartIndex, dc.PrimitiveCount); } }
public void DrawBuffer(CommandBuffer buffer, VMeshData data, ushort startVertex, Matrix4 world, Lighting light, MaterialAnimCollection mc) { if (Material == null) { return; } if (lastmc != mc) { if (mc != null) { mc.Anims.TryGetValue(Material.Name, out ma); lastmc = mc; } else { ma = null; } } float z = 0; if (Material.Render.IsTransparent) { z = RenderHelpers.GetZ(world, Material.Render.Camera.Position, CalculateAvg(data, startVertex)); } buffer.AddCommand( Material.Render, ma, world, light, data.VertexBuffer, PrimitiveTypes.TriangleList, startVertex + StartVertex, TriangleStart, primitiveCount, SortLayers.OBJECT, z ); }
public void AddCommand(RenderMaterial material, MaterialAnim anim, Matrix4 world, Lighting lights, VertexBuffer buffer, PrimitiveTypes primitive, int baseVertex, int start, int count, int layer, float z = 0) { if (material.IsTransparent) { Transparents[transparentCommand++] = new RenderCommand() { Source = material, MaterialAnim = anim, Lights = lights, Buffer = buffer, BaseVertex = baseVertex, Start = start, Count = count, Primitive = primitive, CmdType = RenderCmdType.Material, World = world, SortLayer = layer, Z = z }; } else { Commands[currentCommand++] = new RenderCommand() { Source = material, MaterialAnim = anim, Lights = lights, Buffer = buffer, BaseVertex = baseVertex, Start = start, Count = count, Primitive = primitive, CmdType = RenderCmdType.Material, World = world, }; } }
private void WriteMaterialAnimations(MaterialAnim anim) { if (anim.BindIndices?.Length > 0) { Align(8); WriteOffset(anim.PosBindIndicesOffset); Write(anim.BindIndices); } if (anim.MaterialAnimDataList.Count > 0) { Align(8); WriteOffset(anim.PosMatAnimDataOffset); for (int i = 0; i < anim.MaterialAnimDataList.Count; i++) { anim.MaterialAnimDataList[i].Save(this, anim.signature); } } foreach (MaterialAnimData mat in anim.MaterialAnimDataList) { if (mat.ParamAnimInfos.Count > 0) { Align(4); WriteOffset(mat.PosParamInfoOffset); for (int i = 0; i < mat.ParamAnimInfos.Count; i++) { ((IResData)mat.ParamAnimInfos[i]).Save(this); } } if (mat.PatternAnimInfos.Count > 0) { Align(4); WriteOffset(mat.PosTexPatInfoOffset); for (int i = 0; i < mat.PatternAnimInfos.Count; i++) { ((IResData)mat.PatternAnimInfos[i]).Save(this); } } if (mat.BaseDataList != null && mat.BaseDataList.Length > 0) { Align(4); WriteOffset(mat.PosConstantsOffset); this.Write(mat.BaseDataList); } if (mat.Constants != null && mat.Constants.Count > 0) { Align(4); WriteOffset(mat.PosConstantsOffset); this.Write(mat.Constants); } if (mat.Curves.Count > 0) { Align(4); WriteOffset(mat.PosCurvesOffset); for (int i = 0; i < mat.Curves.Count; i++) { mat.Curves[i].SaveEntryBlock = false; ((IResData)mat.Curves[i]).Save(this); } for (int i = 0; i < mat.Curves.Count; i++) { if (mat.Curves[i].Frames.Length > 0) { Align(4); WriteOffset(mat.Curves[i].PosFrameOffset); mat.Curves[i].SaveFrames(this); } if (mat.Curves[i].Keys.Length > 0) { Align(4); WriteOffset(mat.Curves[i].PosKeyDataOffset); mat.Curves[i].SaveKeyData(this); } } } } if (anim.TextureNames?.Count > 0) { Align(4); WriteOffset(anim.PosTextureNamesOffset); if (ResFile.Version >= 0x03040002) { ((IResData)anim.TextureNames).Save(this); } else { foreach (var texRef in anim.TextureNames.Values) { ((IResData)texRef).Save(this); } } } if (anim.UserData.Count > 0) { Align(4); WriteOffset(anim.PosUserDataOffset); ((IResData)anim.UserData).Save(this); } }
public BfresMaterialAnim(MaterialAnim anim, string name) { ModelName = name; CanPlay = false; //Default all animations to not play unless toggled in list Reload(anim); }
public void Reload(MaterialAnim anim) { Name = anim.Name; FrameCount = anim.FrameCount; FrameRate = 60.0f; Loop = anim.Loop; if (anim.TextureNames != null) { TextureList = anim.TextureNames.Keys.ToList(); } if (anim.MaterialAnimDataList == null) { return; } AnimGroups.Clear(); foreach (var matAnim in anim.MaterialAnimDataList) { var group = new MaterialAnimGroup(); AnimGroups.Add(group); group.Name = matAnim.Name; //Get the material animation's texture pattern animation lists //Each sampler has their own info for (int i = 0; i < matAnim.PatternAnimInfos.Count; i++) { var patternInfo = matAnim.PatternAnimInfos[i]; //Get the curve index for animated indices int curveIndex = patternInfo.CurveIndex; //Get the base index for starting values int textureBaseIndex = matAnim.BaseDataList.Length > i ? matAnim.BaseDataList[i] : 0; //Make a new sampler track using step interpolation var samplerTrack = new SamplerTrack(); samplerTrack.InterpolationType = STInterpoaltionType.Step; samplerTrack.Sampler = patternInfo.Name; group.Tracks.Add(samplerTrack); if (curveIndex != -1) { BfresAnimations.GenerateKeys(samplerTrack, matAnim.Curves[curveIndex], true); } else //Use the base data and make a constant key { samplerTrack.KeyFrames.Add(new STKeyFrame(0, textureBaseIndex)); } } //Get the list of animated parameters for (int i = 0; i < matAnim.ParamAnimInfos.Count; i++) { ParamAnimGroup paramGroup = new ParamAnimGroup(); paramGroup.Name = matAnim.ParamAnimInfos[i].Name; group.SubAnimGroups.Add(paramGroup); var paramInfo = matAnim.ParamAnimInfos[i]; //Params have int and float curves int curveIndex = paramInfo.BeginCurve; int constantIndex = paramInfo.BeginConstant; int numFloats = paramInfo.FloatCurveCount; int numInts = paramInfo.IntCurveCount; int numConstants = paramInfo.ConstantCount; //Each constant and curve get's their own value using a value offset for (int j = 0; j < numConstants; j++) { var constant = matAnim.Constants[constantIndex + j]; float value = constant.Value; //A bit hacky, convert int32 types by value range SRT modes use if (constant.Value.Int32 > 0 && constant.Value.Int32 < 6) { value = constant.Value.Int32; } paramGroup.Tracks.Add(new ParamTrack() { Name = constant.AnimDataOffset.ToString("X"), ValueOffset = constant.AnimDataOffset, //Not the best way, but 4 is typically the stride size for each value ChannelIndex = (int)(constant.AnimDataOffset / 4), KeyFrames = new List <STKeyFrame>() { new STKeyFrame(0, value) }, InterpolationType = STInterpoaltionType.Constant, }); } //Loop through all int and float curve values for (int j = 0; j < numInts + numFloats; j++) { var curve = matAnim.Curves[curveIndex + j]; var paramTrack = new ParamTrack() { Name = curve.AnimDataOffset.ToString("X") }; paramTrack.ValueOffset = curve.AnimDataOffset; //Not the best way, but 4 is typically the stride size for each value paramTrack.ChannelIndex = (int)(curve.AnimDataOffset / 4); paramGroup.Tracks.Add(paramTrack); BfresAnimations.GenerateKeys(paramTrack, curve); } } } }
public static void FromStruct(MaterialAnim anim, MaterialAnimHelper animJson) { anim.TextureNames = new ResDict <TextureRef>(); foreach (var tex in animJson.TextureList) { anim.TextureNames.Add(tex, new TextureRef() { Name = tex }); } anim.Name = animJson.Name; anim.Baked = animJson.Baked; anim.Loop = animJson.Loop; anim.FrameCount = animJson.FrameCount; anim.Baked = animJson.Baked; anim.MaterialAnimDataList = new List <MaterialAnimData>(); anim.BindIndices = new ushort[animJson.MaterialAnims.Count]; for (int i = 0; i < anim.BindIndices.Length; i++) { anim.BindIndices[i] = 65535; } anim.UserData = UserDataConvert.Convert(animJson.UserData); foreach (var matAnimJson in animJson.MaterialAnims) { MaterialAnimData matAnim = new MaterialAnimData(); anim.MaterialAnimDataList.Add(matAnim); matAnim.Name = matAnimJson.Name; matAnim.ParamAnimInfos = new List <ParamAnimInfo>(); matAnim.PatternAnimInfos = new List <PatternAnimInfo>(); matAnim.ShaderParamCurveIndex = 0; List <ushort> texturePatternBase = new List <ushort>(); foreach (var samplerInfo in matAnimJson.Samplers) { var info = new PatternAnimInfo(); info.Name = samplerInfo.Name; info.CurveIndex = -1; if (samplerInfo.Curve != null) { info.CurveIndex = (short)matAnim.Curves.Count; } matAnim.PatternAnimInfos.Add(info); texturePatternBase.Add(samplerInfo.Constant); if (samplerInfo.Curve != null) { matAnim.Curves.Add(CurveAnimHelper.GenerateCurve(samplerInfo.Curve, 0, false)); } } ushort curveIndex = 0; ushort constantIndex = 0; foreach (var paramInfo in matAnimJson.Params) { var info = new ParamAnimInfo(); info.BeginCurve = curveIndex; info.BeginConstant = constantIndex; info.ConstantCount = (ushort)paramInfo.Constants.Count; info.FloatCurveCount = (ushort)paramInfo.Curves.Count(); info.IntCurveCount = 0; info.Name = paramInfo.Name; matAnim.ParamAnimInfos.Add(info); if (paramInfo.Curves.Count > 0) { matAnim.VisualConstantIndex = 0; } foreach (var curveJson in paramInfo.Curves) { uint target = uint.Parse(curveJson.Target); matAnim.Curves.Add(CurveAnimHelper.GenerateCurve(curveJson, target, false)); } foreach (var constJson in paramInfo.Constants) { matAnim.Constants.Add(constJson); } curveIndex += (ushort)matAnim.Curves.Count; constantIndex += (ushort)matAnim.Constants.Count; } matAnim.BaseDataList = texturePatternBase.ToArray(); } }
public MaterialAnim FromYaml() { MaterialAnim matAnim = new MaterialAnim(); matAnim.Name = Name; matAnim.Path = Path; matAnim.Loop = Loop; matAnim.FrameCount = FrameCount; matAnim.TextureNames = GenerateTextureList(); matAnim.BindIndices = new ushort[MaterialAnimConfigs.Count]; for (int i = 0; i < matAnim.BindIndices.Length; i++) { matAnim.BindIndices[i] = ushort.MaxValue; } int ShaderParamCurveIndex = 0; int TexturePatternCurveIndex = 0; Console.WriteLine("MaterialAnimConfigs " + MaterialAnimConfigs.Count); foreach (var matCfg in MaterialAnimConfigs) { var matAnimData = new MaterialAnimData(); matAnimData.Name = matCfg.Name; matAnimData.Constants = new List <AnimConstant>(); matAnimData.Curves = new List <AnimCurve>(); matAnimData.TexturePatternAnimInfos = new List <TexturePatternAnimInfo>(); matAnimData.ParamAnimInfos = new List <ParamAnimInfo>(); matAnimData.BeginVisalConstantIndex = -1; matAnimData.ShaderParamCurveIndex = -1; matAnimData.VisualConstantIndex = -1; matAnimData.TexturePatternCurveIndex = -1; matAnimData.VisalCurveIndex = -1; matAnim.MaterialAnimDataList.Add(matAnimData); ushort CurveIndex = 0; ushort BeginConstantIndex = 0; foreach (var texturePatternCfg in matCfg.TexturePatternInfos) { TexturePatternAnimInfo patternInfo = new TexturePatternAnimInfo(); patternInfo.Name = texturePatternCfg.Name; matAnimData.TexturePatternAnimInfos.Add(patternInfo); if (texturePatternCfg.IsConstant && texturePatternCfg.ConstantValue != null) { patternInfo.BeginConstant = BeginConstantIndex++; AnimConstant constant = new AnimConstant(); constant.AnimDataOffset = 0; constant.Value = matAnim.TextureNames.IndexOf(texturePatternCfg.ConstantValue.Texture); matAnimData.Constants.Add(constant); matAnimData.VisualConstantIndex = 0; matAnimData.BeginVisalConstantIndex = 0; } else if (texturePatternCfg.CurveData != null) { patternInfo.CurveIndex = CurveIndex++; matAnimData.TexturePatternCurveIndex = TexturePatternCurveIndex; matAnimData.BeginVisalConstantIndex = 0; AnimCurve curve = new AnimCurve(); matAnimData.Curves.Add(curve); curve.Offset = 0; curve.AnimDataOffset = 0; curve.Scale = 1; curve.CurveType = AnimCurveType.StepInt; curve.StartFrame = 0; int FrameCount = texturePatternCfg.CurveData.KeyFrames.Count; curve.Frames = new float[FrameCount]; curve.Keys = new float[FrameCount, 1]; int MaxFrame = 0; int MaxIndex = 0; int i = 0; foreach (var KeyFrame in texturePatternCfg.CurveData.KeyFrames) { int Index = matAnim.TextureNames.IndexOf(KeyFrame.Value); Console.WriteLine($"{Index} {KeyFrame.Value}"); curve.Frames[i] = KeyFrame.Key; curve.Keys[i, 0] = Index; MaxFrame = Math.Max(MaxIndex, KeyFrame.Key); MaxIndex = Math.Max(MaxIndex, Index); i++; } curve.EndFrame = curve.Frames.Max(); if (curve.Keys.Length > 1) { curve.Delta = curve.Keys[curve.Keys.Length - 1, 0] - curve.Keys[0, 0]; } if (MaxFrame < byte.MaxValue) { curve.FrameType = AnimCurveFrameType.Byte; } else if (MaxFrame < ushort.MaxValue) { curve.FrameType = AnimCurveFrameType.Decimal10x5; } else { curve.FrameType = AnimCurveFrameType.Single; } if (MaxIndex < byte.MaxValue) { curve.KeyType = AnimCurveKeyType.SByte; } else if (MaxIndex < ushort.MaxValue) { curve.KeyType = AnimCurveKeyType.Int16; } else { curve.KeyType = AnimCurveKeyType.Single; } } } foreach (var paramCfg in matCfg.ParamInfos) { ParamAnimInfo paramInfo = new ParamAnimInfo(); paramInfo.Name = paramCfg.Name; matAnimData.ParamAnimInfos.Add(paramInfo); if (paramCfg.Constants != null && paramCfg.Constants.Count > 0) { paramInfo.BeginConstant = BeginConstantIndex; paramInfo.ConstantCount = (ushort)paramCfg.Constants.Count; BeginConstantIndex += (ushort)paramCfg.Constants.Count; foreach (var constantCfg in paramCfg.Constants) { AnimConstant constant = new AnimConstant(); constant.AnimDataOffset = ConvertParamOffset(constantCfg.Offset); constant.Value = constantCfg.Value; matAnimData.Constants.Add(constant); } } if (paramCfg.CurveData != null && paramCfg.CurveData.Count > 0) { matAnimData.ShaderParamCurveIndex = ShaderParamCurveIndex; paramInfo.BeginCurve = CurveIndex; paramInfo.FloatCurveCount = (ushort)paramCfg.CurveData.Count; CurveIndex += (ushort)paramCfg.CurveData.Count; foreach (var curveCfg in paramCfg.CurveData) { AnimCurve curve = new AnimCurve(); matAnimData.Curves.Add(curve); curve.Offset = 0; curve.AnimDataOffset = ConvertParamOffset(curveCfg.Offset); curve.Scale = 1; curve.CurveType = AnimCurveType.Linear; curve.StartFrame = 0; int MaxFrame = 0; float MaxValue = 0; int FrameCount = curveCfg.KeyFrames.Count; curve.Frames = new float[FrameCount]; curve.Keys = new float[FrameCount, 2]; int i = 0; var values = curveCfg.KeyFrames.Values.ToList(); foreach (var KeyFrame in curveCfg.KeyFrames) { curve.Frames[i] = KeyFrame.Key; curve.Keys[i, 0] = KeyFrame.Value; //Calculate delta float Delta = 0; if (i < values.Count - 1) { Delta = values[i + 1] - values[i]; } curve.Keys[i, 1] = Delta; MaxFrame = Math.Max(MaxFrame, KeyFrame.Key); MaxValue = Math.Max(MaxValue, KeyFrame.Value); i++; } curve.EndFrame = curve.Frames.Max(); if (curve.Keys.Length > 1) { curve.Delta = values[values.Count - 1] - values[0]; } curve.KeyType = AnimCurveKeyType.Single; curve.FrameType = AnimCurveFrameType.Single; /* if (MaxFrame < byte.MaxValue) * curve.FrameType = AnimCurveFrameType.Byte; * else if (MaxFrame < ushort.MaxValue) * curve.FrameType = AnimCurveFrameType.Decimal10x5; * else * curve.FrameType = AnimCurveFrameType.Single; * * if (MaxValue < byte.MaxValue) * curve.KeyType = AnimCurveKeyType.SByte; * else if (MaxValue < ushort.MaxValue) * curve.KeyType = AnimCurveKeyType.Int16; * else * curve.KeyType = AnimCurveKeyType.Single;*/ } } } TexturePatternCurveIndex += matAnimData.TexturePatternAnimInfos.Where(item => item.CurveIndex != uint.MaxValue).ToList().Count; ShaderParamCurveIndex += CurveIndex; } return(matAnim); }
private void LoadAnim(MaterialAnim anim) { Initialize(); MaterialAnim = anim; FrameCount = MaterialAnim.FrameCount; Text = anim.Name; Textures.Clear(); if (anim.TextureNames != null) { foreach (var name in anim.TextureNames) { Textures.Add(name); } } Materials.Clear(); foreach (var matanim in anim.MaterialAnimDataList) { var mat = new MaterialAnimEntry(matanim.Name); mat.MaterialAnimData = matanim; Materials.Add(mat); foreach (var param in matanim.ParamAnimInfos) { FSHU.BfresParamAnim paramInfo = new FSHU.BfresParamAnim(param.Name); mat.Params.Add(paramInfo); paramInfo.Type = AnimationType.ShaderParam; //There is no better way to determine if the param is a color type afaik if (param.Name.Contains("Color") || param.Name.Contains("color") || param.Name == "multi_tex_reg2") { paramInfo.Type = AnimationType.Color; } else if (AnimType == AnimationType.TexturePattern) { paramInfo.Type = AnimationType.TexturePattern; } else if (AnimType == AnimationType.TextureSrt) { paramInfo.Type = AnimationType.TextureSrt; } else { paramInfo.Type = AnimationType.ShaderParam; } //Get constant anims for (int constant = 0; constant < param.ConstantCount; constant++) { int index = constant + param.BeginConstant; Animation.KeyGroup keyGroup = new Animation.KeyGroup(); keyGroup.Keys.Add(new Animation.KeyFrame() { InterType = InterpolationType.CONSTANT, Frame = 0, Value = matanim.Constants[index].Value, }); paramInfo.Values.Add(new Animation.KeyGroup() { AnimDataOffset = matanim.Constants[index].AnimDataOffset, Keys = keyGroup.Keys, }); } for (int curve = 0; curve < param.FloatCurveCount + param.IntCurveCount; curve++) { int index = curve + param.BeginCurve; Animation.KeyGroup keyGroup = CurveHelper.CreateTrack(matanim.Curves[index]); keyGroup.AnimDataOffset = matanim.Curves[index].AnimDataOffset; paramInfo.Values.Add(new Animation.KeyGroup() { AnimDataOffset = keyGroup.AnimDataOffset, Keys = keyGroup.Keys, }); } } foreach (TexturePatternAnimInfo SamplerInfo in matanim.TexturePatternAnimInfos) { BfresSamplerAnim sampler = new BfresSamplerAnim(SamplerInfo.Name, this, mat); mat.Samplers.Add(sampler); int textureIndex = 0; if (SamplerInfo.BeginConstant != 65535) { textureIndex = matanim.Constants[SamplerInfo.BeginConstant].Value; sampler.Keys.Add(new Animation.KeyFrame() { Frame = 0, Value = textureIndex }); sampler.Constant = true; sampler.AnimDataOffset = matanim.Constants[SamplerInfo.BeginConstant].AnimDataOffset; } if (SamplerInfo.CurveIndex != 65535) { int index = (int)SamplerInfo.CurveIndex; Animation.KeyGroup keyGroup = CurveHelper.CreateTrack(matanim.Curves[index]); sampler.AnimDataOffset = matanim.Curves[index].AnimDataOffset; sampler.Keys = keyGroup.Keys; } } } }
public FMAA(MaterialAnim anim) { LoadAnim(anim); }
public void ToYaml(MaterialAnim materialAnim, FMAA.AnimationType animType) { MaterialAnimConfigs = new List <MatAnimConfig>(); Name = materialAnim.Name; Path = materialAnim.Path; FrameCount = materialAnim.FrameCount; Loop = materialAnim.Loop; foreach (var mat in materialAnim.MaterialAnimDataList) { MatAnimConfig matConfig = new MatAnimConfig(); matConfig.Name = mat.Name; MaterialAnimConfigs.Add(matConfig); foreach (var paramInfo in mat.ParamAnimInfos) { ParamInfo paramCfg = new ParamInfo(); paramCfg.Name = paramInfo.Name; paramCfg.IsConstant = paramInfo.ConstantCount != 0; matConfig.ParamInfos.Add(paramCfg); if (paramInfo.ConstantCount != 0) { paramCfg.Constants = new List <ConstantConfig>(); for (int i = 0; i < paramInfo.ConstantCount; i++) { AnimConstant constant = mat.Constants[paramInfo.BeginConstant + i]; ConstantConfig ConstantValue = new ConstantConfig(); ConstantValue.Offset = ConvertParamOffset(constant.AnimDataOffset, animType); ConstantValue.Value = constant.Value; paramCfg.Constants.Add(ConstantValue); } } if (paramInfo.BeginCurve != ushort.MaxValue) { paramCfg.CurveData = new List <CurveConfig>(); for (int i = 0; i < paramInfo.IntCurveCount + paramInfo.FloatCurveCount; i++) { var curve = mat.Curves[(int)paramInfo.BeginCurve + i]; var CurveCfg = new CurveConfig(); CurveCfg.Offset = ConvertParamOffset(curve.AnimDataOffset, animType); if (curve.Scale == 0) { curve.Scale = 1; } for (int f = 0; f < curve.Frames.Length; f++) { int frame = (int)curve.Frames[f]; float Value = curve.Offset + curve.Keys[f, 0] * curve.Scale; CurveCfg.KeyFrames.Add(frame, Value); } paramCfg.CurveData.Add(CurveCfg); } } } foreach (var patternInfo in mat.TexturePatternAnimInfos) { PatternInfo infoCfg = new PatternInfo(); infoCfg.Name = patternInfo.Name; infoCfg.IsConstant = patternInfo.BeginConstant != ushort.MaxValue; matConfig.TexturePatternInfos.Add(infoCfg); if (infoCfg.IsConstant) { infoCfg.ConstantValue = new ConstantTPConfig(); int Index = (int)mat.Constants[(int)patternInfo.BeginConstant].Value; infoCfg.ConstantValue.Texture = materialAnim.TextureNames[Index]; } if (patternInfo.CurveIndex != ushort.MaxValue) { var curve = mat.Curves[(int)patternInfo.CurveIndex]; infoCfg.CurveData = new CurveTPConfig(); if (curve.Scale == 0) { curve.Scale = 1; } for (int f = 0; f < curve.Frames.Length; f++) { int frame = (int)curve.Frames[f]; int Value = (int)curve.Offset + (int)curve.Keys[f, 0] * (int)curve.Scale; infoCfg.CurveData.KeyFrames.Add(frame, materialAnim.TextureNames[Value]); } } } } }
public PerMatAnim(BFRES.MTA mta, MaterialAnim vis) { mta.Text = vis.Name; mta.FrameCount = (uint)vis.FrameCount; if (vis.TextureNames != null) { foreach (string tex in vis.TextureNames) { mta.Pat0.Add(tex); } } foreach (MaterialAnimData matanim in vis.MaterialAnimDataList) { BFRES.MatAnimEntry mat = new BFRES.MatAnimEntry(); mat.Text = matanim.Name; if (matanim.Curves.Count == 0) { int CurTex = 0; foreach (TexturePatternAnimInfo inf in matanim.TexturePatternAnimInfos) { if (vis.TextureNames != null) { BFRES.MatAnimData md = new BFRES.MatAnimData(); //Switch doesn't have base values? I can't find any like wii u did so i'll just have this look though each texture map. //Some have multiple maps but one texture (Yoshi in Odyssey) so this checks the texture count if (CurTex + 1 <= vis.TextureNames.Count) { md.Pat0Tex = mta.Pat0[CurTex]; } else { md.Pat0Tex = mta.Pat0[0]; } md.SamplerName = inf.Name; md.Frame = 0; mat.matCurves.Add(md); } CurTex++; } } int CurCurve = 0; foreach (AnimCurve cr in matanim.Curves) { for (int i = 0; i < (ushort)cr.Frames.Length; i++) { MatAnimData md = new MatAnimData(); foreach (TexturePatternAnimInfo inf in matanim.TexturePatternAnimInfos) { if (inf.CurveIndex == CurCurve) { md.SamplerName = inf.Name; } } //Set pat0 data if texture list exists if (vis.TextureNames != null) { if (cr.KeyType == AnimCurveKeyType.SByte) { md.CurveIndex = CurCurve; if (cr.Scale != 0) { int test = (int)cr.Keys[i, 0]; float key = cr.Offset + test * cr.Scale; md.Pat0Tex = (mta.Pat0[(int)key]); md.Frame = (int)cr.Frames[i]; } else { int test = (int)cr.Keys[i, 0]; int key = cr.Offset + test; md.Pat0Tex = (mta.Pat0[(int)key]); md.Frame = (int)cr.Frames[i]; } } } mat.matCurves.Add(md); } CurCurve++; } mta.matEntries.Add(mat); } }
private void LoadTagDataFromFile(EndianBinaryReader reader, int tagCount) { for (int i = 0; i < tagCount; i++) { long tagStart = reader.BaseStream.Position; string tagName = reader.ReadString(4); int tagSize = reader.ReadInt32(); switch (tagName) { case "TTK1": LoopMode = (LoopType)reader.ReadByte(); // 0 = Play Once. 2 = Loop (Assumed from BCK) byte angleMultiplier = reader.ReadByte(); // Multiply Angle Value by pow(2, angleMultiplier) (Assumed from BCK) AnimLengthInFrames = reader.ReadInt16(); short textureAnimEntryCount = (short)(reader.ReadInt16() / 3); // 3 for each material. BTK stores U, V, and W separately, so you need to divide by three. short numScaleFloatEntries = reader.ReadInt16(); short numRotationShortEntries = reader.ReadInt16(); short numTranslateFloatEntries = reader.ReadInt16(); int animDataOffset = reader.ReadInt32(); int remapTableOffset = reader.ReadInt32(); int stringTableOffset = reader.ReadInt32(); int textureIndexTableOffset = reader.ReadInt32(); int textureCenterTableOffset = reader.ReadInt32(); int scaleDataOffset = reader.ReadInt32(); int rotationDataOffset = reader.ReadInt32(); int translateDataOffset = reader.ReadInt32(); // Read array of scale data float[] scaleData = new float[numScaleFloatEntries]; reader.BaseStream.Position = tagStart + scaleDataOffset; for (int j = 0; j < numScaleFloatEntries; j++) { scaleData[j] = reader.ReadSingle(); } // Read array of rotation data (but don't convert it) float[] rotationData = new float[numRotationShortEntries]; reader.BaseStream.Position = tagStart + rotationDataOffset; for (int j = 0; j < numRotationShortEntries; j++) { rotationData[j] = reader.ReadInt16(); } // Read array of translation/position data float[] translationData = new float[numTranslateFloatEntries]; reader.BaseStream.Position = tagStart + translateDataOffset; for (int j = 0; j < numTranslateFloatEntries; j++) { translationData[j] = reader.ReadSingle(); } // Remap Table (probably matches MAT3's remap table?) m_remapTable = new short[textureAnimEntryCount]; reader.BaseStream.Position = tagStart + remapTableOffset; for (int j = 0; j < textureAnimEntryCount; j++) { m_remapTable[j] = reader.ReadInt16(); } // String Table which gives us material names. reader.BaseStream.Position = tagStart + stringTableOffset; StringTable stringTable = StringTable.FromStream(reader); // Texture Index table which tells us which texture index of this material to modify (?) byte[] texMtxIndexTable = new byte[textureAnimEntryCount]; reader.BaseStream.Position = tagStart + textureIndexTableOffset; for (int j = 0; j < textureAnimEntryCount; j++) { texMtxIndexTable[j] = reader.ReadByte(); } // Texture Centers Vector3[] textureCenters = new Vector3[textureAnimEntryCount]; reader.BaseStream.Position = tagStart + textureCenterTableOffset; for (int j = 0; j < textureAnimEntryCount; j++) { textureCenters[j] = new Vector3(reader.ReadSingle(), reader.ReadSingle(), reader.ReadSingle()); } // Read the data for each joint that this animation. m_animationData = new List <MaterialAnim>(); float rotScale = (float)Math.Pow(2f, angleMultiplier) * (180 / 32768f); reader.BaseStream.Position = tagStart + animDataOffset; for (int j = 0; j < textureAnimEntryCount; j++) { AnimComponent texU = ReadAnimComponent(reader); AnimComponent texV = ReadAnimComponent(reader); AnimComponent texW = ReadAnimComponent(reader); MaterialAnim anim = new MaterialAnim(); anim.Name = stringTable[j]; anim.TexMatrixIndex = texMtxIndexTable[j]; anim.Center = textureCenters[j]; anim.ScalesX = ReadComp(scaleData, texU.Scale); anim.ScalesY = ReadComp(scaleData, texV.Scale); anim.ScalesZ = ReadComp(scaleData, texW.Scale); anim.RotationsX = ReadComp(rotationData, texU.Rotation); anim.RotationsY = ReadComp(rotationData, texV.Rotation); anim.RotationsZ = ReadComp(rotationData, texW.Rotation); // Convert all of the rotations from compressed shorts back into -180, 180 ConvertRotation(anim.RotationsX, rotScale); ConvertRotation(anim.RotationsY, rotScale); ConvertRotation(anim.RotationsZ, rotScale); anim.TranslationsX = ReadComp(translationData, texU.Translation); anim.TranslationsY = ReadComp(translationData, texV.Translation); anim.TranslationsZ = ReadComp(translationData, texW.Translation); m_animationData.Add(anim); } break; } // Skip the stream reader to the start of the next tag since it gets moved around during loading. reader.BaseStream.Position = tagStart + tagSize; } }
public FMAA(MaterialAnim anim, AnimationType type) { LoadAnim(anim); AnimType = type; }