public void ReadCorrectHeader() => File.OpenRead(FileName).Using(stream => { var TestPmo = Pmo.Read(stream); Assert.Equal(0x4F4D50, (int)TestPmo.header.MagicCode); Assert.Equal(0, (int)TestPmo.header.SkeletonOffset); Assert.Equal(0xC0, (int)TestPmo.header.MeshOffset0); Assert.Equal(0, (int)TestPmo.header.MeshOffset1); });
public void ReadCorrectMeshGroup() => File.OpenRead(FileName).Using(stream => { var TestPmo = Pmo.Read(stream); // mesh header 1 Assert.Equal("544", TestPmo.Meshes[0].SectionInfo.VertexCount.ToString()); Assert.Equal("16", TestPmo.Meshes[0].SectionInfo.TriangleStripCount.ToString()); });
private static void Convert(string fileIn, string fileOut) { MeshGroup p = FromFbx(fileIn); Pmo pmo = MeshGroup2PMO(p); using Stream stream = File.Create(fileOut); Pmo.Write(stream, pmo); stream.Close(); }
public PmoParser(Pmo pmo, float Scale) { aPmo = pmo; MeshDescriptors = new List <MeshDescriptor>(); MeshDescriptor currentMesh = new MeshDescriptor(); for (int x = 0; x < pmo.Meshes.Count; x++) { var vertices = new PositionColoredTextured[pmo.Meshes[x].vertices.Count]; for (var i = 0; i < vertices.Length; i++) { Vector4 color; if (Pmo.GetFlags(pmo.Meshes[x].SectionInfo).UniformDiffuseFlag) { byte[] byt = BitConverter.GetBytes(pmo.Meshes[x].SectionInfo_opt2.DiffuseColor); if (BitConverter.IsLittleEndian) { Array.Reverse(byt); } color.X = 0xFF; color.Y = 0xFF; color.Z = 0xFF; color.W = byt[0]; } else { color = pmo.Meshes[x].colors[i]; color.Y = 0xFF; color.Z = 0xFF; color.W = 0xFF; } vertices[i].X = pmo.Meshes[x].vertices[i].X * pmo.header.ModelScale * Scale; vertices[i].Y = pmo.Meshes[x].vertices[i].Y * pmo.header.ModelScale * Scale; vertices[i].Z = pmo.Meshes[x].vertices[i].Z * pmo.header.ModelScale * Scale; vertices[i].Tu = pmo.Meshes[x].textureCoordinates[i].X; vertices[i].Tv = pmo.Meshes[x].textureCoordinates[i].Y; vertices[i].R = (byte)color.W; vertices[i].G = (byte)color.Z; vertices[i].B = (byte)color.Y; vertices[i].A = 0xFF; } currentMesh = new MeshDescriptor() { Vertices = vertices, Indices = pmo.Meshes[x].Indices.ToArray(), TextureIndex = pmo.Meshes[x].TextureID, IsOpaque = true }; MeshDescriptors.Add(currentMesh); } }
public PmoParser(Pmo pmo, float Scale) { aPmo = pmo; MeshDescriptors = new List <MeshDescriptor>(); MeshDescriptor currentMesh = new MeshDescriptor(); for (int x = 0; x < pmo.Meshes.Count; x++) { var vertices = new PositionColoredTextured[pmo.Meshes[x].vertices.Count]; for (var i = 0; i < vertices.Length; i++) { Vector4 color; if (Pmo.GetFlags(pmo.Meshes[x].SectionInfo).UniformDiffuseFlag) { var colorData = BitConverter.GetBytes(pmo.Meshes[x].SectionInfo_opt2.DiffuseColor); color.X = colorData[0] / 255f; color.Y = colorData[1] / 255f; color.Z = colorData[2] / 255f; color.W = colorData[3] / 255f; } else { color.X = pmo.Meshes[x].colors[i].X / 255f; color.Y = pmo.Meshes[x].colors[i].Y / 255f; color.Z = pmo.Meshes[x].colors[i].Z / 255f; color.W = pmo.Meshes[x].colors[i].W / 255f; } vertices[i].X = pmo.Meshes[x].vertices[i].X * pmo.header.ModelScale * Scale; vertices[i].Y = pmo.Meshes[x].vertices[i].Y * pmo.header.ModelScale * Scale; vertices[i].Z = pmo.Meshes[x].vertices[i].Z * pmo.header.ModelScale * Scale; vertices[i].Tu = pmo.Meshes[x].textureCoordinates[i].X; vertices[i].Tv = pmo.Meshes[x].textureCoordinates[i].Y; vertices[i].R = color.X; vertices[i].G = color.Y; vertices[i].B = color.Z; vertices[i].A = color.W; } currentMesh = new MeshDescriptor() { Vertices = vertices, Indices = pmo.Meshes[x].Indices.ToArray(), TextureIndex = pmo.Meshes[x].TextureID, IsOpaque = false }; MeshDescriptors.Add(currentMesh); } }
public void ReadBoneHeader() => File.OpenRead(FileName).Using(stream => { var TestPmo = Pmo.Read(stream); if (TestPmo.header.SkeletonOffset == 0) { Assert.True(true); } else { Assert.Equal((uint)0x4e4f42, TestPmo.skeletonHeader.MagicValue); Assert.Equal((uint)0x35, TestPmo.skeletonHeader.BoneCount); } });
public MeshGroupModel(GraphicsDevice g, string name, Pmo map, List <Tm2> texture, int index, Vector3 loc, Vector3 Rot, Vector3 Scl, bool diffMatrix) { _graphics = g; _model = map; Name = name; Texture = texture; Index = index; IsVisible = true; Location = loc; Rotation = Rot; Scale = Scl; hasDifferentMatrix = diffMatrix; InvalidateTextures(); Invalidate(); }
private static List <Assimp.Animation> PAMtoFBXAnim(Pmo pmo, Pam pam) { List <Assimp.Animation> animationList = new List <Assimp.Animation>(); for (int i = 0; i < pam.header.AnimationCount; i++) { Assimp.Animation anim = new Assimp.Animation(); anim.Name = pam.animList[i].AnimEntry.AnimationName; anim.DurationInTicks = pam.animList[i].AnimHeader.FrameCount; anim.TicksPerSecond = pam.animList[i].AnimHeader.Framerate; //anim.MeshAnimationChannels[0].MeshKeys.Add(new MeshKey(anim.DurationInTicks / 2, new Vector3D(0, 0, 100))); for (int b = 0; b < pam.animList[i].AnimHeader.BoneCount; b++) { Pam.BoneChannel chann = pam.animList[i].BoneChannels[b]; anim.NodeAnimationChannels.Add(new NodeAnimationChannel()); anim.NodeAnimationChannels[b].NodeName = pmo.boneList[b].JointName; ChannelData dat = GetChannelKeyframes(chann, anim.DurationInTicks); //AddTranslationAtKeyframe(anim.NodeAnimationChannels[b].PositionKeys, 0, new Vector3D(), anim.TicksPerSecond); // Position /*if(dat.transData != null) * { * foreach (ChannelTranslationData trans in dat.transData) * { * AddTranslationAtKeyframe(anim.NodeAnimationChannels[b].PositionKeys, trans.keyframeID, trans.Translation, anim.TicksPerSecond); * } * }*/ /*if (dat.rotData != null) * { * // Rotation * foreach (ChannelRotationData trans in dat.rotData) * { * AddRotationAtKeyframe(anim.NodeAnimationChannels[b].RotationKeys, trans.keyframeID, trans.Rotation, anim.TicksPerSecond); * } * }*/ } animationList.Add(anim); } return(animationList); }
private static void Convert(string PMO_Path, string PAM_Path) { Stream pmoStream = File.OpenRead(PMO_Path); Stream pamStream = File.OpenRead(PAM_Path); Pmo pmo = Pmo.Read(pmoStream); Pam pam = Pam.Read(pamStream); Assimp.Scene nScene = GetPMOScene(pmo); List <Assimp.Animation> FBXAnims = PAMtoFBXAnim(pmo, pam); nScene.Animations.AddRange(FBXAnims); pmoStream.Close(); pamStream.Close(); using var ctx = new AssimpContext(); ctx.ExportFile(nScene, "Test.fbx", "fbx"); }
public static (IModelMotion, IKingdomTexture[]) BBSMeshLoader(GraphicsDevice graphics, string FilePath, IModelMotion Model, IKingdomTexture[] Textures) { const float Scale = 100.0f; var file = File.OpenRead(FilePath); Pmo pmo = Pmo.Read(file); Model = new PmoParser(pmo, Scale); List <Tim2KingdomTexture> BbsTextures = new List <Tim2KingdomTexture>(); Textures = new IKingdomTexture[pmo.header.TextureCount]; for (int i = 0; i < pmo.header.TextureCount; i++) { BbsTextures.Add(new Tim2KingdomTexture(pmo.texturesData[i], graphics)); Textures[i] = BbsTextures[i]; } return(Model, Textures); }
public void WritesBackCorrectly() { Stream input = File.OpenRead(FileName); var TestPmo = Pmo.Read(input); Stream output = File.Open("Bbs/res/bbs-dummy_TEST.pmo", FileMode.Create); Pmo.Write(output, TestPmo); input.Position = 0; output.Position = 0; // Check all bytes. for (int i = 0; i < output.Length; i++) { if (input.ReadByte() != output.ReadByte()) { long position = output.Position; Assert.False(true); } } Assert.True(true); }
public void ReadCorrectTextures() => File.OpenRead(FileName).Using(stream => { var TestPmo = Pmo.Read(stream); byte[] buffer = TestPmo.texturesData[0]; Assert.True(buffer[0] == 0x54 && buffer[1] == 0x49 && buffer[2] == 0x4D && buffer[3] == 0x32); });
public static IModelMotion FromBBS(Pmo pmo) => pmo != null ? new PmoParser(pmo, 100.0f) : null;
private static Assimp.Scene GetPMOScene(Pmo pmo) { Assimp.Scene scene = new Assimp.Scene(); scene.RootNode = new Assimp.Node("root"); // Add materials. List <Material> matList = new List <Material>(); for (int t = 0; t < pmo.header.TextureCount; t++) { Material mat = new Material(); mat.Clear(); mat.Name = pmo.textureInfo[t].TextureName; scene.Materials.Add(mat); } // Add skeleton. List <Node> Skeleton = new List <Node>(); for (int b = 0; b < pmo.skeletonHeader.BoneCount; b++) { Pmo.BoneData bn = pmo.boneList[b]; Assimp.Matrix4x4 mtx = new Assimp.Matrix4x4(); mtx.A1 = bn.Transform.M11; mtx.A2 = bn.Transform.M12; mtx.A3 = bn.Transform.M13; mtx.A4 = bn.Transform.M14; mtx.B1 = bn.Transform.M21; mtx.B2 = bn.Transform.M22; mtx.B3 = bn.Transform.M23; mtx.B4 = bn.Transform.M24; mtx.C1 = bn.Transform.M31; mtx.C2 = bn.Transform.M32; mtx.C3 = bn.Transform.M33; mtx.C4 = bn.Transform.M34; mtx.D1 = bn.Transform.M41; mtx.D2 = bn.Transform.M42; mtx.D3 = bn.Transform.M43; mtx.D4 = bn.Transform.M44; Assimp.Matrix4x4 nd_mtx = mtx; nd_mtx.Transpose(); if (bn.ParentBoneIndex == 0xFFFF) { Node curNode = new Node(bn.JointName); curNode.Transform = nd_mtx; scene.RootNode.Children.Add(curNode); Skeleton.Add(curNode); } else { Node curNode = new Node(bn.JointName, Skeleton[bn.ParentBoneIndex]); nd_mtx.A4 *= 100.0f; nd_mtx.B4 *= 100.0f; nd_mtx.C4 *= 100.0f; curNode.Transform = nd_mtx; Skeleton.Add(curNode); scene.RootNode.FindNode(Skeleton[bn.ParentBoneIndex].Name).Children.Add(curNode); } } // Add meshes. for (int i = 0; i < pmo.Meshes.Count; i++) { Assimp.Mesh mesh = new Assimp.Mesh($"Mesh{i}", Assimp.PrimitiveType.Triangle); Pmo.MeshChunks chunk = pmo.Meshes[i]; // Add vertices, vertex color and normals. for (int j = 0; j < chunk.vertices.Count; j++) { mesh.Vertices.Add(new Assimp.Vector3D( chunk.vertices[j].X * pmo.header.ModelScale * 100.0f, chunk.vertices[j].Y * pmo.header.ModelScale * 100.0f, chunk.vertices[j].Z * pmo.header.ModelScale * 100.0f)); mesh.VertexColorChannels[0].Add(new Color4D(1.0f, 1.0f, 1.0f, 1.0f)); mesh.Normals.Add(new Vector3D()); } mesh.SetIndices(chunk.Indices.ToArray(), 3); mesh.MaterialIndex = chunk.SectionInfo.TextureID; scene.Meshes.Add(mesh); for (int v = 0; v < chunk.vertices.Count; v++) { // Build bone influences. for (int z = 0; z < chunk.SectionInfo_opt1.SectionBoneIndices.Length; z++) { if (chunk.SectionInfo_opt1.SectionBoneIndices[z] != 0xFF) { Pmo.BoneData currentBone = new Pmo.BoneData(); int currentIndex = chunk.SectionInfo_opt1.SectionBoneIndices[z]; currentBone = pmo.boneList[currentIndex]; string boneName = currentBone.JointName; Assimp.Matrix4x4 mtx = new Assimp.Matrix4x4(); mtx.A1 = currentBone.Transform.M11; mtx.A2 = currentBone.Transform.M12; mtx.A3 = currentBone.Transform.M13; mtx.A4 = currentBone.Transform.M14; mtx.B1 = currentBone.Transform.M21; mtx.B2 = currentBone.Transform.M22; mtx.B3 = currentBone.Transform.M23; mtx.B4 = currentBone.Transform.M24; mtx.C1 = currentBone.Transform.M31; mtx.C2 = currentBone.Transform.M32; mtx.C3 = currentBone.Transform.M33; mtx.C4 = currentBone.Transform.M34; mtx.D1 = currentBone.Transform.M41; mtx.D2 = currentBone.Transform.M42; mtx.D3 = currentBone.Transform.M43; mtx.D4 = currentBone.Transform.M44; Matrix3x3 mtx3 = new Matrix3x3(mtx); mtx.Transpose(); mtx.A4 *= 100.0f; mtx.B4 *= 100.0f; mtx.C4 *= 100.0f; mtx3.Transpose(); List <VertexWeight> weight = new List <VertexWeight>(); VertexWeight vW = new VertexWeight(); vW.VertexID = v; float currentWeight = chunk.jointWeights[v].weights[z]; switch (chunk.jointWeights[v].coordFormart) { case Pmo.CoordinateFormat.NO_VERTEX: break; case Pmo.CoordinateFormat.NORMALIZED_8_BITS: currentWeight *= 127.0f; currentWeight /= 128.0f; break; case Pmo.CoordinateFormat.NORMALIZED_16_BITS: currentWeight *= 32767.0f; currentWeight /= 32768.0f; break; case Pmo.CoordinateFormat.FLOAT_32_BITS: break; } vW.Weight = currentWeight; weight.Add(vW); Bone tempBone = scene.Meshes[i].Bones.Find(x => x.Name == boneName); int boneInd = scene.Meshes[i].Bones.FindIndex(0, x => x.Name == boneName); if (tempBone == null) { Bone bone = new Bone(boneName, mtx3, weight.ToArray()); scene.Meshes[i].Bones.Add(bone); } else { scene.Meshes[i].Bones[boneInd].VertexWeights.Add(vW); } } } } } scene.RootNode.MeshIndices.AddRange(Enumerable.Range(0, scene.MeshCount)); return(scene); }
private static Pmp MeshGroupList2PMP(List <MeshGroup> meshGroup) { Pmp pmp = new Pmp(); pmp.header.MagicCode = 0x504D50; pmp.header.TextureCount = (ushort)TexList.Count; pmp.header.ObjectCount = (ushort)meshGroup.Count; pmp.header.ModelCount = (ushort)meshGroup.Count; pmp.header.Padding = new int[2]; pmp.PmoList = new List <Pmo>(); pmp.objectInfo = new List <Pmp.ObjectInfo>(); pmp.TextureList = new List <Pmp.PMPTextureInfo>(); pmp.TextureDataList = new List <Tm2>(); Pmo pmo = new Pmo(); foreach (MeshGroup group in meshGroup) { List <MeshDescriptor> Descriptors = group.MeshDescriptors; List <int> textureIndices = new List <int>(); // Max 65K vertices. ushort descriptorVertexCount = 0; foreach (MeshDescriptor d in Descriptors) { descriptorVertexCount += (ushort)d.Vertices.Length; textureIndices.Add(d.TextureIndex); } // Mesh data. for (int i = 0; i < Descriptors.Count; i++) { MeshDescriptor desc = Descriptors[i]; Pmo.MeshChunks chunk = new Pmo.MeshChunks(); // Obtain info for PMO Vertex Flag. bool UsesUniformColor = UsesUniformDiffuseFlag(desc); Pmo.CoordinateFormat TextureCoordinateFormat = GetTextureCoordinateFormat(desc); Pmo.CoordinateFormat VertexFormat = GetVertexFormat(desc); chunk.SectionInfo = new Pmo.MeshSection(); chunk.SectionInfo.Attribute = 0; chunk.SectionInfo.VertexCount = (ushort)desc.Vertices.Length; chunk.SectionInfo.TextureID = (byte)desc.TextureIndex; chunk.SectionInfo.VertexFlags = 0x30000000; // 0011 000 0 0 00 000 0 000 0 00 00 11 00 000 01 // Set extra flags. if (UsesUniformColor) { var UniformColor = (uint)(desc.Vertices[0].A / 255f); UniformColor += (uint)(desc.Vertices[0].B / 255f) << 8; UniformColor += (uint)(desc.Vertices[0].G / 255f) << 16; UniformColor += (uint)(desc.Vertices[0].R / 255f) << 24; chunk.SectionInfo.VertexFlags = BitsUtil.Int.SetBit(chunk.SectionInfo.VertexFlags, 24, true); chunk.SectionInfo_opt2 = new Pmo.MeshSectionOptional2(); chunk.SectionInfo_opt2.DiffuseColor = UniformColor; } else { chunk.SectionInfo.VertexFlags = BitsUtil.Int.SetBits(chunk.SectionInfo.VertexFlags, 2, 3, (uint)0x7); } //chunk.SectionInfo.VertexFlags = BitsUtil.Int.SetBits(chunk.SectionInfo.VertexFlags, 0, 2, (uint)TextureCoordinateFormat); //chunk.SectionInfo.VertexFlags = BitsUtil.Int.SetBits(chunk.SectionInfo.VertexFlags, 7, 2, (uint)VertexFormat); chunk.SectionInfo.VertexFlags = BitsUtil.Int.SetBits(chunk.SectionInfo.VertexFlags, 0, 2, 2); chunk.SectionInfo.VertexFlags = BitsUtil.Int.SetBits(chunk.SectionInfo.VertexFlags, 7, 2, 2); chunk.SectionInfo.VertexSize += 0; // Weights. TextureCoordinateFormat = Pmo.CoordinateFormat.NORMALIZED_16_BITS; chunk.SectionInfo.VertexSize += (TextureCoordinateFormat == Pmo.CoordinateFormat.FLOAT_32_BITS) ? (byte)8 : (byte)((int)TextureCoordinateFormat * 2); // Texture Coordinates if (chunk.SectionInfo.VertexSize % 4 != 0) { chunk.SectionInfo.VertexSize += 2; } chunk.SectionInfo.VertexSize += UsesUniformColor ? (byte)0 : (byte)4; // VertexColor VertexFormat = Pmo.CoordinateFormat.NORMALIZED_16_BITS; chunk.SectionInfo.VertexSize += (VertexFormat == Pmo.CoordinateFormat.FLOAT_32_BITS) ? (byte)12 : (byte)((int)VertexFormat * 3); // Vertices if (chunk.SectionInfo.VertexSize % 4 != 0) { chunk.SectionInfo.VertexSize += 2; } for (int v = 0; v < desc.Vertices.Length; v++) { Vector4 Color = new Vector4(); Color.X = desc.Vertices[v].R * 256; Color.Y = desc.Vertices[v].G * 256; Color.Z = desc.Vertices[v].B * 256; Color.W = 128; chunk.colors.Add(Color); Vector3 vec; vec.X = desc.Vertices[v].X / 10000.0f; vec.Y = desc.Vertices[v].Y / 10000.0f; vec.Z = desc.Vertices[v].Z / 10000.0f; chunk.vertices.Add(vec); Vector2 Coords; Coords.X = desc.Vertices[v].Tu; Coords.Y = desc.Vertices[v].Tv; chunk.textureCoordinates.Add(Coords); } pmo.Meshes.Add(chunk); } // Header. pmo.header = new Pmo.Header(); pmo.header.MagicCode = 0x4F4D50; pmo.header.Number = 1; pmo.header.Group = 1; pmo.header.Version = 3; pmo.header.TextureCount = (byte)textureIndices.Count; // TODO. pmo.header.Flag = 0x800; pmo.header.MeshOffset0 = 0xA0 + ((uint)pmo.header.TextureCount * 0x20); pmo.header.VertexCount = descriptorVertexCount; pmo.header.TriangleCount = pmo.header.VertexCount; pmo.header.TriangleCount /= 3; pmo.header.ModelScale = 1.0f; pmo.header.BoundingBox = new float[32]; // Texture block. if (textureIndices.Count > 0) { pmo.textureInfo = new Pmo.TextureInfo[textureIndices.Count]; for (int t = 0; t < textureIndices.Count; t++) { Tm2 tm = TextureData[textureIndices[t]]; pmo.textureInfo[t] = new Pmo.TextureInfo(); pmo.textureInfo[t].TextureName = TexList[textureIndices[t]]; pmo.textureInfo[t].Unknown = new UInt32[4]; pmo.texturesData.Add(tm); Pmp.PMPTextureInfo pmpInfo = new Pmp.PMPTextureInfo(); pmpInfo.TextureName = pmo.textureInfo[t].TextureName; pmpInfo.Unknown = new uint[4]; pmp.TextureList.Add(pmpInfo); } } Pmp.ObjectInfo info = new Pmp.ObjectInfo(); info.PMO_Offset = 0x20 + (0x30 * (uint)meshGroup.Count) + 0; pmp.PmoList.Add(pmo); pmp.objectInfo.Add(info); } pmp.TextureDataList = TextureData; return(pmp); }
public PmoParser(Pmo pmo, float Scale) { aPmo = pmo; MeshDescriptors = new List <MeshDescriptor>(); MeshDescriptor currentMesh = new MeshDescriptor(); for (int x = 0; x < pmo.Meshes.Count; x++) { var vertices = new PositionColoredTextured[pmo.Meshes[x].vertices.Count]; for (var i = 0; i < vertices.Length; i++) { Vector4 color; color.X = pmo.Meshes[x].colors[i].X / 128.0f; color.Y = pmo.Meshes[x].colors[i].Y / 128.0f; color.Z = pmo.Meshes[x].colors[i].Z / 128.0f; color.W = pmo.Meshes[x].colors[i].W / 128.0f; vertices[i].X = pmo.Meshes[x].vertices[i].X * pmo.header.ModelScale * Scale; vertices[i].Y = pmo.Meshes[x].vertices[i].Y * pmo.header.ModelScale * Scale; vertices[i].Z = pmo.Meshes[x].vertices[i].Z * pmo.header.ModelScale * Scale; vertices[i].Tu = pmo.Meshes[x].textureCoordinates[i].X; vertices[i].Tv = pmo.Meshes[x].textureCoordinates[i].Y; vertices[i].R = color.X; vertices[i].G = color.Y; vertices[i].B = color.Z; vertices[i].A = color.W; } currentMesh = new MeshDescriptor() { Vertices = vertices, Indices = pmo.Meshes[x].Indices.ToArray(), TextureIndex = pmo.Meshes[x].TextureID, IsOpaque = false }; MeshDescriptors.Add(currentMesh); } if (pmo.header.SkeletonOffset != 0) { List <Matrix4x4> matrices = new List <Matrix4x4>(); List <Mdlx.Bone> skeleton = new List <Mdlx.Bone>(); foreach (Pmo.BoneData boneData in pmo.boneList) { Matrix4x4 mtx = boneData.Transform; Matrix4x4 mtx_nd = Matrix4x4.Transpose(mtx); matrices.Add(mtx_nd); Mdlx.Bone otherBone = new Mdlx.Bone(); otherBone.Index = boneData.BoneIndex; otherBone.Parent = (boneData.ParentBoneIndex == 0xFFFF) ? 0 : boneData.ParentBoneIndex; otherBone.TranslationX = mtx_nd.Translation.X; otherBone.TranslationY = mtx_nd.Translation.Y; otherBone.TranslationZ = mtx_nd.Translation.Z; otherBone.TranslationW = mtx_nd.M14; otherBone.RotationX = mtx_nd.M21; otherBone.RotationY = mtx_nd.M22; otherBone.RotationZ = mtx_nd.M23; otherBone.RotationW = mtx_nd.M24; otherBone.ScaleX = mtx_nd.M31; otherBone.ScaleY = mtx_nd.M32; otherBone.ScaleZ = mtx_nd.M33; otherBone.ScaleW = mtx_nd.M34; skeleton.Add(otherBone); } Bones = skeleton; InitialPose = matrices.ToArray(); CurrentPose = InitialPose; } }
public void ReadCorrectTextureBlock() => File.OpenRead(FileName).Using(stream => { var TestPmo = Pmo.Read(stream); Assert.Equal("Dummy_tex02", TestPmo.textureInfo[0].TextureName); Assert.Equal(0x2300, (int)TestPmo.textureInfo[0].TextureOffset); });
private static Pmo MeshGroup2PMO(MeshGroup meshGroup) { Pmo pmo = new Pmo(); List <MeshDescriptor> Descriptors = meshGroup.MeshDescriptors; // Max 65K vertices. uint descriptorVertexCount = 0; uint indicesVertexCount = 0; foreach (MeshDescriptor d in Descriptors) { descriptorVertexCount += (uint)d.Vertices.Length; indicesVertexCount += (uint)d.Indices.Length; } // Mesh data. for (int i = 0; i < Descriptors.Count; i++) { MeshDescriptor desc = Descriptors[i]; int[] vertIndices = desc.Indices; Pmo.MeshChunks chunk = new Pmo.MeshChunks(); // Obtain info for PMO Vertex Flag. bool UsesUniformColor = UsesUniformDiffuseFlag(desc); Pmo.CoordinateFormat TextureCoordinateFormat = GetTextureCoordinateFormat(desc); Pmo.CoordinateFormat VertexFormat = GetVertexFormat(desc); chunk.SectionInfo = new Pmo.MeshSection(); chunk.SectionInfo.Attribute = 0; chunk.SectionInfo.VertexCount = (ushort)desc.Vertices.Length; chunk.SectionInfo.TextureID = (byte)desc.TextureIndex; chunk.SectionInfo.VertexFlags = 0x30000000; // 0011 000 0 0 00 000 0 000 0 00 00 11 00 000 01 // Set extra flags. if (UsesUniformColor) { var UniformColor = (uint)(Math.Min(byte.MaxValue, desc.Vertices[0].A * 256f)); UniformColor += (uint)(Math.Min(byte.MaxValue, desc.Vertices[0].B * 256f)) << 8; UniformColor += (uint)(Math.Min(byte.MaxValue, desc.Vertices[0].G * 256f)) << 16; UniformColor += (uint)(Math.Min(byte.MaxValue, desc.Vertices[0].R * 256f)) << 24; chunk.SectionInfo.VertexFlags = BitsUtil.Int.SetBit(chunk.SectionInfo.VertexFlags, 24, true); chunk.SectionInfo_opt2 = new Pmo.MeshSectionOptional2(); chunk.SectionInfo_opt2.DiffuseColor = UniformColor; } else { chunk.SectionInfo.VertexFlags = BitsUtil.Int.SetBits(chunk.SectionInfo.VertexFlags, 2, 3, (uint)0x7); } chunk.SectionInfo.VertexFlags = BitsUtil.Int.SetBits(chunk.SectionInfo.VertexFlags, 0, 2, (uint)TextureCoordinateFormat); chunk.SectionInfo.VertexFlags = BitsUtil.Int.SetBits(chunk.SectionInfo.VertexFlags, 7, 2, (uint)VertexFormat); chunk.SectionInfo.VertexSize += 0; // Weights. chunk.SectionInfo.VertexSize += (TextureCoordinateFormat == Pmo.CoordinateFormat.FLOAT_32_BITS) ? (byte)8 : (byte)((int)TextureCoordinateFormat * 2); // Texture Coordinates if (chunk.SectionInfo.VertexSize % 4 != 0) { chunk.SectionInfo.VertexSize += 2; } chunk.SectionInfo.VertexSize += UsesUniformColor ? (byte)0 : (byte)4; // VertexColor chunk.SectionInfo.VertexSize += (VertexFormat == Pmo.CoordinateFormat.FLOAT_32_BITS) ? (byte)12 : (byte)((int)VertexFormat * 3); // Vertices for (int v = 0; v < desc.Indices.Length; v++) { int index = vertIndices[v]; Vector4 Color = new Vector4(); Color.X = desc.Vertices[index].R * 2; Color.Y = desc.Vertices[index].G * 2; Color.Z = desc.Vertices[index].B * 2; Color.W = desc.Vertices[index].A * 2; chunk.colors.Add(Color); Vector3 vec; vec.X = desc.Vertices[index].X / 10000.0f; vec.Y = desc.Vertices[index].Y / 10000.0f; vec.Z = desc.Vertices[index].Z / 10000.0f; chunk.vertices.Add(vec); Vector2 Coords; Coords.X = desc.Vertices[index].Tu; Coords.Y = desc.Vertices[index].Tv; chunk.textureCoordinates.Add(Coords); } pmo.Meshes.Add(chunk); } // Header. pmo.header = new Pmo.Header(); pmo.header.MagicCode = 0x4F4D50; pmo.header.TextureCount = (ushort)TextureData.Count; // TODO. pmo.header.Unk0A = 0x80; pmo.header.MeshOffset0 = 0xA0 + ((uint)pmo.header.TextureCount * 0x20); pmo.header.VertexCount = (ushort)indicesVertexCount; pmo.header.TriangleCount = (ushort)indicesVertexCount; pmo.header.TriangleCount /= 3; pmo.header.ModelScale = 1.0f; pmo.header.BoundingBox = new float[32]; // Texture block. if (TextureData.Count > 0) { pmo.textureInfo = new Pmo.TextureInfo[TextureData.Count]; for (int t = 0; t < TextureData.Count; t++) { Tm2 tm = TextureData[t]; pmo.textureInfo[t] = new Pmo.TextureInfo(); pmo.textureInfo[t].TextureName = TexList[t]; pmo.textureInfo[t].Unknown = new UInt32[4]; pmo.texturesData.Add(TextureData[t]); } } return(pmo); }
private static Pmo MeshGroup2PMO(MeshGroup meshGroup) { Pmo pmo = new Pmo(); List <MeshDescriptor> Descriptors = meshGroup.MeshDescriptors; // Max 65K vertices. uint descriptorVertexCount = 0; uint indicesVertexCount = 0; foreach (MeshDescriptor d in Descriptors) { descriptorVertexCount += (uint)d.Vertices.Length; indicesVertexCount += (uint)d.Indices.Length; } // Mesh data. for (int i = 0; i < Descriptors.Count; i++) { MeshDescriptor desc = Descriptors[i]; int[] vertIndices = desc.Indices; Pmo.MeshChunks chunk = new Pmo.MeshChunks(); // Obtain info for PMO Vertex Flag. bool UsesUniformColor = UsesUniformDiffuseFlag(desc); Pmo.CoordinateFormat TextureCoordinateFormat = GetTextureCoordinateFormat(desc); Pmo.CoordinateFormat VertexFormat = GetVertexFormat(desc); chunk.SectionInfo = new Pmo.MeshSection(); chunk.SectionInfo.Attribute = 0; chunk.SectionInfo.VertexCount = (ushort)desc.Vertices.Length; chunk.SectionInfo.TextureID = (byte)desc.TextureIndex; chunk.SectionInfo.VertexFlags = 0x30000000; // 0011 000 0 0 00 000 0 000 0 00 00 11 00 000 01 // Set extra flags. if (UsesUniformColor) { var UniformColor = (uint)(Math.Min(byte.MaxValue, desc.Vertices[0].A * 256f)); UniformColor += (uint)(Math.Min(byte.MaxValue, desc.Vertices[0].B * 256f)) << 8; UniformColor += (uint)(Math.Min(byte.MaxValue, desc.Vertices[0].G * 256f)) << 16; UniformColor += (uint)(Math.Min(byte.MaxValue, desc.Vertices[0].R * 256f)) << 24; chunk.SectionInfo.VertexFlags = BitsUtil.Int.SetBit(chunk.SectionInfo.VertexFlags, 24, true); chunk.SectionInfo_opt2 = new Pmo.MeshSectionOptional2(); chunk.SectionInfo_opt2.DiffuseColor = UniformColor; } else { chunk.SectionInfo.VertexFlags = BitsUtil.Int.SetBits(chunk.SectionInfo.VertexFlags, 2, 3, (uint)0x7); } //chunk.SectionInfo.VertexFlags = BitsUtil.Int.SetBits(chunk.SectionInfo.VertexFlags, 0, 2, (uint)TextureCoordinateFormat); //chunk.SectionInfo.VertexFlags = BitsUtil.Int.SetBits(chunk.SectionInfo.VertexFlags, 7, 2, (uint)VertexFormat); uint texFormat = 3; uint posFormat = 3; chunk.SectionInfo.VertexFlags = BitsUtil.Int.SetBits(chunk.SectionInfo.VertexFlags, 0, 2, texFormat); chunk.SectionInfo.VertexFlags = BitsUtil.Int.SetBits(chunk.SectionInfo.VertexFlags, 7, 2, posFormat); chunk.SectionInfo.VertexSize += 0; // Weights. TextureCoordinateFormat = (Pmo.CoordinateFormat)texFormat; chunk.SectionInfo.VertexSize += (TextureCoordinateFormat == Pmo.CoordinateFormat.FLOAT_32_BITS) ? (byte)8 : (byte)((int)TextureCoordinateFormat * 2); // Texture Coordinates if (chunk.SectionInfo.VertexSize % 4 != 0) { chunk.SectionInfo.VertexSize += 2; } chunk.SectionInfo.VertexSize += UsesUniformColor ? (byte)0 : (byte)4; // VertexColor VertexFormat = (Pmo.CoordinateFormat)posFormat; chunk.SectionInfo.VertexSize += (VertexFormat == Pmo.CoordinateFormat.FLOAT_32_BITS) ? (byte)12 : (byte)((int)VertexFormat * 3); // Vertices if (chunk.SectionInfo.VertexSize % 4 != 0) { chunk.SectionInfo.VertexSize += 2; } for (int v = 0; v < desc.Indices.Length; v++) { int index = vertIndices[v]; Vector4 Color = new Vector4(); Color.X = desc.Vertices[index].R * 256; Color.Y = desc.Vertices[index].G * 256; Color.Z = desc.Vertices[index].B * 256; Color.W = 128; chunk.colors.Add(Color); Vector3 vec; vec.X = desc.Vertices[index].X / 10000.0f; vec.Y = desc.Vertices[index].Y / 10000.0f; vec.Z = desc.Vertices[index].Z / 10000.0f; chunk.vertices.Add(vec); Vector2 Coords; Coords.X = desc.Vertices[index].Tu; Coords.Y = desc.Vertices[index].Tv; chunk.textureCoordinates.Add(Coords); } pmo.Meshes.Add(chunk); } // Header. pmo.header = new Pmo.Header(); pmo.header.MagicCode = 0x4F4D50; pmo.header.Number = 1; pmo.header.Group = 1; pmo.header.Version = 3; pmo.header.TextureCount = (byte)TextureData.Count; // TODO. pmo.header.Flag = 0x800; pmo.header.MeshOffset0 = 0xA0 + ((uint)pmo.header.TextureCount * 0x20); pmo.header.VertexCount = (ushort)indicesVertexCount; pmo.header.TriangleCount = (ushort)indicesVertexCount; pmo.header.TriangleCount /= 3; pmo.header.ModelScale = 1.0f; pmo.header.BoundingBox = new float[32]; // Texture block. if (TextureData.Count > 0) { pmo.textureInfo = new Pmo.TextureInfo[TextureData.Count]; for (int t = 0; t < TextureData.Count; t++) { Tm2 tm = TextureData[t]; pmo.textureInfo[t] = new Pmo.TextureInfo(); pmo.textureInfo[t].TextureName = TexList[t]; pmo.textureInfo[t].Unknown = new UInt32[4]; pmo.texturesData.Add(TextureData[t]); } } //pmo.header.SkeletonOffset = pmo.header.MeshOffset0 + 0; pmo.skeletonHeader = new Pmo.SkeletonHeader(); pmo.boneList = new Pmo.BoneData[0]; /*pmo.skeletonHeader.MagicValue = 0x4E4F42; * pmo.skeletonHeader.BoneCount = (ushort)BoneData.Count; * pmo.skeletonHeader.SkinnedBoneCount = (ushort)BoneData.Count; * pmo.skeletonHeader.nStdBone = 2; * * pmo.boneList = new Pmo.BoneData[BoneData.Count]; * * for(int b = 0; b < pmo.boneList.Length; b++) * { * Pmo.BoneData bn = new Pmo.BoneData(); * bn.BoneIndex = (ushort)b; * * Assimp.Node curNode = new Assimp.Node(); * ushort p = 0; * foreach(var nd in NodeData) * { * p++; * if(nd.Name == BoneData[b].Name) * { * curNode = nd; * p--; * break; * } * } * * bn.ParentBoneIndex = p; * bn.JointName = BoneData[b].Name; * * Matrix4x4 mtx = new Matrix4x4(); * mtx.M11 = BoneData[b].OffsetMatrix.A1; * mtx.M12 = BoneData[b].OffsetMatrix.A2; * mtx.M13 = BoneData[b].OffsetMatrix.A3; * mtx.M14 = BoneData[b].OffsetMatrix.A4; * mtx.M21 = BoneData[b].OffsetMatrix.B1; * mtx.M22 = BoneData[b].OffsetMatrix.B2; * mtx.M23 = BoneData[b].OffsetMatrix.B3; * mtx.M24 = BoneData[b].OffsetMatrix.B4; * mtx.M31 = BoneData[b].OffsetMatrix.C1; * mtx.M32 = BoneData[b].OffsetMatrix.C2; * mtx.M33 = BoneData[b].OffsetMatrix.C3; * mtx.M34 = BoneData[b].OffsetMatrix.C4; * mtx.M41 = BoneData[b].OffsetMatrix.D1; * mtx.M42 = BoneData[b].OffsetMatrix.D2; * mtx.M43 = BoneData[b].OffsetMatrix.D3; * mtx.M44 = BoneData[b].OffsetMatrix.D4; * * bn.Transform = mtx; * bn.InverseTransform = mtx; * pmo.boneList[b] = bn; * }*/ return(pmo); }