public remVertex Clone() { remVertex vert = new remVertex(); vert.Position = Position; vert.UV = UV; vert.Normal = Normal; vert.RGBA = RGBA; return(vert); }
public static void CopyNormalsNear(List <remVertex> src, List <remVertex> dest) { for (int i = 0; i < dest.Count; i++) { var destVert = dest[i]; var destPos = destVert.Position; float minDistSq = Single.MaxValue; remVertex nearestVert = null; foreach (remVertex srcVert in src) { var srcPos = srcVert.Position; float[] diff = new float[] { destPos[0] - srcPos[0], destPos[1] - srcPos[1], destPos[2] - srcPos[2] }; float distSq = (diff[0] * diff[0]) + (diff[1] * diff[1]) + (diff[2] * diff[2]); if (distSq < minDistSq) { minDistSq = distSq; nearestVert = srcVert; } } destVert.Normal = nearestVert.Normal; } }
public static remMesh CreateMesh(WorkspaceMesh mesh, out string[] materialNames, out int[] indices, out bool[] worldCoords, out bool[] replaceSubmeshesOption) { int numUncheckedSubmeshes = 0; foreach (ImportedSubmesh submesh in mesh.SubmeshList) { if (!mesh.isSubmeshEnabled(submesh)) { numUncheckedSubmeshes++; } } int numSubmeshes = mesh.SubmeshList.Count - numUncheckedSubmeshes; materialNames = new string[numSubmeshes]; indices = new int[numSubmeshes]; worldCoords = new bool[numSubmeshes]; replaceSubmeshesOption = new bool[numSubmeshes]; remMesh newMesh = new remMesh(numSubmeshes); newMesh.name = new remId(mesh.Name); List <remVertex> newVertices = new List <remVertex>(); List <int> newFaces = new List <int>(); List <int> newFaceMarks = new List <int>(); for (int i = 0, submeshIdx = 0; i < numSubmeshes; i++, submeshIdx++) { while (!mesh.isSubmeshEnabled(mesh.SubmeshList[submeshIdx])) { submeshIdx++; } ImportedSubmesh submesh = mesh.SubmeshList[submeshIdx]; newMesh.AddMaterial(new remId(submesh.Material)); materialNames[i] = submesh.Material; indices[i] = submesh.Index; worldCoords[i] = submesh.WorldCoords; replaceSubmeshesOption[i] = mesh.isSubmeshReplacingOriginal(submesh); List <ImportedFace> faceList = submesh.FaceList; newFaces.Capacity += faceList.Count * 3; int[] faceMarks = new int[faceList.Count]; for (int j = 0; j < faceList.Count; j++) { ImportedFace face = faceList[j]; for (int k = 0; k < 3; k++) { newFaces.Add(face.VertexIndices[k] + newVertices.Count); } faceMarks[j] = i; } newFaceMarks.AddRange(faceMarks); List <ImportedVertex> vertexList = submesh.VertexList; newVertices.Capacity += vertexList.Count; for (int j = 0; j < vertexList.Count; j++) { ImportedVertex vert = vertexList[j]; remVertex newVertex = new remVertex(); if (submesh.WorldCoords) { newVertex.Position = vert.Position; newVertex.Normal = vert.Normal; } else { newVertex.Position = new Vector3(vert.Position.X, -vert.Position.Z, vert.Position.Y); newVertex.Normal = new Vector3(vert.Normal.X, -vert.Normal.Z, vert.Normal.Y); } newVertex.UV = new Vector2(vert.UV[0], vert.UV[1]); newVertices.Add(newVertex); } } newMesh.vertices = newVertices.ToArray(); newMesh.faces = newFaces.ToArray(); newMesh.faceMarks = newFaceMarks.ToArray(); return(newMesh); }
private void FillVertexBuffer(Mesh animationMesh, List <remVertex> vertexList, float[][] vertexWeights, byte[][] vertexBoneIndices, int selectedBoneIdx) { using (DataStream vertexStream = animationMesh.LockVertexBuffer(LockFlags.None)) { Color4 col = new Color4(1f, 1f, 1f); for (int j = 0; j < vertexList.Count; j++) { remVertex vertex = vertexList[j]; Vector3 position = vertex.Position; Vector3 normal = vertex.Normal; float[] boneWeights = vertexWeights[j]; vertexStream.Write(position.X); vertexStream.Write(position.Y); vertexStream.Write(position.Z); vertexStream.Write(boneWeights[0]); vertexStream.Write(boneWeights[1]); vertexStream.Write(boneWeights[2]); vertexStream.Write(vertexBoneIndices[j][0]); vertexStream.Write(vertexBoneIndices[j][1]); vertexStream.Write(vertexBoneIndices[j][2]); vertexStream.Write(vertexBoneIndices[j][3]); vertexStream.Write(normal.X); vertexStream.Write(normal.Y); vertexStream.Write(normal.Z); if (selectedBoneIdx >= 0) { col.Red = 0f; col.Green = 0f; col.Blue = 0f; byte[] boneIndices = vertexBoneIndices[j]; for (int k = 0; k < boneIndices.Length; k++) { if (boneIndices[k] == 0xFF) { continue; } byte boneIdx = boneIndices[k]; if (boneIdx == selectedBoneIdx) { /* switch (cols) * { * case WeightsColourPreset.Greyscale: * col.Red = col.Green = col.Blue = boneWeights[k]; * break; * case WeightsColourPreset.Metal: * col.Red = boneWeights[k] > 0.666f ? 1f : boneWeights[k] * 1.5f; * col.Green = boneWeights[k] * boneWeights[k] * boneWeights[k]; * break; * case WeightsColourPreset.Rainbow:*/ if (boneWeights[k] > 0.75f) { col.Red = 1f; col.Green = (1f - boneWeights[k]) * 2f; col.Blue = 0f; } else if (boneWeights[k] > 0.5f) { col.Red = 1f; col.Green = (1f - boneWeights[k]) * 2f; col.Blue = 0f; } else if (boneWeights[k] > 0.25f) { col.Red = (boneWeights[k] - 0.25f) * 4f; col.Green = 1f; col.Blue = 0f; } else { col.Green = boneWeights[k] * 4f; col.Blue = 1f - boneWeights[k] * 4f; } /* break; * }*/ break; } } } vertexStream.Write(col.ToArgb()); vertexStream.Write(vertex.UV[0]); vertexStream.Write(vertex.UV[1]); } animationMesh.UnlockVertexBuffer(); } }
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); }
static void CalculateNormals(List <Tuple <List <int>, List <remVertex> > > pairList, float threshold) { if (threshold < 0) { VertexRef[][] vertRefArray = new VertexRef[pairList.Count][]; for (int i = 0; i < pairList.Count; i++) { List <remVertex> vertList = pairList[i].Item2; vertRefArray[i] = new VertexRef[vertList.Count]; for (int j = 0; j < vertList.Count; j++) { remVertex vert = vertList[j]; VertexRef vertRef = new VertexRef(); vertRef.vert = vert; vertRef.norm = new Vector3(); vertRefArray[i][j] = vertRef; } } for (int i = 0; i < pairList.Count; i++) { List <int> faceList = pairList[i].Item1; int numFaces = faceList.Count / 3; for (int j = 0; j < numFaces; j++) { int[] vertIdx = new int[3] { faceList[j * 3 + 0], faceList[j * 3 + 1], faceList[j * 3 + 2] }; Vector3 v1 = vertRefArray[i][vertIdx[1]].vert.Position - vertRefArray[i][vertIdx[2]].vert.Position; Vector3 v2 = vertRefArray[i][vertIdx[0]].vert.Position - vertRefArray[i][vertIdx[2]].vert.Position; Vector3 norm = Vector3.Cross(v2, v1); norm.Normalize(); for (int k = 0; k < vertIdx.Length; k++) { vertRefArray[i][vertIdx[k]].norm += norm; } } } for (int i = 0; i < vertRefArray.Length; i++) { for (int j = 0; j < vertRefArray[i].Length; j++) { Vector3 norm = vertRefArray[i][j].norm; norm.Normalize(); vertRefArray[i][j].vert.Normal = norm; } } } else { int vertCount = 0; for (int i = 0; i < pairList.Count; i++) { vertCount += pairList[i].Item2.Count; } VertexRefComparerX vertRefComparerX = new VertexRefComparerX(); List <VertexRef> vertRefListX = new List <VertexRef>(vertCount); VertexRef[][] vertRefArray = new VertexRef[pairList.Count][]; for (int i = 0; i < pairList.Count; i++) { var vertList = pairList[i].Item2; vertRefArray[i] = new VertexRef[vertList.Count]; for (int j = 0; j < vertList.Count; j++) { remVertex vert = vertList[j]; VertexRef vertRef = new VertexRef(); vertRef.vert = vert; vertRef.norm = new Vector3(); vertRefArray[i][j] = vertRef; vertRefListX.Add(vertRef); } } vertRefListX.Sort(vertRefComparerX); for (int i = 0; i < pairList.Count; i++) { var faceList = pairList[i].Item1; int numFaces = faceList.Count / 3; for (int j = 0; j < numFaces; j++) { int[] vertIdx = new int[3] { faceList[j * 3 + 0], faceList[j * 3 + 1], faceList[j * 3 + 2] }; Vector3 v1 = vertRefArray[i][vertIdx[1]].vert.Position - vertRefArray[i][vertIdx[2]].vert.Position; Vector3 v2 = vertRefArray[i][vertIdx[0]].vert.Position - vertRefArray[i][vertIdx[2]].vert.Position; Vector3 norm = Vector3.Cross(v2, v1); norm.Normalize(); for (int k = 0; k < vertIdx.Length; k++) { vertRefArray[i][vertIdx[k]].norm += norm; } } } float squaredThreshold = threshold * threshold; while (vertRefListX.Count > 0) { VertexRef vertRef = vertRefListX[vertRefListX.Count - 1]; List <VertexRef> dupList = new List <VertexRef>(); List <VertexRef> dupListX = GetAxisDups(vertRef, vertRefListX, 0, threshold, null); foreach (VertexRef dupRef in dupListX) { if (((vertRef.vert.Position.Y - dupRef.vert.Position.Y) <= threshold) && ((vertRef.vert.Position.Z - dupRef.vert.Position.Z) <= threshold) && ((vertRef.vert.Position - dupRef.vert.Position).LengthSquared() <= squaredThreshold)) { dupList.Add(dupRef); } } vertRefListX.RemoveAt(vertRefListX.Count - 1); Vector3 norm = vertRef.norm; foreach (VertexRef dupRef in dupList) { norm += dupRef.norm; vertRefListX.Remove(dupRef); } norm.Normalize(); vertRef.vert.Normal = norm; foreach (VertexRef dupRef in dupList) { dupRef.vert.Normal = norm; vertRefListX.Remove(dupRef); } } } }
public static void CopyBonesNear(List <remVertex> src, List <remVertex> dest, List <remBoneWeights> destBones) { Dictionary <remBoneWeights, Tuple <List <int>, List <float> > > boneTranslation = new Dictionary <remBoneWeights, Tuple <List <int>, List <float> > >(destBones.Count); for (int i = 0; i < dest.Count; i++) { var destVert = dest[i]; var destPos = destVert.Position; float minDistSq = Single.MaxValue; int nearestVertIdx = -1; for (int j = 0; j < src.Count; j++) { remVertex srcVert = src[j]; var srcPos = srcVert.Position; float[] diff = new float[] { destPos[0] - srcPos[0], destPos[1] - srcPos[1], destPos[2] - srcPos[2] }; float distSq = (diff[0] * diff[0]) + (diff[1] * diff[1]) + (diff[2] * diff[2]); if (distSq < minDistSq) { minDistSq = distSq; nearestVertIdx = j; } } int numInfluences = 0; foreach (remBoneWeights srcBone in destBones) { for (int k = 0; k < srcBone.numVertIdxWts; k++) { if (srcBone.vertexIndices[k] == nearestVertIdx) { List <int> idxList; List <float> weightList; Tuple <List <int>, List <float> > destLists; if (!boneTranslation.TryGetValue(srcBone, out destLists)) { idxList = new List <int>(); weightList = new List <float>(); destLists = new Tuple <List <int>, List <float> >(idxList, weightList); boneTranslation.Add(srcBone, destLists); } else { idxList = destLists.Item1; weightList = destLists.Item2; } idxList.Add(i); weightList.Add(srcBone.vertexWeights[k]); numInfluences++; break; } } if (numInfluences == 4) { break; } } } foreach (var boneListPair in boneTranslation) { remBoneWeights srcBone = boneListPair.Key; Tuple <List <int>, List <float> > destLists = boneListPair.Value; srcBone.vertexIndices = destLists.Item1.ToArray(); srcBone.vertexWeights = destLists.Item2.ToArray(); } }
private static remMESCsection ReadMeshes(string sectionName, int sectionLength, int numMeshes, byte[] sectionBuffer) { remMESCsection meshSec = new remMESCsection(numMeshes); int secBufIdx = 0; for (int subSection = 0; subSection < numMeshes; subSection++) { byte[] type = new byte[4] { sectionBuffer[secBufIdx + 0], sectionBuffer[secBufIdx + 1], sectionBuffer[secBufIdx + 2], sectionBuffer[secBufIdx + 3] }; int length = BitConverter.ToInt32(sectionBuffer, secBufIdx + 4); remMesh mesh = new remMesh(5); Trace.Assert(TypeCheck(remMesh.ClassType, type)); mesh.frame = GetIdentifier(sectionBuffer, secBufIdx + 8); int numMats = BitConverter.ToInt32(sectionBuffer, secBufIdx + 8 + 256); mesh.name = GetIdentifier(sectionBuffer, secBufIdx + 8 + 256 + 4); int numFaces = BitConverter.ToInt32(sectionBuffer, secBufIdx + 8 + 256 + 4 + 256); int numVertices = BitConverter.ToInt32(sectionBuffer, secBufIdx + 8 + 256 + 4 + 256 + 4); for (int i = 0; i < mesh.unknown.Length; i++) { mesh.unknown[i] = BitConverter.ToInt32(sectionBuffer, secBufIdx + 8 + 256 + 4 + 256 + 8 + i * 4); } for (int i = 0; i < numMats; i++) { remId mat = GetIdentifier(sectionBuffer, secBufIdx + 8 + 256 + 4 + 256 + 4 * 4 + i * 256); mesh.AddMaterial(mat); } mesh.vertices = new remVertex[numVertices]; int vertBufIdx = secBufIdx + 8 + 256 + 4 + 256 + 4 * 4 + mesh.numMats * 256; for (int i = 0; i < numVertices; i++) { remVertex vertex = new remVertex(); vertex.Position = new Vector3(); vertex.Position[0] = BitConverter.ToSingle(sectionBuffer, vertBufIdx + 0); vertex.Position[1] = BitConverter.ToSingle(sectionBuffer, vertBufIdx + 4); vertex.Position[2] = BitConverter.ToSingle(sectionBuffer, vertBufIdx + 8); vertex.UV = new Vector2(); vertex.UV[0] = BitConverter.ToSingle(sectionBuffer, vertBufIdx + 12); vertex.UV[1] = BitConverter.ToSingle(sectionBuffer, vertBufIdx + 16); vertex.Normal = new Vector3(); vertex.Normal[0] = BitConverter.ToSingle(sectionBuffer, vertBufIdx + 20); vertex.Normal[1] = BitConverter.ToSingle(sectionBuffer, vertBufIdx + 24); vertex.Normal[2] = BitConverter.ToSingle(sectionBuffer, vertBufIdx + 28); vertex.RGBA = new Color4(BitConverter.ToInt32(sectionBuffer, vertBufIdx + 32)); mesh.vertices[i] = vertex; vertBufIdx += 36; } mesh.faces = new int[numFaces * 3]; int faceBufIdx = vertBufIdx; for (int i = 0; i < numFaces; i++) { mesh.faces[i * 3 + 0] = BitConverter.ToInt32(sectionBuffer, faceBufIdx + 0); mesh.faces[i * 3 + 1] = BitConverter.ToInt32(sectionBuffer, faceBufIdx + 4); mesh.faces[i * 3 + 2] = BitConverter.ToInt32(sectionBuffer, faceBufIdx + 8); faceBufIdx += 12; } mesh.faceMarks = new int[numFaces]; int faceExtraIdx = faceBufIdx; for (int i = 0; i < numFaces; i++) { mesh.faceMarks[i] = BitConverter.ToInt32(sectionBuffer, faceExtraIdx); faceExtraIdx += 4; } meshSec.AddChild(mesh); secBufIdx += length; } if (secBufIdx != sectionLength) { Report.ReportLog("Warning! MESC section has wrong length."); } return(meshSec); }
private void ConvertMeshes(List <remMesh> meshes, remParser parser) { MeshList = new List <ImportedMesh>(meshes.Count); MaterialList = new List <ImportedMaterial>(meshes.Count); TextureList = new List <ImportedTexture>(parser.MATC.Count); foreach (remMesh mesh in meshes) { ImportedMesh iMesh = new ImportedMesh(); MeshList.Add(iMesh); iMesh.BoneList = new List <ImportedBone>(); Dictionary <remId, byte> boneDic = new Dictionary <remId, byte>(); remSkin skin = rem.FindSkin(mesh.name, parser.SKIC); rem.Mesh convertedMesh = new rem.Mesh(mesh, skin); iMesh.SubmeshList = new List <ImportedSubmesh>(convertedMesh.Count); remBone meshFrame = rem.FindFrame(mesh.frame, parser.BONC.rootFrame); ImportedFrame iFrame = ImportedHelpers.FindFrame(mesh.frame, FrameList[0]); float s = (float)Math.Round(Math.Abs(meshFrame.matrix.M11), 5); iFrame.Name = iMesh.Name = mesh.name + (s != 1f ? "(Scale=" + s.ToString() + ")" : String.Empty); foreach (rem.Submesh submesh in convertedMesh) { ImportedSubmesh iSubmesh = new ImportedSubmesh(); iMesh.SubmeshList.Add(iSubmesh); remMaterial mat = rem.FindMaterial(submesh.MaterialName, parser.MATC); if (mat != null) { iSubmesh.Material = mat.name; ImportedMaterial iMat = ImportedHelpers.FindMaterial(iSubmesh.Material, MaterialList); if (iMat == null) { iMat = new ImportedMaterial(); MaterialList.Add(iMat); iMat.Name = iSubmesh.Material; iMat.Diffuse = new Color4(mat.diffuse); iMat.Ambient = new Color4(mat.ambient); iMat.Specular = new Color4(mat.specular); iMat.Emissive = new Color4(mat.emissive); iMat.Power = mat.specularPower; iMat.Textures = new string[4] { String.Empty, String.Empty, String.Empty, String.Empty }; if (mat.texture != null) { iMat.Textures[0] = mat.texture; if (ImportedHelpers.FindTexture(iMat.Textures[0], TextureList) == null) { try { ImportedTexture iTex = rem.ImportedTexture(mat.texture, parser.RemPath, true); TextureList.Add(iTex); } catch { Report.ReportLog("cant read texture " + iMat.Textures[0]); } } } } } List <Tuple <byte, float> >[] iSkin = new List <Tuple <byte, float> > [submesh.numVertices]; for (int i = 0; i < submesh.numVertices; i++) { iSkin[i] = new List <Tuple <byte, float> >(4); } List <remBoneWeights> boneList = submesh.BoneList; if (boneList != null) { if (iMesh.BoneList.Capacity < boneList.Count) { iMesh.BoneList.Capacity += boneList.Count; } foreach (remBoneWeights boneWeights in boneList) { byte idx; if (!boneDic.TryGetValue(boneWeights.bone, out idx)) { ImportedBone iBone = new ImportedBone(); iMesh.BoneList.Add(iBone); iBone.Name = boneWeights.bone; Vector3 scale, translate; Quaternion rotate; meshFrame.matrix.Decompose(out scale, out rotate, out translate); scale.X = Math.Abs(scale.X); scale.Y = Math.Abs(scale.Y); scale.Z = Math.Abs(scale.Z); iBone.Matrix = Matrix.Scaling(1f, 1f, -1f) * Matrix.Invert(meshFrame.matrix) * Matrix.Scaling(scale) * boneWeights.matrix; boneDic.Add(boneWeights.bone, idx = (byte)boneDic.Count); } for (int i = 0; i < boneWeights.numVertIdxWts; i++) { iSkin[boneWeights.vertexIndices[i]].Add(new Tuple <byte, float>(idx, boneWeights.vertexWeights[i])); } } } iSubmesh.VertexList = new List <ImportedVertex>(submesh.numVertices); for (int i = 0; i < submesh.numVertices; i++) { remVertex vert = submesh.VertexList[i]; ImportedVertex iVert = new ImportedVertex(); iSubmesh.VertexList.Add(iVert); iVert.Position = new Vector3(vert.Position.X, vert.Position.Z, -vert.Position.Y); iVert.Normal = new Vector3(vert.Normal.X, vert.Normal.Z, -vert.Normal.Y); iVert.UV = new float[] { vert.UV[0], vert.UV[1] }; iVert.BoneIndices = new byte[4]; iVert.Weights = new float[4]; for (int j = 0; j < 4; j++) { if (j < iSkin[i].Count) { Tuple <byte, float> vertIdxWeight = iSkin[i][j]; iVert.BoneIndices[j] = vertIdxWeight.Item1; iVert.Weights[j] = vertIdxWeight.Item2; } else { iVert.BoneIndices[j] = 0xFF; } } } iSubmesh.FaceList = rem.ImportedFaceList(submesh.FaceList); } } }