static PrimitiveManager DecodePrimitivesWeighted(NodeEntry n, GeometryEntry geo, SkinEntry skin, SceneEntry scene, InfluenceManager infManager, ref string Error) { PrimitiveManager manager = DecodePrimitives(n._matrix, geo); MDL0BoneNode[] boneList; MDL0BoneNode bone = null; int boneCount; string[] jointStrings = null; byte* pCmd = stackalloc byte[4]; int cmdCount = skin._weightInputs.Count; float weight = 0; float* pWeights = null; Vector3* pVert = null, pNorms = null; ushort* pVInd = (ushort*)manager._indices.Address; List<Vertex3> vertList = new List<Vertex3>(skin._weightCount); Matrix* pMatrix = null; UnsafeBuffer remap = new UnsafeBuffer(skin._weightCount * 2); ushort* pRemap = (ushort*)remap.Address; pNorms = (Vector3*)manager._faceData[1].Address; manager._vertices = vertList; //Find vertex source foreach (SourceEntry s in geo._sources) if (s._id == geo._verticesInput._source) { pVert = (Vector3*)((UnsafeBuffer)s._arrayData).Address; break; } //Find joint source foreach (InputEntry inp in skin._jointInputs) if (inp._semantic == SemanticType.JOINT) { foreach (SourceEntry src in skin._sources) if (src._id == inp._source) { jointStrings = src._arrayData as string[]; break; } } else if (inp._semantic == SemanticType.INV_BIND_MATRIX) { foreach (SourceEntry src in skin._sources) if (src._id == inp._source) { pMatrix = (Matrix*)((UnsafeBuffer)src._arrayData).Address; break; } } Error = "There was a problem creating the list of bones for geometry entry " + geo._name; //Populate bone list boneCount = jointStrings.Length; boneList = new MDL0BoneNode[boneCount]; for (int i = 0; i < boneCount; i++) boneList[i] = scene.FindNode(jointStrings[i])._node as MDL0BoneNode; //Build command list foreach (InputEntry inp in skin._weightInputs) { switch (inp._semantic) { case SemanticType.JOINT: pCmd[inp._offset] = 1; break; case SemanticType.WEIGHT: pCmd[inp._offset] = 2; //Get weight source foreach (SourceEntry src in skin._sources) if (src._id == inp._source) { pWeights = (float*)((UnsafeBuffer)src._arrayData).Address; break; } break; default: pCmd[inp._offset] = 0; break; } } Error = "There was a problem creating vertex influences for geometry entry " + geo._name; //Build vertex list and remap table for (int i = 0; i < skin._weightCount; i++) { //Create influence int iCount = skin._weights[i].Length / cmdCount; Influence inf = new Influence(/*iCount*/); fixed (int* p = skin._weights[i]) { int* iPtr = p; for (int x = 0; x < iCount; x++) { for (int z = 0; z < cmdCount; z++, iPtr++) if (pCmd[z] == 1) bone = boneList[*iPtr]; else if (pCmd[z] == 2) weight = pWeights[*iPtr]; inf._weights.Add(new BoneWeight(bone, weight)); } } inf.CalcMatrix(); Error = "There was a problem creating a vertex from the geometry entry " + geo._name + ".\nMake sure that all the vertices are weighted properly."; Vertex3 v; if (inf._weights.Count > 1) { //Match with manager inf = infManager.FindOrCreate(inf, true); v = new Vertex3(n._matrix * skin._bindMatrix * pVert[i], inf); //World position } else { bone = inf._weights[0].Bone; v = new Vertex3(n._matrix * bone._inverseBindMatrix * skin._bindMatrix * pVert[i], bone); //Local position } ushort index = 0; while (index < vertList.Count) { if (v.Equals(vertList[index])) break; index++; } if (index == vertList.Count) vertList.Add(v); pRemap[i] = index; } Error = "There was a problem fixing normal rotations for geometry entry " + geo._name; //Remap vertex indices and fix normals for (int i = 0; i < manager._pointCount; i++, pVInd++) { *pVInd = pRemap[*pVInd]; Vertex3 v = null; if (*pVInd < vertList.Count) v = vertList[*pVInd]; if (v != null && v._matrixNode != null) if (v._matrixNode.Weights.Count > 1) pNorms[i] = skin._bindMatrix.GetRotationMatrix() * pNorms[i]; else pNorms[i] = skin._bindMatrix.GetRotationMatrix() * v._matrixNode.Weights[0].Bone._inverseBindMatrix.GetRotationMatrix() * pNorms[i]; } remap.Dispose(); return manager; }
public override bool OnInitialize() { base.OnInitialize(); _billboardBones = new List<MDL0BoneNode>(); _errors = new List<string>(); _influences = new InfluenceManager(); MDL0Header* header = Header; if (_name == null && header->StringOffset != 0) _name = header->ResourceString; MDL0Props* props = header->Properties; _version = header->_header._version; _scalingRule = props->_scalingRule; _texMtxMode = props->_texMatrixMode; _numFacepoints = props->_numVertices; _numFaces = props->_numFaces; _origPathOffset = props->_origPathOffset; _numNodes = props->_numNodes; _needsNrmMtxArray = props->_needNrmMtxArray != 0; _needsTexMtxArray = props->_needTexMtxArray != 0; _min = props->_minExtents; _max = props->_maxExtents; _enableExtents = props->_enableExtents != 0; _envMtxMode = props->_envMtxMode; if (props->_origPathOffset > 0 && props->_origPathOffset < header->_header._size) _originalPath = props->OrigPath; (_userEntries = new UserDataCollection()).Read(header->UserData); return true; }