public static RSkeleton CreateRSkeleton(Skel skel) { if (skel == null) { return(null); } var skeleton = new RSkeleton(); for (int i = 0; i < skel.BoneEntries.Length; i++) { RBone bone = new RBone { Name = skel.BoneEntries[i].Name, Id = skel.BoneEntries[i].Id, ParentId = skel.BoneEntries[i].ParentId, Transform = skel.Transform[i].ToOpenTK(), InvTransform = skel.InvTransform[i].ToOpenTK(), WorldTransform = skel.WorldTransform[i].ToOpenTK(), InvWorldTransform = skel.InvWorldTransform[i].ToOpenTK() }; skeleton.Bones.Add(bone); } skeleton.Reset(); return(skeleton); }
public override void Open() { if (Ssbh.TryParseSsbhFile(AbsolutePath, out var SSBHFile)) { if (SSBHFile is Skel) { skel = (Skel)SSBHFile; } } }
public static void Save(string fileName, SBScene scene, string sourceSkelPath) { var Skeleton = scene.Skeleton; var skelFile = new Skel(); skelFile.MajorVersion = 1; skelFile.MinorVersion = 0; List <SkelBoneEntry> BoneEntries = new List <SkelBoneEntry>(); List <Matrix4x4> Transforms = new List <Matrix4x4>(); List <Matrix4x4> InvTransforms = new List <Matrix4x4>(); List <Matrix4x4> WorldTransforms = new List <Matrix4x4>(); List <Matrix4x4> InvWorldTransforms = new List <Matrix4x4>(); // Attempt to match bone order to an existing SKEL if possible. var sortedBones = Skeleton.Bones; if (!string.IsNullOrEmpty(sourceSkelPath)) { sortedBones = GetBoneOrderBasedOnReference(Skeleton.Bones, sourceSkelPath); } short index = 0; foreach (var bone in sortedBones) { var boneEntry = new SkelBoneEntry { Name = bone.Name, Type = bone.Type, Id = index++ }; boneEntry.Type = 1; boneEntry.ParentId = -1; if (bone.Parent != null) { boneEntry.ParentId = (short)Array.IndexOf(sortedBones, bone.Parent); } BoneEntries.Add(boneEntry); Transforms.Add(bone.Transform.ToSsbh()); InvTransforms.Add(bone.Transform.Inverted().ToSsbh()); WorldTransforms.Add(bone.WorldTransform.ToSsbh()); InvWorldTransforms.Add(bone.InvWorldTransform.ToSsbh()); } skelFile.BoneEntries = BoneEntries.ToArray(); skelFile.Transform = Transforms.ToArray(); skelFile.InvTransform = InvTransforms.ToArray(); skelFile.WorldTransform = WorldTransforms.ToArray(); skelFile.InvWorldTransform = InvWorldTransforms.ToArray(); Ssbh.TrySaveSsbhFile(fileName, skelFile); }
public static void Save(string FileName, SBScene Scene) { var Skeleton = Scene.Skeleton; var skelFile = new Skel(); skelFile.MajorVersion = 1; skelFile.MinorVersion = 0; List <SkelBoneEntry> BoneEntries = new List <SkelBoneEntry>(); List <SkelMatrix> Transforms = new List <SkelMatrix>(); List <SkelMatrix> InvTransforms = new List <SkelMatrix>(); List <SkelMatrix> WorldTransforms = new List <SkelMatrix>(); List <SkelMatrix> InvWorldTransforms = new List <SkelMatrix>(); short index = 0; Dictionary <SBBone, short> BoneToIndex = new Dictionary <SBBone, short>(); var OrderedBones = SortBones(Skeleton.Bones); foreach (var bone in OrderedBones) { BoneToIndex.Add(bone, index); var boneentry = new SkelBoneEntry(); boneentry.Name = bone.Name; boneentry.Type = bone.Type; boneentry.Id = index++; boneentry.Type = 1; boneentry.ParentId = -1; if (bone.Parent != null)// && BoneToIndex.ContainsKey(bone.Parent)) { boneentry.ParentId = (short)OrderedBones.IndexOf(bone.Parent); } BoneEntries.Add(boneentry); Transforms.Add(TKMatrix_to_Skel(bone.Transform)); InvTransforms.Add(TKMatrix_to_Skel(bone.Transform.Inverted())); WorldTransforms.Add(TKMatrix_to_Skel(bone.WorldTransform)); InvWorldTransforms.Add(TKMatrix_to_Skel(bone.InvWorldTransform)); } skelFile.BoneEntries = BoneEntries.ToArray(); skelFile.Transform = Transforms.ToArray(); skelFile.InvTransform = InvTransforms.ToArray(); skelFile.WorldTransform = WorldTransforms.ToArray(); skelFile.InvWorldTransform = InvWorldTransforms.ToArray(); Ssbh.TrySaveSsbhFile(FileName, skelFile); }
public static void Render(Camera camera) { if (Skel == null) { return; } if (capsule == null) { capsule = new Capsule(); } if (sphere == null) { sphere = new Sphere(); } var capsuleShader = ShaderContainer.GetShader("Capsule"); var sphereShader = ShaderContainer.GetShader("Sphere"); var polygonShader = ShaderContainer.GetShader("Polygon"); if (RenderSettings.Instance.RenderHitCollisions) { GL.Disable(EnableCap.DepthTest); GL.Enable(EnableCap.Blend); GL.BlendFunc(BlendingFactor.SrcAlpha, BlendingFactor.OneMinusSrcAlpha); foreach (var hit in HitData) { if (hit.Enabled) { //some param files refer to bone hashes that don't exist on the skeleton if (!BoneIDs.TryGetValue(hit.Bone, out int boneIndex)) { continue; } Matrix4 bone = Skel.GetAnimationSingleBindsTransform(boneIndex); Vector4 color = new Vector4(hit.Color, 0.3f); //if (BoneIDs[hit.Bone] == 0)//special purpose HitData attached to trans or top // color = new Vector4(1, 0.3f, 0.3f, 0.3f); if (hit.Pos != hit.Pos2) { capsule.Render(capsuleShader, hit.Size, hit.Pos, hit.Pos2, bone, camera.MvpMatrix, color); } else { sphere.Render(sphereShader, hit.Size, hit.Pos, bone, camera.MvpMatrix, color); } } } GL.Enable(EnableCap.DepthTest); GL.Disable(EnableCap.Blend); } Matrix4 transN = Skel.GetAnimationSingleBindsTransform(0).ClearRotation().ClearScale(); int cliffHangID = RenderSettings.Instance.CliffHangID; if (cliffHangID >= 0 && cliffHangID < CliffHangData.Length) { GL.Disable(EnableCap.DepthTest); CliffHangShape shape = CliffHangData[cliffHangID]; Vector3 v1; Vector3 v2; Vector3 v3; Vector3 v4; //this makes sure the rectangle is always front facing //I had trouble using OpenGL's culling mode, I don't know why if ((shape.p1.X - shape.p2.X) * (shape.p1.Y - shape.p2.Y) > 0) { v1 = new Vector3(0, shape.p1.Y, shape.p1.X); v2 = new Vector3(0, shape.p1.Y, shape.p2.X); v3 = new Vector3(0, shape.p2.Y, shape.p2.X); v4 = new Vector3(0, shape.p2.Y, shape.p1.X); } else { v1 = new Vector3(0, shape.p1.Y, shape.p1.X); v2 = new Vector3(0, shape.p2.Y, shape.p1.X); v3 = new Vector3(0, shape.p2.Y, shape.p2.X); v4 = new Vector3(0, shape.p1.Y, shape.p2.X); } quad = new Polygon(new List <Vector3>() { v1, v2, v3, v4 }); quad.Render(polygonShader, transN, camera.MvpMatrix, new Vector4(Collision.IDColors[cliffHangID % 9], 1f)); GL.Enable(EnableCap.DepthTest); } }
public override void OnImportAsset(AssetImportContext ctx) { //Load file contents BoneLib.Bone file = new BoneLib.Bone(); file.LoadFile(ctx.assetPath); //Load skel file for reference M2 model = new M2(); model.LoadFile(ctx.assetPath.Substring(0, ctx.assetPath.Length - 8) + ".m2"); Skel skeleton = model.Skeleton; //Create empty animation clip AnimationClip clip = new AnimationClip(); AnimationCurve curve; Matrix4x4 matrix; Vector4[] columns = new Vector4[4]; float value; //Generate temporary bones Transform[] bones = new Transform[skeleton.Bones.Length]; for (int i = 0; i < bones.Length; i++) { bones[i] = new GameObject("Bone" + i).transform; bones[i].position = new Vector3(-skeleton.Bones[i].Pivot.X / 2, skeleton.Bones[i].Pivot.Z / 2, -skeleton.Bones[i].Pivot.Y / 2); } GameObject rig = new GameObject("Skeleton"); for (int i = 0; i < bones.Length; i++) { if (skeleton.Bones[i].Parent == -1) { bones[i].parent = rig.transform; } else { bones[i].parent = bones[skeleton.Bones[i].Parent]; } } //Fill animation data for each bone for (int i = 0; i < file.Bones.Length; i++) { string path = GetBonePath(skeleton.Bones[file.Bones[i]].Parent, skeleton.Bones) + "Bone" + file.Bones[i]; for (int j = 0; j < 4; j++) { columns[j] = new Vector4(file.Transformations[i][j][0], file.Transformations[i][j][1], file.Transformations[i][j][2], file.Transformations[i][j][3]); } matrix = new Matrix4x4(columns[0], columns[1], columns[2], columns[3]); value = -matrix.m03 / 2 + bones[file.Bones[i]].localPosition.x; curve = AnimationCurve.Linear(0f, value, 0.1f, value); clip.SetCurve(path, typeof(Transform), "localPosition.x", curve); value = matrix.m23 / 2 + bones[file.Bones[i]].localPosition.y; curve = AnimationCurve.Linear(0f, value, 0.1f, value); clip.SetCurve(path, typeof(Transform), "localPosition.y", curve); value = -matrix.m13 / 2 + bones[file.Bones[i]].localPosition.z; curve = AnimationCurve.Linear(0f, value, 0.1f, value); clip.SetCurve(path, typeof(Transform), "localPosition.z", curve); UnityEngine.Quaternion rotation = matrix.rotation; curve = AnimationCurve.Linear(0f, -rotation.x, 1f, rotation.x); clip.SetCurve(path, typeof(Transform), "localRotation.x", curve); curve = AnimationCurve.Linear(0f, -rotation.z, 0.1f, rotation.z); clip.SetCurve(path, typeof(Transform), "localRotation.y", curve); curve = AnimationCurve.Linear(0f, rotation.y, 0.1f, rotation.y); clip.SetCurve(path, typeof(Transform), "localRotation.z", curve); curve = AnimationCurve.Linear(0f, rotation.w, 0.1f, rotation.w); clip.SetCurve(path, typeof(Transform), "localRotation.w", curve); Vector3 scale = matrix.lossyScale; curve = AnimationCurve.Linear(0f, scale.x, 0.1f, scale.x); clip.SetCurve(path, typeof(Transform), "localScale.x", curve); curve = AnimationCurve.Linear(0f, scale.z, 0.1f, scale.z); clip.SetCurve(path, typeof(Transform), "localScale.y", curve); curve = AnimationCurve.Linear(0f, scale.y, 0.1f, scale.y); clip.SetCurve(path, typeof(Transform), "localScale.z", curve); } //Clear temporary bones and add animation clip to the asset DestroyImmediate(rig); ctx.AddObjectToAsset(Path.GetFileNameWithoutExtension(ctx.assetPath.Replace("/", "\\")), clip); }
public void Render(Camera camera) { if (Sphere == null) { Sphere = new Sphere(); } if (Capsule == null) { Capsule = new Capsule(); } if (Line == null) { Line = new Line(); } var sphereShader = ShaderContainer.GetShader("Sphere"); var capsuleShader = ShaderContainer.GetShader("Capsule"); var lineShader = ShaderContainer.GetShader("Line"); Matrix4 mvp = camera.MvpMatrix; List <Collision> collisions = new List <Collision>(); collisions.AddRange(Attacks); collisions.AddRange(Grabs); GL.Disable(EnableCap.DepthTest); for (int i = 0; i < collisions.Count; i++) { Collision coll = collisions[i]; if (!coll.Enabled) { continue; } Vector4 collColor = new Vector4(Collision.IDColors[i % Collision.IDColors.Length], 0.5f); Matrix4 boneTransform = Skel.GetAnimationSingleBindsTransform(BoneIDs[coll.Bone]); Matrix4 boneNoScale = Matrix4.CreateFromQuaternion(boneTransform.ExtractRotation()) * Matrix4.CreateTranslation(boneTransform.ExtractTranslation()); if (IsSphere(coll)) { Sphere.Render(sphereShader, coll.Size, coll.Pos, boneNoScale, mvp, collColor); } else if (coll.ShapeType == Collision.Shape.capsule) { Capsule.Render(capsuleShader, coll.Size, coll.Pos, coll.Pos2, boneNoScale, mvp, collColor); } //angle marker if (coll is Attack attack) { int angle = attack.Angle; Vector4 angleColor = new Vector4(1, 1, 1, 1); GL.LineWidth(2f); if (angle < 361) { float radian = angle * (float)Math.PI / 180f; Line.Render(lineShader, radian, coll.Size, coll.Pos, boneNoScale, mvp, angleColor); } else if (angle == 361) { float radian = (float)Math.PI / 2f; for (int j = 0; j < 4; j++) { Line.Render(lineShader, radian * j, coll.Size / 2, coll.Pos, boneNoScale, mvp, angleColor); } } else if (angle == 368) { //set_vec_target_pos uses a second position to pull opponents toward //this is represented by a line drawn between hitbox center and that point if (attack.VecTargetPos_node != 0) { var attackVecBone = Skel.GetAnimationSingleBindsTransform(BoneIDs[attack.VecTargetPos_node]); var attackVecBoneNoScale = Matrix4.CreateFromQuaternion(attackVecBone.ExtractRotation()) * Matrix4.CreateTranslation(attackVecBone.ExtractTranslation()); Line.Render(lineShader, boneNoScale, attackVecBoneNoScale, coll.Pos, Vector3.Zero, Vector3.Zero, new Vector3(attack.VecTargetPos_pos.Z, attack.VecTargetPos_pos.Y, 0), mvp, angleColor ); } } else { float radian = (float)Math.PI / 2f; float add = (float)Math.PI / 4f; for (int j = 0; j < 4; j++) { Line.Render(lineShader, radian * j + add, coll.Size / 2, coll.Pos, boneNoScale, mvp, angleColor); } } } } GL.Enable(EnableCap.DepthTest); }