private AnimationFrame CreateFrame(remBone frame, remParser parser, HashSet <string> extractFrames, remMesh mesh, Device device, Matrix combinedParent, List <AnimationFrame> meshFrames) { AnimationFrame animationFrame = new AnimationFrame(); animationFrame.Name = frame.name.ToString(); animationFrame.TransformationMatrix = frame.matrix; animationFrame.OriginalTransform = animationFrame.TransformationMatrix; animationFrame.CombinedTransform = combinedParent * animationFrame.TransformationMatrix; if (frame.name == mesh.frame) { ExtendedMaterial[] materials = new ExtendedMaterial[mesh.numMats]; List <List <remVertex> > submeshVertLists = new List <List <remVertex> >(mesh.numMats); List <List <ushort> > submeshFaceLists = new List <List <ushort> >(mesh.numMats); List <int[]> submeshVertIndices = new List <int[]>(mesh.numMats); SplitMesh(mesh, submeshVertLists, submeshFaceLists, submeshVertIndices); remSkin boneList = rem.FindSkin(mesh.name, parser.SKIC); bool skinned = boneList != null; int numBones = skinned ? boneList.Count : 0; List <string> boneNamesList = new List <string>(numBones); List <Matrix> boneOffsetsList = new List <Matrix>(numBones); for (int boneIdx = 0; boneIdx < numBones; boneIdx++) { boneNamesList.Add(boneList[boneIdx].bone.ToString()); boneOffsetsList.Add(boneList[boneIdx].matrix); } List <string> boneFrameParentNames = new List <string>(numBones); List <Matrix> boneFrameParentMatrices = new List <Matrix>(numBones); for (int boneIdx = 0; boneIdx < numBones; boneIdx++) { remBone boneFrame = rem.FindFrame(boneList[boneIdx].bone, parser.BONC.rootFrame); if (boneFrame == null) { continue; } remBone boneFrameParent = boneFrame.Parent; if (!boneNamesList.Contains(boneFrameParent.name) && !boneFrameParentNames.Contains(boneFrameParent.name)) { boneFrameParentNames.Add(boneFrameParent.name); Matrix incompleteMeshFrameCorrection = Matrix.Invert(frame.matrix); boneFrameParentMatrices.Add(incompleteMeshFrameCorrection * Matrix.Invert(boneFrame.matrix) * boneList[boneIdx].matrix); } } boneNamesList.AddRange(boneFrameParentNames); string[] boneNames = boneNamesList.ToArray(); boneOffsetsList.AddRange(boneFrameParentMatrices); Matrix[] boneOffsets = boneOffsetsList.ToArray(); AnimationMeshContainer[] meshContainers = new AnimationMeshContainer[submeshFaceLists.Count]; Vector3 min = new Vector3(Single.MaxValue); Vector3 max = new Vector3(Single.MinValue); for (int i = 0; i < submeshFaceLists.Count; i++) { List <ushort> faceList = submeshFaceLists[i]; List <remVertex> vertexList = submeshVertLists[i]; Mesh animationMesh = new Mesh(device, faceList.Count, vertexList.Count, MeshFlags.Managed, PositionBlendWeightsIndexedNormalTexturedColoured.Format); using (DataStream indexStream = animationMesh.LockIndexBuffer(LockFlags.None)) { for (int j = 0; j < faceList.Count; j++) { indexStream.Write(faceList[j]); } animationMesh.UnlockIndexBuffer(); } byte[][] vertexBoneIndices = null; float[][] vertexWeights = ConvertVertexWeights(vertexList, submeshVertIndices[i], boneList, out vertexBoneIndices); FillVertexBuffer(animationMesh, vertexList, vertexWeights, vertexBoneIndices, -1); var normalLines = new PositionBlendWeightsIndexedColored[vertexList.Count * 2]; for (int j = 0; j < vertexList.Count; j++) { remVertex vertex = vertexList[j]; Vector3 position = vertex.Position; Vector3 normal = vertex.Normal; float[] boneWeights = vertexWeights[j]; normalLines[j * 2] = new PositionBlendWeightsIndexedColored(position, boneWeights, vertexBoneIndices[j], Color.Coral.ToArgb()); normalLines[(j * 2) + 1] = new PositionBlendWeightsIndexedColored(position + normal, boneWeights, vertexBoneIndices[j], Color.Blue.ToArgb()); #if !DONT_MIRROR position.Z *= -1f; #endif min = Vector3.Minimize(min, position); max = Vector3.Maximize(max, position); } AnimationMeshContainer meshContainer = new AnimationMeshContainer(); meshContainer.Name = animationFrame.Name; meshContainer.MeshData = new MeshData(animationMesh); meshContainer.NormalLines = normalLines; meshContainer.BoneNames = boneNames; meshContainer.BoneOffsets = boneOffsets; meshContainers[i] = meshContainer; remMaterial mat = rem.FindMaterial(mesh.materials[i], parser.MATC); if (mat != null) { Material material3D = new Material(); material3D.Ambient = new Color4(mat.ambient); material3D.Diffuse = new Color4(mat.diffuse); material3D.Emissive = new Color4(mat.emissive); material3D.Specular = new Color4(mat.specular); material3D.Power = mat.specularPower; int matIdx = parser.MATC.IndexOf(mat); Materials[matIdx] = material3D; meshContainer.MaterialIndex = matIdx; int texIdx = 0; if (mat.texture != null && !TextureDic.TryGetValue(mat.texture.ToString(), out texIdx)) { ImportedTexture importedTex = null; if (!ImportedTextures.TryGetValue(mat.texture.ToString(), out importedTex)) { importedTex = rem.ImportedTexture(mat.texture, parser.RemPath, true); if (importedTex == null) { Report.ReportLog("Export textures of TEXH.FPK!"); continue; } ImportedTextures.Add(mat.texture.ToString(), importedTex); } Texture memTex = Texture.FromMemory(device, importedTex.Data); texIdx = TextureDic.Count; TextureDic.Add(mat.texture.ToString(), texIdx); Textures.Add(memTex); } meshContainer.TextureIndex = texIdx; } } for (int i = 0; i < (meshContainers.Length - 1); i++) { meshContainers[i].NextMeshContainer = meshContainers[i + 1]; } min = Vector3.TransformCoordinate(min, animationFrame.CombinedTransform); max = Vector3.TransformCoordinate(max, animationFrame.CombinedTransform); animationFrame.Bounds = new BoundingBox(min, max); animationFrame.MeshContainer = meshContainers[0]; meshFrames.Add(animationFrame); } for (int i = 0; i < frame.Count; i++) { remBone child = frame[i]; if (extractFrames.Contains(child.name.ToString())) { AnimationFrame childAnimationFrame = CreateFrame(child, parser, extractFrames, mesh, device, animationFrame.CombinedTransform, meshFrames); childAnimationFrame.Parent = animationFrame; animationFrame.AppendChild(childAnimationFrame); } } numFrames++; return(animationFrame); }
private AnimationFrame CreateFrame(odfFrame frame, odfParser parser, HashSet <int> extractFrames, HashSet <int> meshIDs, Device device, Matrix combinedParent, List <AnimationFrame> meshFrames) { AnimationFrame animationFrame = new AnimationFrame(); animationFrame.Name = frame.Name; animationFrame.TransformationMatrix = frame.Matrix; animationFrame.OriginalTransform = animationFrame.TransformationMatrix; animationFrame.CombinedTransform = combinedParent * animationFrame.TransformationMatrix; if ((int)frame.MeshId != 0 && meshIDs.Contains((int)frame.MeshId)) { odfMesh mesh = odf.FindMeshListSome(frame.MeshId, parser.MeshSection); ExtendedMaterial[] materials = new ExtendedMaterial[mesh.Count]; AnimationMeshContainer[] meshContainers = new AnimationMeshContainer[mesh.Count]; Vector3 min = new Vector3(Single.MaxValue); Vector3 max = new Vector3(Single.MinValue); for (int i = 0; i < mesh.Count; i++) { odfSubmesh submesh = mesh[i]; List <odfFace> faceList = submesh.FaceList; List <odfVertex> vertexList = submesh.VertexList; odfBoneList boneList = odf.FindBoneList(submesh.Id, parser.EnvelopeSection); bool skinned = boneList != null; int numBones = skinned ? boneList.Count : 0; string[] boneNames = new string[numBones]; Matrix[] boneOffsets = new Matrix[numBones]; for (int boneIdx = 0; boneIdx < numBones; boneIdx++) { odfBone bone = boneList[boneIdx]; boneNames[boneIdx] = odf.FindFrame(bone.FrameId, parser.FrameSection.RootFrame).Name; Matrix mirrored; if (!BoneMatrixDic.TryGetValue(boneNames[boneIdx], out mirrored)) { #if !DONT_MIRROR Vector3 translate, scale; Quaternion rotate; bone.Matrix.Decompose(out scale, out rotate, out translate); mirrored = Matrix.Scaling(scale.X, scale.Y, -scale.Z) * Matrix.RotationQuaternion(rotate) * Matrix.Translation(translate); #else mirrored = bone.Matrix; #endif BoneMatrixDic.Add(boneNames[boneIdx], mirrored); } boneOffsets[boneIdx] = mirrored; } Mesh animationMesh = new Mesh(device, faceList.Count, vertexList.Count, MeshFlags.Managed, PositionBlendWeightsIndexedNormalTexturedColoured.Format); using (DataStream indexStream = animationMesh.LockIndexBuffer(LockFlags.None)) { for (int j = 0; j < faceList.Count; j++) { ushort[] indices = faceList[j].VertexIndices; indexStream.Write(indices[0]); indexStream.Write(indices[1]); indexStream.Write(indices[2]); } animationMesh.UnlockIndexBuffer(); } float[][] vertexWeights = ConvertVertexWeights(vertexList, boneList); FillVertexBuffer(animationMesh, vertexList, vertexWeights, -1); var normalLines = new PositionBlendWeightsIndexedColored[vertexList.Count * 2]; for (int j = 0; j < vertexList.Count; j++) { odfVertex vertex = vertexList[j]; #if !DONT_MIRROR Vector3 position = new Vector3(vertex.Position.X, vertex.Position.Y, -vertex.Position.Z); Vector3 normal = new Vector3(vertex.Normal.X, vertex.Normal.Y, -vertex.Normal.Z); #else Vector3 position = vertex.Position; Vector3 normal = vertex.Normal; #endif float[] boneWeights = vertexWeights[j]; normalLines[j * 2] = new PositionBlendWeightsIndexedColored(position, boneWeights, vertex.BoneIndices, Color.Yellow.ToArgb()); normalLines[(j * 2) + 1] = new PositionBlendWeightsIndexedColored(position + (normal / 11), boneWeights, vertex.BoneIndices, Color.Blue.ToArgb()); min = Vector3.Minimize(min, position); max = Vector3.Maximize(max, position); } AnimationMeshContainer meshContainer = new AnimationMeshContainer(); meshContainer.Name = animationFrame.Name; meshContainer.MeshData = new MeshData(animationMesh); meshContainer.NormalLines = normalLines; meshContainer.BoneNames = boneNames; meshContainer.BoneOffsets = boneOffsets; meshContainers[i] = meshContainer; odfMaterial mat = odf.FindMaterialInfo(submesh.MaterialId, parser.MaterialSection); if (mat != null) { Material material3D = new Material(); material3D.Ambient = mat.Ambient; material3D.Diffuse = mat.Diffuse; material3D.Emissive = mat.Emissive; material3D.Specular = mat.Specular; material3D.Power = mat.SpecularPower; int matIdx = parser.MaterialSection.IndexOf(mat); Materials[matIdx] = material3D; meshContainer.MaterialIndex = matIdx; int texIdx = -1; if ((int)submesh.TextureIds[0] != 0 && !TextureDic.TryGetValue((int)submesh.TextureIds[0], out texIdx)) { odfTexture tex = odf.FindTextureInfo(submesh.TextureIds[0], parser.TextureSection); if (tex != null) { try { odfTextureFile texFile = new odfTextureFile(null, Path.GetDirectoryName(parser.ODFPath) + Path.DirectorySeparatorChar + tex.TextureFile); int fileSize = 0; ImportedTexture impTex = new ImportedTexture(texFile.DecryptFile(ref fileSize).BaseStream, tex.TextureFile); Texture memTex = impTex.ToTexture(device); texIdx = TextureDic.Count; TextureDic.Add((int)submesh.TextureIds[0], texIdx); Textures[texIdx] = memTex; } catch (SlimDXException ex) { Utility.ReportException(ex); Report.ReportLog("Please check " + tex.TextureFile + ". It may have an unsupported format."); } catch (Exception ex) { Utility.ReportException(ex); } } } meshContainer.TextureIndex = texIdx; } } for (int i = 0; i < (meshContainers.Length - 1); i++) { meshContainers[i].NextMeshContainer = meshContainers[i + 1]; } animationFrame.Bounds = new BoundingBox(min, max); animationFrame.MeshContainer = meshContainers[0]; meshFrames.Add(animationFrame); } for (int i = 0; i < frame.Count; i++) { odfFrame child = frame[i]; if (extractFrames.Contains((int)child.Id)) { AnimationFrame childAnimationFrame = CreateFrame(child, parser, extractFrames, meshIDs, device, animationFrame.CombinedTransform, meshFrames); childAnimationFrame.Parent = animationFrame; animationFrame.AppendChild(childAnimationFrame); } } numFrames++; return(animationFrame); }