//Increases reference count public Influence AddOrCreateInf(Influence inf) { Influence i = AddOrCreate(inf); i._refCount++; return(i); }
public Influence Clone() { Influence i = new Influence(_weights.Length); _weights.CopyTo(i._weights, 0); return(i); }
public bool Equals(Influence inf) { bool found; if (object.ReferenceEquals(this, inf)) { return(true); } if (_weights.Length != inf._weights.Length) { return(false); } foreach (BoneWeight w1 in _weights) { found = false; foreach (BoneWeight w2 in inf._weights) { if (w1 == w2) { found = true; break; } } if (!found) { return(false); } } return(true); }
public Influence Splice(BoneWeight weight) { Influence i = new Influence(_weights.Length + 1); _weights.CopyTo(i._weights, 0); i._weights[_weights.Length] = weight; return(i); }
public Influence Clone() { Influence i = new Influence(); foreach (BoneWeight b in _weights) { i.AddWeight(new BoneWeight(b.Bone, b.Weight) { Locked = b.Locked }); } return(i); }
public void Remove(Influence inf) { for (int i = 0; i < _influences.Count; i++) { if (object.ReferenceEquals(_influences[i], inf)) { if (inf._refCount-- <= 0) { _influences.RemoveAt(i); } break; } } }
public Influence AddOrCreate(Influence inf) { //Search for influence in list. If it exists, return it. foreach (Influence i in _influences) { if (i.Equals(inf)) { return(i); } } //Not found, add it to the list. _influences.Add(inf); return(inf); }
public void Remove(Influence inf, IMatrixNodeUser user) { for (int i = 0; i < Count; i++) { if (object.ReferenceEquals(_influences[i], inf) && inf.Users.Contains(user)) { inf.Users.Remove(user); if (inf.Users.Count <= 0) { _influences.RemoveAt(i); } break; } } }
public Influence FindOrCreate(Influence inf, bool increaseRefs) { //Search for influence in list. If it exists, return it. foreach (Influence i in _influences) { if (i.Equals(inf)) { return(i); } } //Not found, add it to the list. _influences.Add(inf); if (increaseRefs) { inf._refCount++; } return(inf); }
public static int Compare(Influence i1, Influence i2) { if (i1._weights.Count < i2._weights.Count) { return(-1); } if (i1._weights.Count > i2._weights.Count) { return(1); } if (i1.Users.Count > i2.Users.Count) { return(-1); } if (i1.Users.Count < i2.Users.Count) { return(1); } return(0); }
//public override bool Equals(object obj) //{ // if (obj is Influence) // return Equals(obj as Influence); // return false; //} public static int Compare(Influence i1, Influence i2) { if (i1._weights.Length < i2._weights.Length) { return(-1); } if (i1._weights.Length > i2._weights.Length) { return(1); } if (i1._refCount > i2._refCount) { return(-1); } if (i1._refCount < i2._refCount) { return(1); } return(0); }
public Influence FindOrCreate(Influence inf, bool increaseRefs) { //Search for influence in list. If it exists, return it. foreach (Influence i in _influences) if (i.Equals(inf)) return i; //Not found, add it to the list. _influences.Add(inf); if (increaseRefs) inf._refCount++; return inf; }
public void Remove(Influence inf) { for (int i = 0; i < Count; i++) if (object.ReferenceEquals(_influences[i], inf)) { if (inf._refCount-- <= 0) _influences.RemoveAt(i); break; } }
public Influence Clone() { Influence i = new Influence(); foreach (BoneWeight b in _weights) i._weights.Add(new BoneWeight(b.Bone, b.Weight) { Locked = b.Locked }); return i; }
public bool Equals(Influence inf) { bool found; if (object.ReferenceEquals(this, inf)) return true; if (object.ReferenceEquals(inf, null)) return false; if (_weights.Count != inf._weights.Count) return false; foreach (BoneWeight w1 in _weights) { found = false; foreach (BoneWeight w2 in inf._weights) { if (w1 == w2) { found = true; break; } } if (!found) return false; } return true; }
public static int Compare(Influence i1, Influence i2) { if (i1._weights.Count < i2._weights.Count) return -1; if (i1._weights.Count > i2._weights.Count) return 1; if (i1._refCount > i2._refCount) return -1; if (i1._refCount < i2._refCount) return 1; return 0; }
private void EnumNode(NodeEntry node, ResourceNode parent, SceneEntry scene, MDL0Node model, DecoderShell shell) { MDL0BoneNode bone = null; Influence inf = null; if (node._type == NodeType.JOINT) { Error = "There was a problem creating a new bone."; bone = new MDL0BoneNode(); bone._name = node._name != null ? node._name : node._id; bone._bindState = node._transform; node._node = bone; parent._children.Add(bone); bone._parent = parent; bone.RecalcBindState(); bone.CalcFlags(); foreach (NodeEntry e in node._children) EnumNode(e, bone, scene, model, shell); inf = new Influence(bone); model._influences._influences.Add(inf); } else foreach (NodeEntry e in node._children) EnumNode(e, parent, scene, model, shell); foreach (InstanceEntry inst in node._instances) { if (inst._type == InstanceType.Controller) { foreach (SkinEntry skin in shell._skins) if (skin._id == inst._url) { foreach (GeometryEntry g in shell._geometry) if (g._id == skin._skinSource) { Error = @" There was a problem decoding weighted primitives for the object " + (node._name != null ? node._name : node._id) + ".\nOne or more vertices may not be weighted correctly."; Say("Decoding weighted primitives for " + (g._name != null ? g._name : g._id) + "..."); CreateObject(inst, node, parent, DecodePrimitivesWeighted(node, g, skin, scene, model._influences, ref Error), model, shell); break; } break; } } else if (inst._type == InstanceType.Geometry) { foreach (GeometryEntry g in shell._geometry) if (g._id == inst._url) { Error = "There was a problem decoding unweighted primitives for the object " + (node._name != null ? node._name : node._id) + "."; Say("Decoding unweighted primitives for " + (g._name != null ? g._name : g._id) + "..."); CreateObject(inst, node, parent, DecodePrimitivesUnweighted(node, g), model, shell); break; } } else { foreach (NodeEntry e in shell._nodes) if (e._id == inst._url) EnumNode(e, parent, scene, model, shell); } } }
public static unsafe void PMD2MDL0(MDL0Node model) { model._version = 9; model._isImport = true; Collada._importOptions = BrawlLib.Properties.Settings.Default.ColladaImportOptions; Collada._importOptions._forceCCW = true; Collada._importOptions._fltVerts = true; Collada._importOptions._fltNrms = true; Collada._importOptions._fltUVs = true; model.InitGroups(); List<MDL0BoneNode> BoneCache = new List<MDL0BoneNode>(); int index = 0; if (!String.IsNullOrWhiteSpace(_header._modelNameEnglish)) model.Name = _header._modelNameEnglish; else model.Name = _header._modelName; if (!String.IsNullOrWhiteSpace(_header._commentEnglish)) MessageBox.Show(_header._commentEnglish); else MessageBox.Show(_header._comment); ModelBone parent = null; foreach (ModelBone b in _bones) { MDL0BoneNode bone = new MDL0BoneNode(); if (!String.IsNullOrWhiteSpace(b._boneNameEnglish)) bone._name = b._boneNameEnglish; else bone._name = b._boneName; bone._entryIndex = index++; if (b._parentBoneIndex != ushort.MaxValue) { parent = _bones[b._parentBoneIndex]; foreach (MDL0BoneNode v in model._boneGroup._children) AssignParent(v, b, bone, parent); } else { bone.Parent = model._boneGroup; bone._bindState._scale = new Vector3(1.0f); bone._bindState._translate = new Vector3(b._wPos[0], b._wPos[1], b._wPos[2]); bone._bindState.CalcTransforms(); bone.RecalcBindState(); } BoneCache.Add(bone); } MDL0ShaderNode texSpa = null, tex = null, colorSpa = null, color = null; index = 0; foreach (ModelMaterial m in _materials) { MDL0MaterialNode mn = new MDL0MaterialNode(); mn.Name = "Material" + index++; MDL0MaterialRefNode texRef = null; MDL0MaterialRefNode spaRef = null; if (!String.IsNullOrEmpty(m._textureFileName)) if (m._textureFileName.Contains('*')) { string[] names = m._textureFileName.Split('*'); if (!String.IsNullOrEmpty(names[0])) { texRef = new MDL0MaterialRefNode(); texRef.Name = names[0].Substring(0, names[0].IndexOf('.')); } if (!String.IsNullOrEmpty(names[1])) { spaRef = new MDL0MaterialRefNode(); spaRef.Name = names[1].Substring(0, names[1].IndexOf('.')); spaRef.MapMode = MDL0MaterialRefNode.MappingMethod.EnvCamera; spaRef.UWrapMode = MDL0MaterialRefNode.WrapMode.Clamp; spaRef.VWrapMode = MDL0MaterialRefNode.WrapMode.Clamp; spaRef.Projection = Wii.Graphics.TexProjection.STQ; spaRef.InputForm = Wii.Graphics.TexInputForm.ABC1; spaRef.Coordinates = Wii.Graphics.TexSourceRow.Normals; spaRef.Normalize = true; } } else { texRef = new MDL0MaterialRefNode(); texRef.Name = m._textureFileName.Substring(0, m._textureFileName.IndexOf('.')); texRef.Coordinates = Wii.Graphics.TexSourceRow.TexCoord0; } if (texRef != null) { (texRef._texture = model.FindOrCreateTexture(texRef.Name))._references.Add(texRef); texRef._parent = mn; mn._children.Add(texRef); } if (spaRef != null) { (spaRef._texture = model.FindOrCreateTexture(spaRef.Name))._references.Add(spaRef); spaRef._parent = mn; mn._children.Add(spaRef); } mn._chan1._matColor = new RGBAPixel((byte)(m._diffuseColor[0] * 255), (byte)(m._diffuseColor[1] * 255), (byte)(m._diffuseColor[2] * 255), 255); mn._chan1.ColorMaterialSource = GXColorSrc.Register; if (texRef != null && spaRef != null) { if (texSpa == null) { MDL0ShaderNode n = TexSpaShader; n._parent = model._shadGroup; model._shadList.Add(n); texSpa = n; } mn.ShaderNode = texSpa; } else if (texRef != null) { if (tex == null) { MDL0ShaderNode n = TexShader; n._parent = model._shadGroup; model._shadList.Add(n); tex = n; } mn.ShaderNode = tex; } else if (spaRef != null) { if (colorSpa == null) { MDL0ShaderNode n = ColorSpaShader; n._parent = model._shadGroup; model._shadList.Add(n); colorSpa = n; } mn.ShaderNode = colorSpa; } else { if (color == null) { MDL0ShaderNode n = ColorShader; n._parent = model._shadGroup; model._shadList.Add(n); color = n; } mn.ShaderNode = color; } mn._parent = model._matGroup; model._matList.Add(mn); } model._numFaces = 0; model._numFacepoints = 0; int x = 0; int offset = 0; foreach (ModelMaterial m in _materials) { PrimitiveManager manager = new PrimitiveManager() { _pointCount = (int)m._faceVertCount }; MDL0ObjectNode p = new MDL0ObjectNode() { _manager = manager, _opaMaterial = (MDL0MaterialNode)model._matList[x] }; p._opaMaterial._objects.Add(p); p._manager._vertices = new List<Vertex3>(); p.Name = "polygon" + x++; p._parent = model._objGroup; model._numFaces += p._numFaces = manager._faceCount = manager._pointCount / 3; model._numFacepoints += p._numFacepoints = manager._pointCount; p._manager._indices = new UnsafeBuffer((int)m._faceVertCount * 2); p._manager._faceData[0] = new UnsafeBuffer((int)m._faceVertCount * 12); p._manager._faceData[1] = new UnsafeBuffer((int)m._faceVertCount * 12); p._manager._faceData[4] = new UnsafeBuffer((int)m._faceVertCount * 8); p._manager._dirty[0] = true; p._manager._dirty[1] = true; p._manager._dirty[4] = true; ushort* Indices = (ushort*)p._manager._indices.Address; Vector3* Vertices = (Vector3*)p._manager._faceData[0].Address; Vector3* Normals = (Vector3*)p._manager._faceData[1].Address; Vector2* UVs = (Vector2*)p._manager._faceData[4].Address; manager._triangles = new NewPrimitive((int)m._faceVertCount, BeginMode.Triangles); uint[] pTriarr = manager._triangles._indices; uint pTri = 0; index = 0; List<int> usedVertices = new List<int>(); List<int> vertexIndices = new List<int>(); for (int s = offset, l = 0; l < (int)m._faceVertCount; l++, s++) { ushort i = _faceIndices[s]; ModelVertex mv = _vertices[i]; ushort j = 0; if (!usedVertices.Contains(i)) { Influence inf; BoneWeight weight1 = null, weight2 = null; float weight = ((float)mv._boneWeight / 100.0f).Clamp(0.0f, 1.0f); if (weight > 0.0f && weight < 1.0f) { weight1 = new BoneWeight(BoneCache[mv._boneIndex[0]], weight); weight2 = new BoneWeight(BoneCache[mv._boneIndex[1]], 1.0f - weight); } else if (weight == 0.0f) weight1 = new BoneWeight(BoneCache[mv._boneIndex[1]]); else weight1 = new BoneWeight(BoneCache[mv._boneIndex[0]]); if (weight2 != null) inf = new Influence(new List<BoneWeight> { weight1, weight2 }); else inf = new Influence(new List<BoneWeight> { weight1 }); Vector3 t = new Vector3(); Vertex3 v; t._x = mv._position[0]; t._y = mv._position[1]; t._z = mv._position[2]; if (inf._weights.Count > 1) { inf = model._influences.FindOrCreate(inf, true); inf.CalcMatrix(); v = new Vertex3(t, inf); } else { MDL0BoneNode bone = inf._weights[0].Bone; v = new Vertex3(t * bone._inverseBindMatrix, bone); } p._manager._vertices.Add(v); vertexIndices.Add(usedVertices.Count); usedVertices.Add(i); j = (ushort)(usedVertices.Count - 1); } else j = (ushort)vertexIndices[usedVertices.IndexOf(i)]; *Indices++ = j; pTriarr[pTri++] = (uint)l; *Vertices++ = p._manager._vertices[j]._position; *Normals++ = mv._normal; *UVs++ = mv._texCoord; } model._objList.Add(p); offset += (int)m._faceVertCount; } //Check each polygon to see if it can be rigged to a single influence if (model._objList != null && model._objList.Count != 0) foreach (MDL0ObjectNode p in model._objList) { IMatrixNode node = null; bool singlebind = true; foreach (Vertex3 v in p._manager._vertices) if (v._matrixNode != null) { if (node == null) node = v._matrixNode; if (v._matrixNode != node) { singlebind = false; break; } } if (singlebind && p._matrixNode == null) { //Increase reference count ahead of time for rebuild if (p._manager._vertices[0]._matrixNode != null) p._manager._vertices[0]._matrixNode.ReferenceCount++; foreach (Vertex3 v in p._manager._vertices) if (v._matrixNode != null) v._matrixNode.ReferenceCount--; p._nodeId = -2; //Continued on polygon rebuild } } //foreach (MDL0ObjectNode p in model._objList) // foreach (MDL0MaterialNode m in model._matList) // { // MDL0MaterialNode m2 = p.OpaMaterialNode; // if (m2 == null || m2.ShaderNode != m.ShaderNode || m2.Children.Count != m.Children.Count) // continue; // for (int i = 0; i < m.Children.Count; i++) // if (m2.Children[i].Name != m.Children[i].Name) // continue; // p.OpaMaterialNode = m; // break; // } //for (int i = 0; i < model._matList.Count; i++) // if (((MDL0MaterialNode)model._matList[i])._objects.Count == 0) // model._matList.RemoveAt(i--); model.CleanGroups(); model.BuildFromScratch(null); }
public void Merge(Influence inf, float weight) { _weights[_weights.Length + 1] = new BoneWeight(inf._weights[0].Bone, weight); }
internal void Parse(MDL0Node model) { Influence inf; ModelLinker linker = model._linker; switch (_type) { case MDLResourceType.Definitions: if (linker.Defs != null) ExtractGroup(linker.Defs, typeof(MDL0DefNode)); break; case MDLResourceType.Bones: //Break if there are no bones defined if (linker.Bones == null) break; //Parse bones from raw data (flat list). //Bones re-assign parents in their Initialize block, so parents are true. //Parents must be assigned now as bones will be moved in memory when assigned as children. ExtractGroup(linker.Bones, typeof(MDL0BoneNode)); //Cache flat list linker.BoneCache = _children.ToArray(); //Make sure the node cache is the correct size int highest = 0; foreach (MDL0BoneNode b in linker.BoneCache) if (b._nodeIndex >= linker.NodeCache.Length && b._nodeIndex > highest) highest = b._nodeIndex; if (highest >= linker.NodeCache.Length) linker.NodeCache = new IMatrixNode[highest + 1]; //Reset children so we can rebuild _children.Clear(); //Assign children using each bones' parent offset in case NodeTree is corrupted foreach (MDL0BoneNode b in linker.BoneCache) b._parent._children.Add(b); //Populate node cache MDL0BoneNode bone = null; int index; int count = linker.BoneCache.Length; for (int i = 0; i < count; i++) linker.NodeCache[(bone = linker.BoneCache[i] as MDL0BoneNode)._nodeIndex] = bone; int nullCount = 0; bool nodeTreeError = false; //Now that bones and primary influences have been cached, we can create weighted influences. foreach (ResourcePair p in *linker.Defs) if (p.Name == "NodeTree") { //Double check bone tree using the NodeTree definition. //If the NodeTree is corrupt, the user will be informed that it needs to be rebuilt. byte* pData = (byte*)p.Data; Top: if (*pData == 2) { bone = linker.BoneCache[*(bushort*)(pData + 1)] as MDL0BoneNode; index = *(bushort*)(pData + 3); if (bone.Header->_parentOffset == 0) { if (!_children.Contains(bone)) { nodeTreeError = true; continue; } } else { ResourceNode n = linker.NodeCache[index] as ResourceNode; if (n == null || bone._parent != n || !n._children.Contains(bone)) { nodeTreeError = true; continue; } } pData += 5; goto Top; } } else if (p.Name == "NodeMix") { //Use node mix to create weight groups byte* pData = (byte*)p.Data; Top: switch (*pData) { //Type 3 is for weighted influences case 3: //Get index/count fields index = *(bushort*)(pData + 1); count = pData[3]; //Get data pointer (offset of 4) MDL0NodeType3Entry* nEntry = (MDL0NodeType3Entry*)(pData + 4); //Create influence with specified count inf = new Influence(); //Iterate through weights, adding each to the influence //Here, we are referring back to the NodeCache to grab the bone. //Note that the weights do not reference other influences, only bones. There is a good reason for this. MDL0BoneNode b = null; List<int> nullIndices = new List<int>(); for (int i = 0; i < count; i++, nEntry++) if (nEntry->_id < linker.NodeCache.Length && (b = (linker.NodeCache[nEntry->_id] as MDL0BoneNode)) != null) inf._weights.Add(new BoneWeight(b, nEntry->_value)); else { nullIndices.Add(i); nullCount++; } bool d = false; if (nullIndices.Count > 0) { List<BoneWeight> newWeights = new List<BoneWeight>(); for (int i = 0; i < inf._weights.Count; i++) if (!nullIndices.Contains(i)) newWeights.Add(inf._weights[i]); if (newWeights.Count == 0) d = true; else inf._weights = newWeights; } //Add influence to model object, while adding it to the cache. if (!d) ((Influence)(linker.NodeCache[index] = model._influences.FindOrCreate(inf, true)))._index = index; //Move data pointer to next entry pData = (byte*)nEntry; goto Top; //Type 5 is for primary influences case 5: pData += 5; goto Top; } } if (nullCount > 0) { model._errors.Add("There were " + nullCount + " null weights in NodeMix."); SignalPropertyChange(); } if (nodeTreeError) { model._errors.Add("The NodeTree definition did not match the bone tree."); SignalPropertyChange(); } break; case MDLResourceType.Materials: if (linker.Materials != null) ExtractGroup(linker.Materials, typeof(MDL0MaterialNode)); break; case MDLResourceType.Shaders: if (linker.Shaders != null) ExtractGroup(linker.Shaders, typeof(MDL0ShaderNode)); break; case MDLResourceType.Vertices: if (linker.Vertices != null) ExtractGroup(linker.Vertices, typeof(MDL0VertexNode)); break; case MDLResourceType.Normals: if (linker.Normals != null) ExtractGroup(linker.Normals, typeof(MDL0NormalNode)); break; case MDLResourceType.UVs: if (linker.UVs != null) ExtractGroup(linker.UVs, typeof(MDL0UVNode)); break; case MDLResourceType.FurLayerCoords: if (linker.FurLayerCoords != null) ExtractGroup(linker.FurLayerCoords, typeof(MDL0FurPosNode)); break; case MDLResourceType.FurVectors: if (linker.FurVectors != null) ExtractGroup(linker.FurVectors, typeof(MDL0FurVecNode)); break; case MDLResourceType.Objects: //Break if no polygons defined if (linker.Polygons == null) break; //Extract ExtractGroup(linker.Polygons, typeof(MDL0ObjectNode)); //Attach materials to polygons. //This assumes that materials have already been parsed. List<ResourceNode> matList = ((MDL0Node)_parent)._matList; MDL0ObjectNode poly; MDL0MaterialNode mat; //Find DrawOpa or DrawXlu entry in Definition list foreach (ResourcePair p in *linker.Defs) if ((p.Name == "DrawOpa") || (p.Name == "DrawXlu")) { bool opa = p.Name == "DrawOpa"; ushort dIndex = 0; byte* pData = (byte*)p.Data; while (*pData++ == 4) { //Get polygon from index dIndex = *(bushort*)(pData + 2); if (dIndex >= _children.Count || dIndex < 0) { model._errors.Add("Object index was greater than the actual object count."); SignalPropertyChange(); dIndex = 0; } poly = _children[dIndex] as MDL0ObjectNode; poly._drawIndex = pData[6]; //Get material from index mat = matList[*(bushort*)pData] as MDL0MaterialNode; //Get bone from index and assign int boneIndex = *(bushort*)(pData + 4); if (linker.BoneCache != null && boneIndex >= 0 && boneIndex < linker.BoneCache.Length) poly.BoneNode = linker.BoneCache[boneIndex] as MDL0BoneNode; //Assign material to polygon if (opa) poly.OpaMaterialNode = mat; else poly.XluMaterialNode = mat; //Increment pointer pData += 7; } } foreach (MDL0ObjectNode m in _children) { int max = Maths.Max( m.OpaMaterialNode != null ? m.OpaMaterialNode.Children.Count : 0, m.XluMaterialNode != null ? m.XluMaterialNode.Children.Count : 0, m.OpaMaterialNode != null && m.OpaMaterialNode.MetalMaterial != null ? m.OpaMaterialNode.MetalMaterial.Children.Count : 0, m.XluMaterialNode != null && m.XluMaterialNode.MetalMaterial != null ? m.XluMaterialNode.MetalMaterial.Children.Count : 0); bool hasUnused = false; for (int i = max; i < 8; i++) if (m.HasTextureMatrix[i]) { m.HasTextureMatrix[i] = false; m._rebuild = true; hasUnused = true; } if (hasUnused) { ((MDL0Node)Parent)._errors.Add("Object " + m.Index + " has unused texture matrices."); m.SignalPropertyChange(); } if (m.HasTexMtx && m.HasNonFloatVertices) { ((MDL0Node)Parent)._errors.Add("Object " + m.Index + " has texture matrices and non-float vertices, meaning it will explode in-game."); m.SignalPropertyChange(); } } break; case MDLResourceType.Colors: if (linker.Colors != null) ExtractGroup(linker.Colors, typeof(MDL0ColorNode)); break; case MDLResourceType.Textures: if (linker.Textures != null) ExtractGroup(linker.Textures, typeof(MDL0TextureNode)); break; case MDLResourceType.Palettes: if (linker.Palettes != null) ExtractGroup(linker.Palettes, typeof(MDL0TextureNode)); break; } }
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; }
private void Weight(float value, Vertex3 vertex, bool increment) { //LET'S TANGO Influence targetInf = null; BoneWeight targetWeight = null; float max = 1.0f; int selectedIndex = 0; IMatrixNode node = vertex.MatrixNode; if (node == null) { vertex._object.ConvertInf(); node = vertex.MatrixNode; } List<BoneWeight> weights = node.Weights; if (_targetBone == null || _targetBone._locked) return; MDL0BoneNode origBone = null; if (node is MDL0BoneNode) { origBone = node as MDL0BoneNode; node = new Influence(origBone); } bool refs = node.Users.Count > 1; if (refs) targetInf = (node as Influence).Clone(); else targetInf = (node as Influence); weights = targetInf._weights; selectedIndex = vertex.IndexOfBone(TargetBone); if (selectedIndex == -1) { weights.Add(new BoneWeight(TargetBone, 0.0f)); selectedIndex = weights.Count - 1; } targetWeight = targetInf._weights[selectedIndex]; if (targetWeight.Locked) return; max = 1.0f; foreach (BoneWeight b in weights) if (b.Locked) max -= b.Weight; value = increment ? RoundValue(targetWeight.Weight + value, max) : RoundValue(value, max); if (targetWeight.Weight == value) return; List<int> editableWeights = new List<int>(); int c = 0; foreach (BoneWeight b in targetInf._weights) { if (!b.Locked && c != selectedIndex) editableWeights.Add(c); c++; } if (editableWeights.Count == 0) return; float diff = targetWeight.Weight - value; targetWeight.Weight = value; float val = diff / (editableWeights.Count); if (value != max) foreach (int i in editableWeights) targetInf._weights[i].Weight = (float)Math.Round((targetInf._weights[i].Weight + val).Clamp(0.0f, 1.0f), 7); else foreach (int i in editableWeights) targetInf._weights[i].Weight = 0; //Don't want the modified value to be normalized bool locked = targetWeight.Locked; targetWeight.Locked = true; targetInf.Normalize(); targetWeight.Locked = locked; vertex.MatrixNode = vertex._object.Model._influences.FindOrCreate(targetInf, false); vertex._object.ConvertInf(); vertex._object.Model.SignalPropertyChange(); _mainWindow.UpdateModel(); }