public odfVertex Clone() { odfVertex newVert = new odfVertex(); newVert.Position = Position; newVert.Weights = (float[])Weights.Clone(); newVert.Normal = Normal; newVert.BoneIndices = (byte[])BoneIndices.Clone(); newVert.UV = UV; return(newVert); }
public static List <odfVertex> ParseVertexList(BinaryReader reader, int numVertices) { List <odfVertex> vertList = new List <odfVertex>(numVertices); for (int vertIdx = 0; vertIdx < numVertices; vertIdx++) { odfVertex vertex = new odfVertex(); vertex.Position = reader.ReadVector3(); vertex.Weights = reader.ReadSingleArray(4); vertex.Normal = reader.ReadVector3(); vertex.BoneIndices = reader.ReadBytes(4); vertex.UV = reader.ReadVector2(); vertList.Add(vertex); } return(vertList); }
public static void CopyNormalsNear(List <odfVertex> src, List <odfVertex> dest) { for (int i = 0; i < dest.Count; i++) { var destVert = dest[i]; var destPos = destVert.Position; float minDistSq = Single.MaxValue; odfVertex nearestVert = null; foreach (odfVertex 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 void CalculateNormals(List <Tuple <List <odfFace>, List <odfVertex> > > pairList, float threshold) { if (threshold < 0) { VertexRef[][] vertRefArray = new VertexRef[pairList.Count][]; for (int i = 0; i < pairList.Count; i++) { List <odfVertex> vertList = pairList[i].Item2; vertRefArray[i] = new VertexRef[vertList.Count]; for (int j = 0; j < vertList.Count; j++) { odfVertex 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 <odfFace> faceList = pairList[i].Item1; for (int j = 0; j < faceList.Count; j++) { odfFace face = faceList[j]; Vector3 v1 = vertRefArray[i][face.VertexIndices[1]].vert.Position - vertRefArray[i][face.VertexIndices[2]].vert.Position; Vector3 v2 = vertRefArray[i][face.VertexIndices[0]].vert.Position - vertRefArray[i][face.VertexIndices[2]].vert.Position; Vector3 norm = Vector3.Cross(v2, v1); norm.Normalize(); for (int k = 0; k < face.VertexIndices.Length; k++) { vertRefArray[i][face.VertexIndices[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++) { odfVertex 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; for (int j = 0; j < faceList.Count; j++) { odfFace face = faceList[j]; Vector3 v1 = vertRefArray[i][face.VertexIndices[1]].vert.Position - vertRefArray[i][face.VertexIndices[2]].vert.Position; Vector3 v2 = vertRefArray[i][face.VertexIndices[0]].vert.Position - vertRefArray[i][face.VertexIndices[2]].vert.Position; Vector3 norm = Vector3.Cross(v2, v1); norm.Normalize(); for (int k = 0; k < face.VertexIndices.Length; k++) { vertRefArray[i][face.VertexIndices[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 <odfVertex> src, List <odfVertex> dest, odfBoneList destBones) { Dictionary <odfBone, Tuple <List <int>, List <float> > > boneTranslation = new Dictionary <odfBone, 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++) { odfVertex 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 (odfBone srcBone in destBones) { for (int k = 0; k < srcBone.NumberIndices; k++) { if (srcBone.VertexIndexArray[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.WeightArray[k]); numInfluences++; break; } } if (numInfluences == 4) { break; } } } foreach (var boneListPair in boneTranslation) { odfBone srcBone = boneListPair.Key; int oldLength = srcBone.VertexIndexArray.Length; Tuple <List <int>, List <float> > destLists = boneListPair.Value; srcBone.VertexIndexArray = destLists.Item1.ToArray(); srcBone.WeightArray = destLists.Item2.ToArray(); if (srcBone.VertexIndexArray.Length != oldLength) { srcBone.AlwaysZero24perIndex = new byte[24 * srcBone.VertexIndexArray.Length]; } } }
public static odfBoneList CreateBoneList(ObjectID id, ObjectID meshFrameId, odfSubmesh submesh, List <ImportedBone> boneList, Matrix lMeshMatrixInv, odfFrame rootFrame) { if (boneList == null || boneList.Count == 0) { return(null); } Dictionary <byte, Tuple <byte, odfBone> > boneDic = new Dictionary <byte, Tuple <byte, odfBone> >(boneList.Count); Tuple <List <int>, List <float> >[] newBoneListComponents = new Tuple <List <int>, List <float> > [boneList.Count]; int boneframeNotFound = 0; for (int i = 0; i < submesh.NumVertices; i++) { odfVertex vert = submesh.VertexList[i]; for (int j = 0; j < vert.BoneIndices.Length; j++) { byte boneIdx = vert.BoneIndices[j]; if (boneIdx == 0xFF) { continue; } Tuple <byte, odfBone> boneDesc; odfBone newBone; if (!boneDic.TryGetValue(boneIdx, out boneDesc)) { odfFrame boneFrame = odf.FindFrame(boneList[boneIdx].Name, rootFrame); if (boneFrame == null) { boneframeNotFound++; continue; } newBone = new odfBone(boneFrame.Id); newBone.Matrix = boneList[boneIdx].Matrix; boneDesc = new Tuple <byte, odfBone>((byte)boneDic.Count, newBone); boneDic.Add(boneIdx, boneDesc); newBoneListComponents[boneDesc.Item1] = new Tuple <List <int>, List <float> >(new List <int>(200), new List <float>(200)); } else { newBone = boneDesc.Item2; } byte newBoneIdx = boneDesc.Item1; List <int> newBoneIdxList = newBoneListComponents[newBoneIdx].Item1; newBoneIdxList.Add(i); List <float> newBoneWeightList = newBoneListComponents[newBoneIdx].Item2; newBoneWeightList.Add(vert.Weights[j]); } } if (boneDic.Count == 0) { Report.ReportLog(submesh.ToString() + ": all bones dropped because of missing skeleton."); return(null); } odfBoneList newBoneList = new odfBoneList(new ObjectName(String.Empty, null), id, boneDic.Count); newBoneList.MeshFrameId = meshFrameId; newBoneList.SubmeshId = submesh.Id; newBoneList.AlwaysZero4 = new byte[4]; foreach (Tuple <byte, odfBone> boneDesc in boneDic.Values) { byte newBoneIdx = boneDesc.Item1; List <int> newBoneIdxList = newBoneListComponents[newBoneIdx].Item1; List <float> newBoneWeightList = newBoneListComponents[newBoneIdx].Item2; odfBone newBone = boneDesc.Item2; newBone.AlwaysZero24perIndex = new byte[24 * newBoneIdxList.Count]; newBone.VertexIndexArray = newBoneIdxList.ToArray(); newBone.WeightArray = newBoneWeightList.ToArray(); Matrix lMatrix = Matrix.Invert(newBone.Matrix); newBone.Matrix = Matrix.Invert(lMatrix * lMeshMatrixInv); newBoneList.AddChild(newBone); } if (boneframeNotFound > 0) { Report.ReportLog(submesh.ToString() + ": " + boneframeNotFound + " bone(s) because of missing boneframe(s) dropped."); } return(newBoneList); }
public static odfMesh CreateMesh(WorkspaceMesh mesh, int subMeshFormat, 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]; odfMesh newMesh = new odfMesh(new ObjectName(String.Empty, null), null, numSubmeshes); for (int i = 0, submeshIdx = 0; i < numSubmeshes; i++, submeshIdx++) { while (!mesh.isSubmeshEnabled(mesh.SubmeshList[submeshIdx])) { submeshIdx++; } ImportedSubmesh submesh = mesh.SubmeshList[submeshIdx]; odfSubmesh newSubmesh = new odfSubmesh(new ObjectName(String.Empty, null), null, subMeshFormat); newMesh.AddChild(newSubmesh); newSubmesh.MaterialId = ObjectID.INVALID; materialNames[i] = submesh.Material; indices[i] = submesh.Index; worldCoords[i] = submesh.WorldCoords; replaceSubmeshesOption[i] = mesh.isSubmeshReplacingOriginal(mesh.SubmeshList[submeshIdx]); List <ImportedVertex> vertexList = submesh.VertexList; List <odfVertex> newVertexList = new List <odfVertex>(vertexList.Count); for (int j = 0; j < vertexList.Count; j++) { ImportedVertex vert = vertexList[j]; odfVertex newVertex = new odfVertex(); newVertex.Normal = vert.Normal; newVertex.UV = new Vector2(vert.UV[0], vert.UV[1]); newVertex.Weights = (float[])vert.Weights.Clone(); newVertex.BoneIndices = (byte[])vert.BoneIndices.Clone(); newVertex.Position = vert.Position; newVertexList.Add(newVertex); } newSubmesh.VertexList = newVertexList; List <ImportedFace> faceList = submesh.FaceList; List <odfFace> newFaceList = new List <odfFace>(faceList.Count); for (int j = 0; j < faceList.Count; j++) { int[] vertexIndices = faceList[j].VertexIndices; odfFace newFace = new odfFace(); newFace.VertexIndices = new ushort[3] { (ushort)vertexIndices[0], (ushort)vertexIndices[1], (ushort)vertexIndices[2] }; newFaceList.Add(newFace); } newSubmesh.FaceList = newFaceList; } return(newMesh); }
private void FillVertexBuffer(Mesh animationMesh, List <odfVertex> vertexList, float[][] vertexWeights, int selectedBoneIdx) { using (DataStream vertexStream = animationMesh.LockVertexBuffer(LockFlags.None)) { Color4 col = new Color4(1f, 1f, 1f); 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]; 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(vertex.BoneIndices[0]); vertexStream.Write(vertex.BoneIndices[1]); vertexStream.Write(vertex.BoneIndices[2]); vertexStream.Write(vertex.BoneIndices[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 = vertex.BoneIndices; 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.r = col.g = col.b = boneWeights[k]; * break; * case WeightsColourPreset.Metal: * col.r = boneWeights[k] > 0.666f ? 1f : boneWeights[k] * 1.5f; * col.g = 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(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); }
private void ConvertMeshes(List <odfMesh> meshes, odfParser parser) { MeshList = new List <ImportedMesh>(meshes.Count); MaterialList = new List <ImportedMaterial>(meshes.Count); TextureList = new List <ImportedTexture>(parser.TextureSection != null ? parser.TextureSection.Count : 0); foreach (odfMesh mesh in meshes) { ImportedMesh iMesh = new ImportedMesh(); MeshList.Add(iMesh); iMesh.Name = odf.FindMeshFrame(mesh.Id, parser.FrameSection.RootFrame).Name; iMesh.BoneList = new List <ImportedBone>(); Dictionary <ObjectID, byte> boneDic = new Dictionary <ObjectID, byte>(); iMesh.SubmeshList = new List <ImportedSubmesh>(mesh.Count); foreach (odfSubmesh submesh in mesh) { ImportedSubmesh iSubmesh = new ImportedSubmesh(); iMesh.SubmeshList.Add(iSubmesh); odfMaterial mat = odf.FindMaterialInfo(submesh.MaterialId, parser.MaterialSection); 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 = mat.Diffuse; iMat.Ambient = mat.Ambient; iMat.Specular = mat.Specular; iMat.Emissive = mat.Emissive; iMat.Power = mat.SpecularPower; iMat.Textures = new string[4]; for (int i = 0; i < 4; i++) { if (submesh.TextureIds[i] != ObjectID.INVALID) { odfTexture tex = odf.FindTextureInfo(submesh.TextureIds[i], parser.TextureSection); iMat.Textures[i] = tex.Name; if (ImportedHelpers.FindTexture(iMat.Textures[i], TextureList) == null) { try { odfTextureFile texFile = new odfTextureFile(iMat.Textures[i], Path.GetDirectoryName(parser.ODFPath) + @"\" + iMat.Textures[i]); MemoryStream memStream; int filesize = 0; using (BinaryReader reader = texFile.DecryptFile(ref filesize)) { memStream = new MemoryStream(reader.ReadBytes(filesize)); } ImportedTexture iTex = new ImportedTexture(memStream, iMat.Textures[i]); TextureList.Add(iTex); } catch { Report.ReportLog("cant read texture " + iMat.Textures[i]); } } } else { iMat.Textures[i] = String.Empty; } } } } List <Tuple <byte, float> >[] skin = new List <Tuple <byte, float> > [submesh.NumVertices]; for (int i = 0; i < submesh.NumVertices; i++) { skin[i] = new List <Tuple <byte, float> >(4); } odfBoneList boneList = odf.FindBoneList(submesh.Id, parser.EnvelopeSection); if (boneList != null) { if (iMesh.BoneList.Capacity < boneList.Count) { iMesh.BoneList.Capacity += boneList.Count; } foreach (odfBone bone in boneList) { byte idx; if (!boneDic.TryGetValue(bone.FrameId, out idx)) { ImportedBone iBone = new ImportedBone(); iMesh.BoneList.Add(iBone); iBone.Name = odf.FindFrame(bone.FrameId, parser.FrameSection.RootFrame).Name; iBone.Matrix = bone.Matrix; boneDic.Add(bone.FrameId, idx = (byte)boneDic.Count); } for (int i = 0; i < bone.NumberIndices; i++) { skin[bone.VertexIndexArray[i]].Add(new Tuple <byte, float>(idx, bone.WeightArray[i])); } } } iSubmesh.VertexList = new List <ImportedVertex>(submesh.NumVertices); for (int i = 0; i < submesh.NumVertices; i++) { odfVertex vert = submesh.VertexList[i]; ImportedVertex iVert = new ImportedVertex(); iSubmesh.VertexList.Add(iVert); iVert.Position = vert.Position; iVert.Normal = vert.Normal; 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 < skin[i].Count) { Tuple <byte, float> vertIdxWeight = skin[i][j]; iVert.BoneIndices[j] = vertIdxWeight.Item1; iVert.Weights[j] = vertIdxWeight.Item2; } else { iVert.BoneIndices[j] = 0xFF; } } } iSubmesh.FaceList = new List <ImportedFace>(submesh.NumVertexIndices / 3); foreach (odfFace face in submesh.FaceList) { ImportedFace iFace = new ImportedFace(); iSubmesh.FaceList.Add(iFace); iFace.VertexIndices = new int[3]; for (int i = 0; i < 3; i++) { iFace.VertexIndices[i] = face.VertexIndices[i]; } } } } }