public static remSkin CreateBoneList(ImportedMesh mesh, Matrix lMeshMatrixInv) { if (mesh.BoneList == null || mesh.BoneList.Count == 0) { return null; } Dictionary<int, float>[] boneDic = new Dictionary<int, float>[mesh.BoneList.Count]; for (int i= 0; i < mesh.BoneList.Count; i++) { boneDic[i] = new Dictionary<int, float>(); } int vertexOffset = 0; foreach (ImportedSubmesh submesh in mesh.SubmeshList) { List<ImportedVertex> vertices = submesh.VertexList; for (int i = 0; i < vertices.Count; i++) { ImportedVertex vert = vertices[i]; for (int j = 0; j < vert.BoneIndices.Length; j++) { if (vert.BoneIndices[j] == 0xFF) continue; boneDic[vert.BoneIndices[j]].Add(vertexOffset + i, vert.Weights[j]); } } vertexOffset += vertices.Count; } remSkin remBoneList = new remSkin(mesh.BoneList.Count); remBoneList.mesh = new remId(mesh.Name); Vector3 scale, translate; Quaternion rotate; lMeshMatrixInv.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); Matrix combinedCorrection = Matrix.Scaling(-1f / scale.X, 1f / scale.Y, -1f / scale.Z) * lMeshMatrixInv; for (int i = 0; i < mesh.BoneList.Count; i++) { remBoneWeights boneWeights = new remBoneWeights(); boneWeights.bone = new remId(mesh.BoneList[i].Name); Matrix lMatrix = Matrix.Invert(mesh.BoneList[i].Matrix); boneWeights.matrix = Matrix.Invert(lMatrix * combinedCorrection); boneWeights.vertexIndices = new int[boneDic[i].Count]; boneDic[i].Keys.CopyTo(boneWeights.vertexIndices, 0); boneWeights.vertexWeights = new float[boneDic[i].Count]; boneDic[i].Values.CopyTo(boneWeights.vertexWeights, 0); remBoneList.AddChild(boneWeights); } return remBoneList; }
private float[][] ConvertVertexWeights(List<remVertex> vertexList, int[] vertexIndices, remSkin boneList, out byte[][] vertexBoneIndices) { int numBones = boneList != null ? boneList.Count : 0; float[][] vertexWeights = new float[vertexList.Count][]; vertexBoneIndices = new byte[vertexList.Count][]; for (int j = 0; j < vertexList.Count; j++) { int meshVertIdx = -1; for (int k = 0; k < vertexIndices.Length; k++) { if (vertexIndices[k] == j) { meshVertIdx = k; break; } } if (meshVertIdx < 0) { throw new Exception("ConvertVertexWeights : index not found"); } vertexWeights[j] = new float[4]; vertexBoneIndices[j] = new byte[4]; int weightIdx = 0; for (int k = 0; k < numBones; k++) { remBoneWeights bone = boneList[k]; for (int l = 0; l < bone.numVertIdxWts; l++) { if (bone.vertexIndices[l] == meshVertIdx) { vertexBoneIndices[j][weightIdx] = (byte)k; if (weightIdx < 3) { vertexWeights[j][weightIdx++] = bone.vertexWeights[l]; } else { vertexWeights[j][3] = 1f - vertexWeights[j][0] - vertexWeights[j][1] - vertexWeights[j][2]; } break; } } } } return vertexWeights; }
private static remSKICsection ReadSkin(string sectionName, int sectionLength, int numSkins, byte[] sectionBuffer) { remSKICsection skinSec = new remSKICsection(numSkins); int secBufIdx = 0; for (int subSection = 0; subSection < numSkins; 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); remId mesh = GetIdentifier(sectionBuffer, secBufIdx+8); int numWeights = BitConverter.ToInt32(sectionBuffer, secBufIdx+8+256); remSkin skin = new remSkin(numWeights); Trace.Assert(TypeCheck(remSkin.ClassType, type)); skin.mesh = mesh; int weightBufIdx = secBufIdx+8+256+4; for (int weightIdx = 0; weightIdx < numWeights; weightIdx++) { remBoneWeights weights = new remBoneWeights(); weights.bone = GetIdentifier(sectionBuffer, weightBufIdx); weightBufIdx += 256; int numVertIdxWts = BitConverter.ToInt32(sectionBuffer, weightBufIdx); weightBufIdx += 4; Matrix matrix = new Matrix(); for (int i = 0; i < 4; i++) { Vector4 row = new Vector4(); for (int j = 0; j < 4; j++) { row[j] = BitConverter.ToSingle(sectionBuffer, weightBufIdx); weightBufIdx += 4; } matrix.set_Rows(i, row); } weights.matrix = matrix; weights.vertexIndices = new int[numVertIdxWts]; for (int i = 0; i < numVertIdxWts; i++) { weights.vertexIndices[i] = BitConverter.ToInt32(sectionBuffer, weightBufIdx); weightBufIdx += 4; } weights.vertexWeights = new float[weights.numVertIdxWts]; for (int i = 0; i < numVertIdxWts; i++) { weights.vertexWeights[i] = BitConverter.ToSingle(sectionBuffer, weightBufIdx); weightBufIdx += 4; } skin.AddChild(weights); } skinSec.AddChild(skin); secBufIdx += length; } if (secBufIdx != sectionLength) Report.ReportLog("Warning! SKIC section has wrong length."); return skinSec; }