public DialogResult ShowDialog(MDL0Node internalModel, MDL0Node externalModel) { _internalModel = internalModel; _externalModel = externalModel; _externalModel._renderBones = false; comboBox1.Items.AddRange(_externalModel.FindChild("Objects", true).Children.ToArray()); comboBox2.Items.AddRange(_internalModel._linker.BoneCache); comboBox1.SelectedIndex = comboBox2.SelectedIndex = comboBox3.SelectedIndex = 0; _parent = (MDL0BoneNode)comboBox2.SelectedItem; return base.ShowDialog(null); }
/// <summary> /// Call before and after making a modification to a bone's framestate. /// </summary> /// <param name="bone"></param> public void BoneChange(MDL0BoneNode bone) { SaveState state = new SaveState(); state._bone = bone; state._frameState = bone._frameState; state._animation = SelectedCHR0; state._frameIndex = CurrentFrame; if (before) AddUndo(state); else AddRedo(state); before = !before; }
private void CreateNode() { MDL0GroupNode group = _resource as MDL0GroupNode; MDL0Node model = group.Parent as MDL0Node; switch (group._type.ToString("g")) { case "Bones": MDL0BoneNode bone = new MDL0BoneNode() { Name = "NewBone" }; model._boneGroup.InsertChild(bone, false, 0); bone._flags1 = (BoneFlags)284; bone.Scale = new Vector3(1, 1, 1); bone._bindMatrix = Matrix.Identity; bone._inverseBindMatrix = Matrix.Identity; bone.Moved = true; break; } }
private void OnBillboardModeChanged() { if (BillboardSetting == BillboardFlags.Off) { MDL0BoneNode n = this; while ((n = n.Parent as MDL0BoneNode) != null) { if (n.BillboardSetting != BillboardFlags.Off) { break; } } if (n != null) { BBRefNode = n; foreach (MDL0BoneNode b in Children) { b.RecursiveSetBillboard(BBRefNode); } } else { BBRefNode = null; foreach (MDL0BoneNode b in Children) { b.RecursiveSetBillboard(null); } } } else { BBRefNode = null; foreach (MDL0BoneNode b in Children) { b.RecursiveSetBillboard(this); } } }
public CHR0EntryNode CreateEntryFromBone(MDL0BoneNode b, int framesToGenerate, bool generateOrigin) { CHR0EntryNode n = new CHR0EntryNode(); if (!generateOrigin) { if (b.isOriginRot() && b.isOriginScale() && b.isOriginTrans()) { //Console.WriteLine(" " + b + " has all values equal to origin. Not generating keyframes."); return(null); } } n._name = this.FindName(b.Name); AddChild(n); n.SetSize(_numFrames, Loop); //Console.WriteLine(_numFrames); for (int i = 0; i < framesToGenerate; ++i) { n.generateKeyframeFromBone(b, i, true, generateOrigin); } SignalPropertyChange(); return(n); }
//Initialize should only be called from parent group during parse. //Bones need not be imported/exported anyways public override bool OnInitialize() { MDL0Bone *header = Header; SetSizeInternal(header->_headerLen); //Conditional name assignment if (_name == null && header->_stringOffset != 0) { _name = header->ResourceString; } //Assign fields _boneFlags = (BoneFlags)(uint)header->_flags; _billboardFlags = (BillboardFlags)(uint)header->_bbFlags; _nodeIndex = header->_nodeId; _entryIndex = header->_index; _bbRefNode = !_replaced && _boneFlags.HasFlag(BoneFlags.HasBillboardParent) ? Model._linker.NodeCache[header->_bbNodeId] as MDL0BoneNode : null; if (_billboardFlags != BillboardFlags.Off) { Model._billboardBones.Add(this); //Update mesh in T-Pose } _bindState = _frameState = new FrameState(header->_scale, (Vector3)header->_rotation, header->_translation); _bindMatrix = _frameMatrix = header->_transform; _inverseBindMatrix = _inverseFrameMatrix = header->_transformInv; _extents = header->_extents; (_userEntries = new UserDataCollection()).Read(header->UserDataAddress); //We don't want to process children because not all have been parsed yet. //Child assignments will be handled by the parent group. return(false); }
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 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 BoneWeight(MDL0BoneNode bone, float weight) { Bone = bone; Weight = weight; }
public Influence(MDL0BoneNode bone) { _weights = new List<BoneWeight> { new BoneWeight(bone) }; }
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); } } }
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. 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 _children) { 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(); //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; } //Now that bones and primary influences have been cached, we can create weighted influences. foreach (ResourcePair p in *linker.Defs) { if (p.Name == "NodeTree") { //Use node tree to rebuild bone heirarchy 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) { _children.Add(bone); } else { (bone._parent = linker.NodeCache[index] as ResourceNode)._children.Add(bone); } 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(count); //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. for (int i = 0; i < count; i++, nEntry++) { if ((linker.NodeCache[nEntry->_id] as MDL0BoneNode) == null) { Console.WriteLine("Null bone entry!"); } else { inf._weights[i] = new BoneWeight(linker.NodeCache[nEntry->_id] as MDL0BoneNode, nEntry->_value); } } //Add influence to model object, while adding it to the cache. linker.NodeCache[index] = model._influences.AddOrCreate(inf); //Move data pointer to next entry pData = (byte *)nEntry; goto Top; //Type 5 is for primary influences case 5: pData += 5; goto Top; } } } int z = 0; foreach (IMatrixNode m in linker.NodeCache) { if (!m.IsPrimaryNode) { ((Influence)m)._permanentID = z; break; } z++; } 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.Objects: //Break if no polygons defined if (linker.Polygons == null) { break; } //Extract ExtractGroup(linker.Polygons, typeof(MDL0PolygonNode)); //Attach materials to polygons. //This assumes that materials have already been parsed. List <ResourceNode> matList = ((MDL0Node)_parent)._matList; MDL0PolygonNode poly; MDL0MaterialNode mat; //Find DrawOpa or DrawXlu entry in Definition list foreach (ResourcePair p in *linker.Defs) { if ((p.Name == "DrawOpa") || (p.Name == "DrawXlu")) { 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) { ((MDL0Node)Parent)._errors.Add("Object index was greater than the actual object count."); SignalPropertyChange(); dIndex = 0; } poly = _children[dIndex] as MDL0PolygonNode; //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 and add polygon to material reference list (poly._material = mat)._polygons.Add(poly); //Increment pointer pData += 7; } } } 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; } }
internal void Parse(MDL0Node model) { Influence inf; ModelLinker linker = model._linker; int typeIndex = (int)_type; fixed(ResourceGroup **gList = &linker.Defs) if (gList[typeIndex] != null) ExtractGroup(gList[typeIndex], ModelLinker.TypeBank[typeIndex]); else return; //Nothing to read //Special handling for bones and objects if (_type == MDLResourceType.Bones) { //Bones have been parsed from raw data as a 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. //Cache flat list linker.BoneCache = _children.Select(x => x as MDL0BoneNode).ToArray(); //Reset children so we can rebuild _children.Clear(); //Assign children using each bones' parent offset in case NodeTree is corrupted. //Bone parents are assigned when they are initialized in a flat array. foreach (MDL0BoneNode b in linker.BoneCache) { MDL0Bone *header = b.Header; //Assign true parent using parent header offset int offset = header->_parentOffset; if (offset != 0) { //Get address of parent header MDL0Bone *pHeader = (MDL0Bone *)((byte *)header + offset); //Search bone list for matching header foreach (MDL0BoneNode b2 in linker.BoneCache) { if (pHeader == b2.Header) { b._parent = b2; break; } } } if (b._boneFlags.HasFlag(BoneFlags.HasBillboardParent)) { b._bbRefNode = model._linker.BoneCache[header->_bbIndex] as MDL0BoneNode; } } //Make sure the node cache is the correct size int highest = 0; //Add bones to their parent's child lists and find highest node id foreach (MDL0BoneNode b in linker.BoneCache) { b._parent._children.Add(b); if (b._nodeIndex >= linker.NodeCache.Length && b._nodeIndex > highest) { highest = b._nodeIndex; } } if (highest >= linker.NodeCache.Length) { linker.NodeCache = new IMatrixNode[highest + 1]; } //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; bool fixCS0159 = false; List <MDL0BoneNode> bones = linker.BoneCache.ToList(); STop: if (*pData == 2) { bone = linker.BoneCache[*(bushort *)(pData + 1)] as MDL0BoneNode; index = *(bushort *)(pData + 3); //Parent bone node index if (bone.Header->_parentOffset == 0) { if (!_children.Contains(bone)) { nodeTreeError = true; continue; } else { bones.Remove(bone); } } else { MDL0BoneNode parent = linker.NodeCache[index] as MDL0BoneNode; if (parent == null || bone._parent != parent || !parent._children.Contains(bone)) { nodeTreeError = true; continue; } else { bones.Remove(bone); } } pData += 5; fixCS0159 = true; } if (fixCS0159) { fixCS0159 = false; goto STop; } if (bones.Count > 0) { nodeTreeError = true; } } else if (p.Name == "NodeMix") { //Use node mix to create weight groups byte *pData = (byte *)p.Data; bool fixCS0159 = false; TTop: 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.AddWeight(new BoneWeight(b, nEntry->_value)); } else { nullIndices.Add(i); } } bool noWeights = false; if ((nullCount = 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) { noWeights = true; } else { inf.SetWeights(newWeights); } } //Add influence to model object, while adding it to the cache. //Don't add user references here, they will be added during each object's initialization if (!noWeights) { ((Influence)(linker.NodeCache[index] = model._influences.FindOrCreate(inf)))._index = index; } //Move data pointer to next entry pData = (byte *)nEntry; fixCS0159 = true; break; //Type 5 is for primary influences case 5: pData += 5; fixCS0159 = true; break; } if (fixCS0159) { fixCS0159 = false; goto TTop; } } } if (nullCount > 0) { model._errors.Add("There were " + nullCount + " null weights in NodeMix."); } if (nodeTreeError) { model._errors.Add("The NodeTree definition did not match the bone tree."); } } else if (_type == MDLResourceType.Objects) { //Attach materials to polygons. //This assumes that materials have already been parsed. List <ResourceNode> matList = ((MDL0Node)_parent)._matList; MDL0ObjectNode obj; MDL0MaterialNode mat; //Find DrawOpa or DrawXlu entry in Definition list foreach (ResourcePair p in *linker.Defs) { if ((p.Name == "DrawOpa") || (p.Name == "DrawXlu")) { bool isXLU = p.Name == "DrawXlu"; ushort objectIndex = 0; byte * pData = (byte *)p.Data; while (*pData++ == 4) { //Get object with index objectIndex = *(bushort *)(pData + 2); if (objectIndex >= _children.Count || objectIndex < 0) { model._errors.Add("Object index was greater than the actual object count."); objectIndex = 0; } obj = _children[objectIndex] as MDL0ObjectNode; //Get material with index mat = matList[*(bushort *)pData] as MDL0MaterialNode; //Get bone with index int boneIndex = *(bushort *)(pData + 4); MDL0BoneNode visBone = null; if (linker.BoneCache != null && boneIndex >= 0 && boneIndex < linker.BoneCache.Length) { visBone = linker.BoneCache[boneIndex] as MDL0BoneNode; } obj._drawCalls.Add(new DrawCall(obj) { _drawOrder = pData[6], _isXLU = isXLU, MaterialNode = mat, VisibilityBoneNode = visBone, }); //Increment pointer pData += 7; } } } foreach (MDL0ObjectNode m in _children) { int max = 0; foreach (DrawCall c in m._drawCalls) { max = Maths.Max(max, c.MaterialNode.Children.Count); if (c.MaterialNode.MetalMaterial != null) { max = Maths.Max(max, c.MaterialNode.MetalMaterial.Children.Count); } } bool hasUnused = false; if (m._manager != null) { for (int i = max; i < 8; i++) { if (m._manager.HasTextureMatrix[i]) { m._manager.HasTextureMatrix[i] = false; m._forceRebuild = true; hasUnused = true; } } } if (hasUnused) { ((MDL0Node)Parent)._errors.Add("Object " + m.Index + " has unused texture matrices."); } //This error doesn't seem to always be true for factory models... //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(); //} } } }
private unsafe void RenderCatchCollision(TKContext c, Vector3 cam) { if (_event != 0x060A0800 && _event != 0x060A0900 && _event != 0x060A0A00) { return; } ResourceNode[] bl = _model._linker.BoneCache; int boneindex = _parameters[1]; int size = HitboxSize; Root.GetBoneIndex(ref boneindex); if (boneindex == 0) // if a hitbox is on TopN, make it follow TransN { if (Root.Data != null) { boneindex = Root.Data._misc._boneRefs[4].boneIndex; Root.GetBoneIndex(ref boneindex); } else { int transindex = 0; foreach (MDL0BoneNode bn in bl) { if (bn.Name.Equals("TransN")) { break; } transindex++; } if (transindex != bl.Length) { boneindex = transindex; } } } MDL0BoneNode b = bl[boneindex] as MDL0BoneNode; Matrix r = b.Matrix.GetRotationMatrix(); FrameState state = b.Matrix.Derive(); Vector3 bonePos = state._translate; Vector3 pos = new Vector3(Util.UnScalar(_parameters[3]), Util.UnScalar(_parameters[4]), Util.UnScalar(_parameters[5])) / state._scale; Vector3 globalPos = r.Multiply(pos); Matrix m = Matrix.TransformMatrix(new Vector3(1), state._rotate, globalPos + bonePos); Vector3 resultPos = m.GetPoint(); m = Matrix.TransformMatrix(new Vector3(Util.UnScalar(size)), new Vector3(), resultPos); GL.PushMatrix(); GL.MultMatrix((float *)&m); int res = 16; double drawangle = 360.0 / res; Vector3 color = Util.GetTypeColor(Util.HitboxType.Throwing); GL.Color4((color._x / 255.0f), (color._y / 225.0f), (color._z / 255.0f), 0.375f); GLDisplayList spheres = c.GetSphereList(); spheres.Call(); GL.PopMatrix(); }
public void Advance(int eventid, ModelEditControl _mainWindow) { if (eventid >= Children.Count) { return; } int list, index, type; MoveDefEventNode e = Children[eventid] as MoveDefEventNode; if (!_runEvents && e._event != 0x00050000 && e._event != 0x00110100 && e._event != 0x00120000 && e._event != 0x00130000) { return; } //Code what to do for each event here. switch (e._event) { case 0x00010100: //Synchronous Timer _waitFrames = (int)((float)e.EventData.parameters[0]._data / 60000f); break; case 0x00020000: //No Operation break; case 0x00020100: //Asynchronous Timer _waitFrames = Math.Max((int)((float)e.EventData.parameters[0]._data / 60000f) - _totalFrames, 0); break; case 0x00040100: //Set loop data _loopCount = (int)e.EventData.parameters[0]._data; _loopStartIndex = e.Index + 1; _runEvents = false; break; case 0x00050000: //Start looping _looping = true; _loopEndIndex = e.Index; _eventIndex = _loopStartIndex; _runEvents = true; break; case 0x01010000: //Loop Rest _waitFrames = 1; break; case 0x06000D00: //Offensive Collison case 0x062B0D00: //Thrown Collision e.HitboxID = (int)(e.EventData.parameters[0]._data & 0xFFFF); e.HitboxSize = (int)(e.EventData.parameters[5]._data); offensiveCollisions.Add(e); break; case 0x06050100: //Body Collision _mainWindow.hurtBoxType = (int)(e.EventData.parameters[0]._data); break; case 0x06080200: //Bone Collision int id = (int)(e.EventData.parameters[0]._data); if (Root.Model != null && Root.Model._linker.BoneCache.Length > id && id > 0) { MDL0BoneNode bone = Root.Model._linker.BoneCache[id] as MDL0BoneNode; switch ((int)(e.EventData.parameters[1]._data)) { case 0: bone._nodeColor = Color.Transparent; bone._boneColor = Color.Transparent; break; case 1: bone._nodeColor = bone._boneColor = Color.FromArgb(255, 255, 0); break; default: bone._nodeColor = bone._boneColor = Color.FromArgb(0, 0, 255); break; } _mainWindow.boneCollisions.Add(bone); } break; case 0x06060100: //Undo Bone Collision foreach (MDL0BoneNode bone in _mainWindow.boneCollisions) { bone._nodeColor = bone._boneColor = Color.Transparent; } _mainWindow.boneCollisions = new List <MDL0BoneNode>(); break; case 0x060A0800: //Catch Collision 1 case 0x060A0900: //Catch Collision 2 case 0x060A0A00: //Catch Collision 3 e.HitboxID = (int)(e.EventData.parameters[0]._data); e.HitboxSize = (int)(e.EventData.parameters[2]._data); catchCollisions.Add(e); break; case 0x060D0000: //Terminate Catch Collisions catchCollisions = new List <MoveDefEventNode>(); break; case 0x00060000: //Loop break? _looping = false; _eventIndex = _loopEndIndex + 1; _loopTime = 0; break; case 0x06150F00: //Special Offensive Collison e.HitboxID = (int)(e.EventData.parameters[0]._data & 0xFFFF); e.HitboxSize = (int)(e.EventData.parameters[5]._data); specialOffensiveCollisions.Add(e); break; case 0x06040000: //Terminate Collisions offensiveCollisions = new List <MoveDefEventNode>(); specialOffensiveCollisions = new List <MoveDefEventNode>(); break; case 0x06030100: //Delete hitbox foreach (MoveDefEventNode ev in offensiveCollisions) { if (ev.HitboxID == (int)(ev.EventData.parameters[0]._data)) { offensiveCollisions.Remove(ev); break; } } foreach (MoveDefEventNode ev in specialOffensiveCollisions) { if (ev.HitboxID == (int)(ev.EventData.parameters[0]._data)) { specialOffensiveCollisions.Remove(ev); break; } } break; case 0x04060100: //Set anim frame - subaction timer unaffected _mainWindow.SetFrame((int)((float)e.EventData.parameters[0]._data / 60000f)); break; case 0x00070100: //Go to subroutine and return Root.GetLocation((int)e.EventData.parameters[0]._data, out list, out type, out index); subRoutine = Root.GetAction(list, type, index); if (subRoutine != null) { subRoutineSetAt = _totalFrames; subRoutine.actionReferencedBy = this; subRoutine._subRoutine = true; } break; case 0x00080000: //Return _return = true; _eventIndex = Children.Count; _idling = true; break; case 0x00090100: //Go to and do not return unless called Root.GetLocation((int)e.EventData.parameters[0]._data, out list, out type, out index); MoveDefActionNode a = Root.GetAction(list, type, index); if (a != null) { subRoutineSetAt = _totalFrames; a.actionReferencedBy = this; a._delete = true; _mainWindow.pnlMoveset.selectedActionNodes.Add(a); //if (_eventIndex == Children.Count) _mainWindow.pnlMoveset.selectedActionNodes.Remove(this); } break; case 0x0B000200: //Model Changer 1 case 0x0B010200: //Model Changer 2 if (Root.Model._polyList == null) { break; } if (Root.data.mdlVisibility.Children.Count == 0) { break; } MoveDefModelVisRefNode entry = Root.data.mdlVisibility.Children[(e._event >> 16 & 1)] as MoveDefModelVisRefNode; if (entry.Children.Count == 0) { break; } MoveDefBoneSwitchNode list1 = entry.Children[(int)e.EventData.parameters[0]._data] as MoveDefBoneSwitchNode; if (list1.Children.Count == 0) { break; } if ((int)e.EventData.parameters[1]._data > list1.Children.Count) { foreach (MDL0PolygonNode p in Root.Model._polyList) { p._render = false; } break; } else if ((int)e.EventData.parameters[1]._data < 0) { foreach (MoveDefModelVisGroupNode l in list1.Children) { foreach (MoveDefBoneIndexNode b in l.Children) { if (b.BoneNode == null) { continue; } foreach (MDL0PolygonNode p in b.BoneNode._manPolys) { p._render = false; } } } break; } MoveDefModelVisGroupNode list2 = list1.Children[(int)e.EventData.parameters[1]._data] as MoveDefModelVisGroupNode; if (list2.Children.Count == 0) { break; } foreach (MoveDefModelVisGroupNode l in list1.Children) { if (l.Index != (int)e.EventData.parameters[1]._data) { foreach (MoveDefBoneIndexNode b in l.Children) { if (b.BoneNode == null) { continue; } foreach (MDL0PolygonNode p in b.BoneNode._manPolys) { p._render = false; } } } } foreach (MoveDefBoneIndexNode b in list2.Children) { if (b.BoneNode == null) { continue; } foreach (MDL0PolygonNode p in b.BoneNode._manPolys) { p._render = true; } } break; case 0x0B020100: if (Root.Model._polyList != null) { bool val = e.EventData.parameters[0]._data != 0; foreach (MDL0PolygonNode p in Root.Model._polyList) { p._render = val; } if (val) { _mainWindow.pnlMoveset.ResetModelVis(); } } break; case 0x00100200: //Switch _cases = new List <MoveDefEventParameterNode>(); _caseIndices = new List <int>(); _runEvents = false; _loopStartIndex = e.Index; break; case 0x00110100: //Case if (!_runEvents) { if (_cases != null && _caseIndices != null) { _cases.Add(e.Children[0] as MoveDefEventParameterNode); _caseIndices.Add(e.Index); } } else { _eventIndex = _loopEndIndex + 1; _loopEndIndex = -1; } break; case 0x00120000: //Default Case _defaultCaseIndex = e.Index; break; case 0x00130000: //End Switch _runEvents = true; _loopEndIndex = e.Index; //Apply cases int i = 0; MoveDefEventParameterNode Switch = Children[_loopStartIndex].Children[1] as MoveDefEventParameterNode; foreach (MoveDefEventParameterNode p in _cases) { if (Switch.Compare(p, 2)) { _eventIndex = _caseIndices[i] + 1; break; } i++; } if (i == _cases.Count && _defaultCaseIndex != -1) { _eventIndex = _defaultCaseIndex + 1; } _cases = null; _defaultCaseIndex = -1; _loopStartIndex = -1; break; case 0x00180000: //Break _eventIndex = _loopEndIndex + 1; _loopEndIndex = -1; break; } }
private void MergeChildren(MDL0BoneNode parent, MDL0BoneNode child, ResourceNode res) { bool found = false; MDL0BoneNode bone = null; foreach (MDL0BoneNode b1 in parent.Children) if (b1.Name == child.Name) { found = true; bone = b1; foreach (MDL0BoneNode b in child.Children) MergeChildren(b1, b, res); break; } if (!found) { MDL0BoneNode b = child.Clone(); parent.InsertChild(b, true, child.Index); bone = b; } else found = false; if (res is MDL0ObjectNode) { MDL0ObjectNode poly = res as MDL0ObjectNode; foreach (Vertex3 v in poly._manager._vertices) if (v._matrixNode == child) v.MatrixNode = bone; } else if (res is MDL0Node) { MDL0Node mdl = res as MDL0Node; foreach (MDL0ObjectNode poly in mdl.FindChild("Objects", true).Children) { foreach (Vertex3 v in poly._manager._vertices) if (v._matrixNode == child) v.MatrixNode = bone; } } }
private void CreateNode() { TreeView.BeginUpdate(); int id = 1; string name = "NewBone0"; MDL0Node model = ((MDL0BoneNode)_resource).Model; Top: foreach (MDL0BoneNode b in model._linker.BoneCache) { if (b.Name == name) { name = "NewBone" + id++; goto Top; } } MDL0BoneNode bone = new MDL0BoneNode() { Name = name }; bone.Scale = new Vector3(1); bone._bindMatrix = bone._inverseBindMatrix = bone._frameMatrix = bone._inverseFrameMatrix = Matrix.Identity; _resource.AddChild(bone, true); bone.Moved = true; TreeView.EndUpdate(); Nodes[Nodes.Count - 1].EnsureVisible(); //TreeView.SelectedNode = Nodes[Nodes.Count - 1]; }
private void comboBox2_SelectedIndexChanged(object sender, EventArgs e) { if (comboBox1.SelectedItem == null) return; _parent = (MDL0BoneNode)comboBox2.SelectedItem; }
public void RunEvent(int eventIndex) { //Get the current event and its id Event e = this[eventIndex]; if (e == null) { return; } uint eventId = e.EventID; byte eNameSpace = e.NameSpace; byte eID = e.ID; byte eCount = (byte)e.Count; byte eUnk = e.Unknown; //Get raw parameter list int[] p = e.Select(x => x.Data).ToArray(); //Run event only if allowed or if an exception if (!_runEvents && !_runExceptions.Contains((eNameSpace << 8) | eID)) { return; } //Variables that are used often int id; Script script; Event ev; int index; ArticleInfo articleInfo; HitBox hitbox; RequirementInfo reqInfo; ActionChangeInfo aChangeInfo; SubActionChangeInfo sChangeInfo; //Code what to do for each event here! switch (eventId) { case 0x01000000: //Loop Rest 1 for Goto Application.DoEvents(); break; case 0x00010100: //Synchronous Timer _waitFrames = (int)(e[0].RealValue + 0.5f); break; case 0x00020000: //No Operation break; case 0x00020100: //Asynchronous Timer _waitFrames = Math.Max((int)(e[0].RealValue + 0.5f) - _frameIndex, 0); break; case 0x00040100: //Set loop data _loopCount = p[0]; _loopStartIndex = e.Index + 1; _runEvents = false; break; case 0x00050000: //Start looping _looping = true; _loopEndIndex = e.Index; _eventIndex = _loopStartIndex; _runEvents = true; break; case 0x000A0100: //If case 0x000A0200: //If Value case 0x000A0300: //If Unk case 0x000A0400: //If Comparison if (_runEvents) { _currentIf = _ifIndex++; _runEvents = false; _ifInfo = new IfInfo(); index = eventIndex + 1; while (true) { if (index < Count) { ev = this[index]; id = (int)ev.EventID; if (id == 0x000B0100 || id == 0x000B0200 || id == 0x000B0300 || id == 0x000B0400) { index++; } else { break; } } else { break; } } _ifInfo._reqIndices = new List <int>(); _ifInfo._reqIndices.Add(index); _ifEndIndices.Add(0); reqInfo = new RequirementInfo(p[0]); for (int i = 1; i < ((eventId >> 8) & 0xFF); i++) { reqInfo._values.Add(e[i]); } _ifInfo._requirements = new List <List <RequirementInfo> >(); _ifInfo._requirements.Add(new List <RequirementInfo>()); _ifInfo._requirements[0].Add(reqInfo); } else { _ifIndex++; } break; case 0x000E0000: //Else if (!_runEvents) { if (_ifIndex == _currentIf) { _ifInfo._elseIndex = eventIndex; } } else { if (_ifIndex == _currentIf + 1) { _eventIndex = _ifInfo._endIndex; } } break; case 0x000D0100: //Else If (req) case 0x000D0200: //Else If Value (req val) case 0x000D0300: //Else If Unk (req val unk) case 0x000D0400: //Else If Comparison (req var val var) if (!_runEvents) { if (_ifIndex == _currentIf) { index = eventIndex + 1; while (true) { if (index < Count) { ev = this[index]; id = (int)ev.EventID; if (id == 0x000B0100 || id == 0x000B0200 || id == 0x000B0300 || id == 0x000B0400) { index++; } else { break; } } else { break; } } _ifInfo._reqIndices.Add(index); } } else { if (_ifIndex == _currentIf + 1) { _eventIndex = _ifInfo._endIndex; } } if (!_runEvents && _ifIndex == _currentIf + 1) { reqInfo = new RequirementInfo(p[0]); for (int i = 1; i < eCount; i++) { reqInfo._values.Add(e[i]); } _ifInfo._requirements.Add(new List <RequirementInfo>()); _ifInfo._requirements[0].Add(reqInfo); } break; case 0x000B0100: //And If case 0x000B0200: //And If Value case 0x000B0300: //And If Unk case 0x000B0400: //And If Comparison if (!_runEvents && _ifIndex == _currentIf + 1) { reqInfo = new RequirementInfo(p[0]); for (int i = 1; i < eCount; i++) { reqInfo._values.Add(e[i]); } _ifInfo._requirements.Add(new List <RequirementInfo>()); _ifInfo._requirements[0].Add(reqInfo); } break; case 0x000F0000: //End if _ifIndex--; if (!_runEvents) { if (_ifIndex == _currentIf) { _ifInfo._endIndex = _ifEndIndices[_currentIf] = eventIndex + 1; _eventIndex = _ifInfo.Run(); _runEvents = true; } } break; case 0x00100200: //Switch _cases = new List <Parameter>(); _caseIndices = new List <int>(); //Turn off events to examine them until end switch //Then the examined data will be evaluated _runEvents = false; _switchStartIndex = eventIndex; break; case 0x00110100: //Case if (!_runEvents) { if (_cases != null && _caseIndices != null) { _cases.Add(e[0]); _caseIndices.Add(e.Index); } } else { _eventIndex = _switchEndIndex + 1; _switchEndIndex = -1; } break; case 0x00120000: //Default Case _defaultCaseIndex = e.Index; break; case 0x00130000: //End Switch _runEvents = true; _switchEndIndex = e.Index; //Apply cases index = 0; if (_switchStartIndex >= 0 && _switchStartIndex < Count) { Parameter Switch = this[_switchStartIndex][1]; foreach (Parameter param in _cases) { if (Switch.Compare(param, 2)) { _eventIndex = _caseIndices[index] + 1; break; } index++; } } if (_cases != null && index == _cases.Count && _defaultCaseIndex != -1) { _eventIndex = _defaultCaseIndex + 1; } _defaultCaseIndex = -1; _switchStartIndex = -1; _cases = null; break; case 0x00180000: //Break _eventIndex = _switchEndIndex + 1; _switchEndIndex = -1; break; case 0x10050200: //Article Visiblity id = p[0]; if (id < 0 || id >= RunTime._articles.Length) { break; } articleInfo = RunTime._articles[id]; if (articleInfo != null && articleInfo._model != null) { articleInfo._model._visible = p[1] != 0; } break; case 0x01010000: //Loop Rest _waitFrames = 1; break; case 0x06000D00: //Offensive Collison case 0x062B0D00: //Thrown Collision hitbox = new HitBox(e, Article != null ? Article.Index : -1); hitbox.HitboxID = (int)(p[0] & 0xFFFF); hitbox.HitboxSize = p[5]; RunTime._hitBoxes.Add(hitbox); break; case 0x06050100: //Body Collision _hurtBoxType = p[0]; break; case 0x06080200: //Bone Collision id = p[0]; if (Root.Model != null && Root.Model._linker.BoneCache.Length > id && id >= 0) { MDL0BoneNode bone = Root.Model._linker.BoneCache[id] as MDL0BoneNode; switch ((int)p[1]) { case 0: bone._nodeColor = Color.Transparent; bone._boneColor = Color.Transparent; break; case 1: bone._nodeColor = bone._boneColor = Color.FromArgb(255, 255, 0); break; default: bone._nodeColor = bone._boneColor = Color.FromArgb(0, 0, 255); break; } _boneCollisions.Add(bone); } break; case 0x06060100: //Undo Bone Collision foreach (MDL0BoneNode bone in _boneCollisions) { bone._nodeColor = bone._boneColor = Color.Transparent; } _boneCollisions = new List <MDL0BoneNode>(); break; case 0x060A0800: //Catch Collision 1 case 0x060A0900: //Catch Collision 2 case 0x060A0A00: //Catch Collision 3 hitbox = new HitBox(e, Article != null ? Article.Index : -1); hitbox.HitboxID = p[0]; hitbox.HitboxSize = p[2]; RunTime._hitBoxes.Add(hitbox); break; case 0x060D0000: //Terminate Catch Collisions for (int i = 0; i < RunTime._hitBoxes.Count; i++) { if (RunTime._hitBoxes[i].IsCatch()) { RunTime._hitBoxes.RemoveAt(i--); } } break; case 0x00060000: //Loop break _looping = false; _eventIndex = _loopEndIndex + 1; _loopTime = 0; break; case 0x06150F00: //Special Offensive Collison hitbox = new HitBox(e, Article != null ? Article.Index : -1); hitbox.HitboxID = (int)(p[0] & 0xFFFF); hitbox.HitboxSize = p[5]; RunTime._hitBoxes.Add(hitbox); break; case 0x06040000: //Terminate Collisions for (int i = 0; i < RunTime._hitBoxes.Count; i++) { if (RunTime._hitBoxes[i].IsOffensive(true)) { RunTime._hitBoxes.RemoveAt(i--); } } break; case 0x06030100: //Delete hitbox for (int i = 0; i < RunTime._hitBoxes.Count; i++) { HitBox hbox = RunTime._hitBoxes[i]; if (hbox.HitboxID == p[0] && hbox.IsOffensive(true)) { RunTime._hitBoxes.RemoveAt(i--); break; } } break; case 0x060C0100: //Delete Catch Collision for (int i = 0; i < RunTime._hitBoxes.Count; i++) { HitBox hbox = RunTime._hitBoxes[i]; if (hbox.HitboxID == p[0] && hbox.IsCatch()) { RunTime._hitBoxes.RemoveAt(i--); break; } } break; case 0x061B0500: //Move hitbox foreach (HitBox hbox in RunTime._hitBoxes) { if (hbox.HitboxID == p[0] && hbox.IsOffensive(true)) { hbox._parameters[1] = p[1]; hbox._parameters[6] = p[2]; hbox._parameters[7] = p[3]; hbox._parameters[8] = p[4]; break; } } break; case 0x04060100: //Set animation frame //if (Article == null) // RunTime.SetFrame((int)(e[0].RealValue + 0.05f)); //else // RunTime._articles[Article.Index].SetFrame((int)(e[0].RealValue + 0.05f)); break; case 0x00070100: //Subroutine script = (e[0] as EventOffset)._script; if (script != null && script != _script) { script.Reset(); RunTime._runningScripts.Add(script); script.SetFrame(0); } break; case 0x00080000: //Return _return = true; _eventIndex = Count; if (RunTime._runningScripts.Contains(_script)) { RunTime._runningScripts.Remove(_script); } break; case 0x00090100: //Go to script = (e[0] as EventOffset)._script; if (script != null && script != _script) { RunTime._runningScripts.Remove(_script); script.Reset(); RunTime._runningScripts.Add(script); script.SetFrame(0); } break; case 0x0A030100: //Stop sound id = p[0]; if (RunTime._playingSounds.ContainsKey(id)) { List <AudioInfo> aList = RunTime._playingSounds[id]; foreach (AudioInfo aInfo in aList) { if (aInfo._buffer != null) { aInfo._buffer.Stop(); aInfo._buffer.Dispose(); aInfo._stream.Dispose(); } } RunTime._playingSounds.Remove(id); } break; case 0x0A000100: //Play sound case 0x0A010100: case 0x0A020100: case 0x0A040100: case 0x0A050100: case 0x0A060100: case 0x0A070100: case 0x0A080100: case 0x0A090100: case 0x0A0A0100: case 0x0A0B0100: case 0x0A0C0100: case 0x0A0D0100: case 0x0A0E0100: case 0x0A0F0100: if (RunTime._muteSFX) { break; } id = p[0]; if (Manager.SoundArchive != null) { RSARNode node = Manager.SoundArchive; List <RSAREntryNode> sounds = node._infoCache[0]; if (id >= 0 && id < sounds.Count) { RSARSoundNode s = sounds[id] as RSARSoundNode; if (s != null) { IAudioStream stream = s.CreateStreams()[0]; AudioBuffer b = Manager._audioProvider.CreateBuffer(stream); AudioInfo info = new AudioInfo(b, stream); if (RunTime._playingSounds.ContainsKey(id)) { RunTime._playingSounds[id].Add(info); } else { RunTime._playingSounds[id] = new List <AudioInfo>() { info } }; b.Reset(); b.Seek(0); b.Play(); } } } break; case 0x0B000200: //Model Changer 1 case 0x0B010200: //Model Changer 2 ModelVisibility visNode = null; if (Article != null) { //Check if we have data to work with articleInfo = RunTime._articles[Article.Index]; if (articleInfo == null || articleInfo._model == null || articleInfo._model._objList == null || articleInfo._article._mdlVis == null || articleInfo._article._mdlVis.Count == 0) { break; } visNode = articleInfo._article._mdlVis; } else { //Check if we have data to work with if (Root.Model._objList == null || Root.Data._modelVis.Count == 0) { break; } visNode = Root.Data._modelVis; } //Get the target reference ModelVisReference refEntry = Root.Data._modelVis[((int)(eventId >> 16 & 1))]; //Check if the reference and switch id is usable if (refEntry.Count == 0 || p[0] < 0 || p[0] >= refEntry.Count) { break; } //Turn off objects ModelVisBoneSwitch SwitchNode = refEntry[p[0]]; foreach (ModelVisGroup grp in SwitchNode) { foreach (BoneIndexValue b in grp._bones) { if (b.BoneNode != null) { foreach (MDL0ObjectNode obj in b.BoneNode._manPolys) { obj._render = false; } } } } //Check if the group id is usable if (p[1] > SwitchNode.Count || p[1] < 0) { break; } //Turn on objects ModelVisGroup group = SwitchNode[p[1]]; if (group != null) { foreach (BoneIndexValue b in group._bones) { if (b.BoneNode != null) { foreach (MDL0ObjectNode obj in b.BoneNode._manPolys) { obj._render = true; } } } } break; case 0x0B020100: //Model visibility if (Article == null) { Root.Model._visible = p[0] != 0; } else if (Article.Index < RunTime._articles.Length && RunTime._articles[Article.Index]._model != null) { RunTime._articles[Article.Index]._model._visible = p[0] != 0; } break; case 0x0D000200: //Concurrent Infinite Loop index = p[0]; EventOffset off = (e[1] as EventOffset); if (off._script != null) { if (RunTime._concurrentLoopScripts.ContainsKey(index)) { RunTime._concurrentLoopScripts.Remove(index); } RunTime._concurrentLoopScripts.Add(index, off._script); } break; case 0x0D010100: //Terminate Concurrent Infinite Loop index = p[0]; if (RunTime._concurrentLoopScripts.ContainsKey(index)) { RunTime._concurrentLoopScripts.Remove(index); } break; case 0x0E000100: //Set Air/Ground RunTime._location = (RunTime.Location)(p[0]); break; case 0x10000100: //Generate Article case 0x10000200: //Generate Article case 0x10030100: //Remove Article //These events do a similar job! bool removeArticle = eID == 3; //Make sure we have all the data we need available MainControl main = MainForm.Instance._mainControl; MovesetFile mNode = Manager.Moveset; if (mNode == null) { break; } DataSection d = mNode.Data; if (d == null) { break; } //Get the id of the article to be called and check it int aId2 = p[0]; if (aId2 < 0 || aId2 >= RunTime._articles.Length) { break; } //Get the called article from the article list articleInfo = RunTime._articles[aId2]; if (articleInfo == null) { return; } //Remove or add the article if (removeArticle) { if (!articleInfo.Running) { return; } //Remove the article's model from the scene if (articleInfo._model != null) { main.RemoveTarget(articleInfo._model); articleInfo._model._visible = false; } //This article is no longer available for use articleInfo.Running = false; } else { if (articleInfo.Running) { return; } //Add the article's model to the scene if (articleInfo._model != null) { main.AddTarget(articleInfo._model); articleInfo._model._visible = true; } //This article is now available for use articleInfo.Running = true; } break; case 0x10040200: //Set Anchored Article SubAction case 0x10070200: //Set Remote Article SubAction id = p[0]; int sId = p[1]; if (id < 0 || id >= RunTime._articles.Length) { break; } //Get the called article from the article list articleInfo = RunTime._articles[id]; if (articleInfo != null) { articleInfo.SubactionIndex = sId; articleInfo._setAt = _frameIndex; } break; case 0x10010200: //Set Ex-Anchored Article Action break; case 0x12000200: //Basic Var Set case 0x12060200: //Float Var Set e[1].RealValue = e[0].RealValue; break; case 0x12010200: //Basic Var Add case 0x12070200: //Float Var Add e[1].RealValue = e[1].RealValue + e[0].RealValue; break; case 0x12020200: //Basic Var Sub case 0x12080200: //Float Var Sub e[1].RealValue = e[1].RealValue - e[0].RealValue; break; case 0x12030100: //Basic Var Inc e[0].RealValue = e[0].RealValue + 1.0f; break; case 0x12040100: //Basic Var Dec e[0].RealValue = e[0].RealValue - 1.0f; break; case 0x120A0100: //Bit Variable Set e[0].RealValue = 1.0f; break; case 0x120B0100: //Bit Variable Clear e[0].RealValue = 0.0f; break; case 0x120F0200: //Float Variable Multiply e[1].RealValue = e[1].RealValue * e[0].RealValue; break; case 0x12100200: //Float Variable Divide if (e[0].RealValue != 0) { e[1].RealValue = e[1].RealValue / e[0].RealValue; } break; case 0x64000000: //Allow Interrupt RunTime._allowInterrupt = true; break; case 0x02000300: //Change Action Status case 0x02000400: case 0x02000500: case 0x02000600: break; case 0x02010200: //Change Action case 0x02010300: case 0x02010400: case 0x02010500: aChangeInfo = new ActionChangeInfo(p[0]); reqInfo = new RequirementInfo(p[1]); for (int i = 2; i < Count; i++) { reqInfo._values.Add(e[i]); } aChangeInfo._requirements.Add(reqInfo); RunTime.AddActionChangeInfo(aChangeInfo); break; case 0x02040100: //Additional Change Action Requirement case 0x02040200: case 0x02040300: case 0x02040400: break; case 0x02060100: //Enable Action Status ID break; case 0x02080100: //Disable Action Status ID break; case 0x02090200: //Invert Action Status ID break; case 0x020A0100: //Allow Specific Interrupt break; case 0x020B0100: //Disallow Specific Interrupt break; case 0x020C0100: //Unregister Interrupt break; case 0x04000100: //Change Subaction case 0x04000200: sChangeInfo = new SubActionChangeInfo(p[0], eCount == 2 && p[1] != 0); RunTime.AddSubActionChangeInfo(sChangeInfo); break; case 0x04010200: //Change Subaction sChangeInfo = new SubActionChangeInfo(p[0], false); sChangeInfo._requirements.Add(new RequirementInfo(p[1])); RunTime.AddSubActionChangeInfo(sChangeInfo); break; } }
private static unsafe void WriteControllers(MDL0Node model, XmlWriter writer) { if (model._objList == null) return; writer.WriteStartElement("library_controllers"); int g = 0; //List<MDL0BoneNode> boneSet = new List<MDL0BoneNode>(); MDL0BoneNode[] bones = new MDL0BoneNode[model._linker.BoneCache.Length]; model._linker.BoneCache.CopyTo(bones, 0); //foreach (MDL0BoneNode b in model._linker.BoneCache) //{ // b._nodeIndex = g++; // boneSet.Add(b); //} HashSet<float> temp = new HashSet<float>(); Matrix m; bool first; foreach (MDL0ObjectNode poly in model._objList) { List<Vertex3> verts = poly._manager._vertices; writer.WriteStartElement("controller"); writer.WriteAttributeString("id", poly.Name + "_Controller"); writer.WriteStartElement("skin"); writer.WriteAttributeString("source", "#" + poly.Name); writer.WriteStartElement("bind_shape_matrix"); //Set bind pose matrix //if (poly._singleBind != null) // m = poly._singleBind.Matrix; //else m = Matrix.Identity; writer.WriteString(WriteMatrix(m)); writer.WriteEndElement(); //Get list of used bones and weights //int index = 0; if (poly._matrixNode != null) { foreach (BoneWeight w in poly._matrixNode.Weights) { //if (!boneSet.Contains(w.Bone)) //{ // boneSet.Add(w.Bone); // w.Bone._nodeIndex = index++; //} //if (!weightSet.Contains(w.Weight)) temp.Add(w.Weight); } } else { foreach (Vertex3 v in verts) foreach (BoneWeight w in v._matrixNode.Weights) { //if (!boneSet.Contains(w.Bone)) //{ // boneSet.Add(w.Bone); // w.Bone._nodeIndex = index++; //} //if (!weightSet.Contains(w.Weight)) temp.Add(w.Weight); } } float[] weightSet = new float[temp.Count]; temp.CopyTo(weightSet); //Write joint source writer.WriteStartElement("source"); writer.WriteAttributeString("id", poly.Name + "_Joints"); //Node array writer.WriteStartElement("Name_array"); writer.WriteAttributeString("id", poly.Name + "_JointArr"); //writer.WriteAttributeString("count", boneSet.Count.ToString()); writer.WriteAttributeString("count", bones.Length.ToString()); first = true; //foreach (MDL0BoneNode b in boneSet) foreach (MDL0BoneNode b in bones) { if (first) first = false; else writer.WriteString(" "); writer.WriteString(b.Name); } writer.WriteEndElement(); //Name_array //Technique writer.WriteStartElement("technique_common"); writer.WriteStartElement("accessor"); writer.WriteAttributeString("source", String.Format("#{0}_JointArr", poly.Name)); //writer.WriteAttributeString("count", boneSet.Count.ToString()); writer.WriteAttributeString("count", bones.Length.ToString()); writer.WriteStartElement("param"); writer.WriteAttributeString("name", "JOINT"); writer.WriteAttributeString("type", "Name"); writer.WriteEndElement(); //param writer.WriteEndElement(); //accessor writer.WriteEndElement(); //technique writer.WriteEndElement(); //joint source //Inverse matrices source writer.WriteStartElement("source"); writer.WriteAttributeString("id", poly.Name + "_Matrices"); writer.WriteStartElement("float_array"); writer.WriteAttributeString("id", poly.Name + "_MatArr"); //writer.WriteAttributeString("count", (boneSet.Count * 16).ToString()); writer.WriteAttributeString("count", (bones.Length * 16).ToString()); first = true; foreach (MDL0BoneNode b in bones) { if (first) first = false; else writer.WriteString(" "); writer.WriteString(WriteMatrix(b.InverseBindMatrix)); } writer.WriteEndElement(); //float_array //Technique writer.WriteStartElement("technique_common"); writer.WriteStartElement("accessor"); writer.WriteAttributeString("source", String.Format("#{0}_MatArr", poly.Name)); //writer.WriteAttributeString("count", boneSet.Count.ToString()); writer.WriteAttributeString("count", bones.Length.ToString()); writer.WriteAttributeString("stride", "16"); writer.WriteStartElement("param"); writer.WriteAttributeString("type", "float4x4"); writer.WriteEndElement(); //param writer.WriteEndElement(); //accessor writer.WriteEndElement(); //technique writer.WriteEndElement(); //source //Weights source writer.WriteStartElement("source"); writer.WriteAttributeString("id", poly.Name + "_Weights"); writer.WriteStartElement("float_array"); writer.WriteAttributeString("id", poly.Name + "_WeightArr"); writer.WriteAttributeString("count", weightSet.Length.ToString()); first = true; foreach (float f in weightSet) { if (first) first = false; else writer.WriteString(" "); writer.WriteValue(f); } writer.WriteEndElement(); //Technique writer.WriteStartElement("technique_common"); writer.WriteStartElement("accessor"); writer.WriteAttributeString("source", String.Format("#{0}_WeightArr", poly.Name)); writer.WriteAttributeString("count", weightSet.Length.ToString()); writer.WriteStartElement("param"); writer.WriteAttributeString("type", "float"); writer.WriteEndElement(); //param writer.WriteEndElement(); //accessor writer.WriteEndElement(); //technique writer.WriteEndElement(); //source //Joint bindings writer.WriteStartElement("joints"); writer.WriteStartElement("input"); writer.WriteAttributeString("semantic", "JOINT"); writer.WriteAttributeString("source", String.Format("#{0}_Joints", poly.Name)); writer.WriteEndElement(); //input writer.WriteStartElement("input"); writer.WriteAttributeString("semantic", "INV_BIND_MATRIX"); writer.WriteAttributeString("source", String.Format("#{0}_Matrices", poly.Name)); writer.WriteEndElement(); //input writer.WriteEndElement(); //joints //Vertex weights, one for each vertex in geometry writer.WriteStartElement("vertex_weights"); writer.WriteAttributeString("count", verts.Count.ToString()); writer.WriteStartElement("input"); writer.WriteAttributeString("semantic", "JOINT"); writer.WriteAttributeString("offset", "0"); writer.WriteAttributeString("source", String.Format("#{0}_Joints", poly.Name)); writer.WriteEndElement(); //input writer.WriteStartElement("input"); writer.WriteAttributeString("semantic", "WEIGHT"); writer.WriteAttributeString("offset", "1"); writer.WriteAttributeString("source", String.Format("#{0}_Weights", poly.Name)); writer.WriteEndElement(); //input writer.WriteStartElement("vcount"); first = true; if (poly._matrixNode != null) for (int i = 0; i < verts.Count; i++) { if (first) first = false; else writer.WriteString(" "); writer.WriteString(poly._matrixNode.Weights.Count.ToString(CultureInfo.InvariantCulture.NumberFormat)); } else foreach (Vertex3 v in verts) { if (first) first = false; else writer.WriteString(" "); writer.WriteString(v._matrixNode.Weights.Count.ToString(CultureInfo.InvariantCulture.NumberFormat)); } writer.WriteEndElement(); //vcount writer.WriteStartElement("v"); first = true; if (poly._matrixNode != null) for (int i = 0; i < verts.Count; i++) foreach (BoneWeight w in poly._matrixNode.Weights) { if (first) first = false; else writer.WriteString(" "); //writer.WriteString(w.Bone._nodeIndex.ToString()); writer.WriteString(Array.IndexOf(bones, w.Bone).ToString(CultureInfo.InvariantCulture.NumberFormat)); writer.WriteString(" "); writer.WriteString(Array.IndexOf(weightSet, w.Weight).ToString(CultureInfo.InvariantCulture.NumberFormat)); } else foreach (Vertex3 v in verts) foreach (BoneWeight w in v._matrixNode.Weights) { if (first) first = false; else writer.WriteString(" "); //writer.WriteString(w.Bone._nodeIndex.ToString()); writer.WriteString(Array.IndexOf(bones, w.Bone).ToString(CultureInfo.InvariantCulture.NumberFormat)); writer.WriteString(" "); writer.WriteString(Array.IndexOf(weightSet, w.Weight).ToString(CultureInfo.InvariantCulture.NumberFormat)); } writer.WriteEndElement(); //v writer.WriteEndElement(); //vertex_weights writer.WriteEndElement(); //skin writer.WriteEndElement(); //controller //boneSet.Clear(); //weightSet.Clear(); } writer.WriteEndElement(); }
//private List<MDL0BoneNode> _overriding = new List<MDL0BoneNode>(); //[Browsable(false)] //public List<MDL0BoneNode> Overriding //{ // get { return _overriding; } // set { _overriding = value; } //} public MDL0BoneNode Clone() { MDL0BoneNode b = new MDL0BoneNode(); b._name = _name; b._bindState = new FrameState(_bindState._scale, _bindState._rotate, _bindState._translate); return b; }
public void HighlightStuff(MouseEventArgs e) { modelPanel.Cursor = Cursors.Default; float depth = modelPanel.GetDepth(e.X, e.Y); _hiX = _hiY = _hiZ = _hiCirc = _hiSphere = false; MDL0BoneNode bone = SelectedBone; //Vertex3 vertex = TargetVertex; MDL0ObjectNode poly = modelListsPanel1.SelectedPolygon; if (bone != null) { //Get the location of the bone Vector3 center = BoneLoc; //Standard radius scaling snippet. This is used for orb scaling depending on camera distance. float radius = center.TrueDistance(modelPanel._camera.GetPoint()) / _orbRadius * 0.1f; if (_editType == TransformType.Rotation) { //Get point projected onto our orb. Vector3 point = modelPanel.ProjectCameraSphere(new Vector2(e.X, e.Y), center, radius, false); //Get the distance of the mouse point from the bone float distance = point.TrueDistance(center); if (Math.Abs(distance - radius) < (radius * _selectOrbScale)) //Point lies within orb radius { _hiSphere = true; //Determine axis snapping Vector3 angles = (bone._inverseFrameMatrix * point).GetAngles() * Maths._rad2degf; angles._x = (float)Math.Abs(angles._x); angles._y = (float)Math.Abs(angles._y); angles._z = (float)Math.Abs(angles._z); if (Math.Abs(angles._y - 90.0f) <= _axisSnapRange) _hiX = true; else if (angles._x >= (180 - _axisSnapRange) || angles._x <= _axisSnapRange) _hiY = true; else if (angles._y >= (180 - _axisSnapRange) || angles._y <= _axisSnapRange) _hiZ = true; } else if (Math.Abs(distance - (radius * _circOrbScale)) < (radius * _selectOrbScale)) //Point lies on circ line _hiCirc = true; if (_hiX || _hiY || _hiZ || _hiCirc) modelPanel.Cursor = Cursors.Hand; } else if (_editType == TransformType.Translation) { Vector3 point = modelPanel.UnProject(e.X, e.Y, depth); Vector3 diff = (point - center) / radius; float halfDist = _axisHalfLDist; if (diff._x > -_axisSelectRange && diff._x < (_axisLDist + 0.01f) && diff._y > -_axisSelectRange && diff._y < (_axisLDist + 0.01f) && diff._z > -_axisSelectRange && diff._z < (_axisLDist + 0.01f)) { //Point lies within axes if (diff._x < halfDist && diff._y < halfDist && diff._z < halfDist) { //Point lies inside the double drag areas if (diff._x > _axisSelectRange) _hiX = true; if (diff._y > _axisSelectRange) _hiY = true; if (diff._z > _axisSelectRange) _hiZ = true; modelPanel.Cursor = Cursors.Hand; } else { //Check if point lies on a specific axis float errorRange = _axisSelectRange; if (diff._x > halfDist && Math.Abs(diff._y) < errorRange && Math.Abs(diff._z) < errorRange) _hiX = true; if (diff._y > halfDist && Math.Abs(diff._x) < errorRange && Math.Abs(diff._z) < errorRange) _hiY = true; if (diff._z > halfDist && Math.Abs(diff._x) < errorRange && Math.Abs(diff._y) < errorRange) _hiZ = true; if (!_hiX && !_hiY && !_hiZ) goto GetBone; else modelPanel.Cursor = Cursors.Hand; } } else goto GetBone; } else if (_editType == TransformType.Scale) { Vector3 point = modelPanel.UnProject(e.X, e.Y, depth); Vector3 diff = (point - center) / radius; if (diff._x > -_axisSelectRange && diff._x < (_axisLDist + 0.01f) && diff._y > -_axisSelectRange && diff._y < (_axisLDist + 0.01f) && diff._z > -_axisSelectRange && diff._z < (_axisLDist + 0.01f)) { //Point lies within axes //Check if point lies on a specific axis first float errorRange = _axisSelectRange; if (diff._x > errorRange && Math.Abs(diff._y) < errorRange && Math.Abs(diff._z) < errorRange) _hiX = true; if (diff._y > errorRange && Math.Abs(diff._x) < errorRange && Math.Abs(diff._z) < errorRange) _hiY = true; if (diff._z > errorRange && Math.Abs(diff._x) < errorRange && Math.Abs(diff._y) < errorRange) _hiZ = true; if (!_hiX && !_hiY && !_hiZ) { //Determine if the point is in the double or triple drag triangles float halfDist = _scaleHalf2LDist; float centerDist = _scaleHalf1LDist; if (IsInTriangle(diff, new Vector3(), new Vector3(halfDist, 0, 0), new Vector3(0, halfDist, 0))) if (IsInTriangle(diff, new Vector3(), new Vector3(centerDist, 0, 0), new Vector3(0, centerDist, 0))) _hiX = _hiY = _hiZ = true; else _hiX = _hiY = true; else if (IsInTriangle(diff, new Vector3(), new Vector3(halfDist, 0, 0), new Vector3(0, 0, halfDist))) if (IsInTriangle(diff, new Vector3(), new Vector3(centerDist, 0, 0), new Vector3(0, 0, centerDist))) _hiX = _hiY = _hiZ = true; else _hiX = _hiZ = true; else if (IsInTriangle(diff, new Vector3(), new Vector3(0, halfDist, 0), new Vector3(0, 0, halfDist))) if (IsInTriangle(diff, new Vector3(), new Vector3(0, centerDist, 0), new Vector3(0, 0, centerDist))) _hiX = _hiY = _hiZ = true; else _hiY = _hiZ = true; if (!_hiX && !_hiY && !_hiZ) goto GetBone; else modelPanel.Cursor = Cursors.Hand; } else modelPanel.Cursor = Cursors.Hand; } else goto GetBone; } } //modelPanel1.Invalidate(); GetBone: //Try selecting new bone //if (modelPanel._selecting) //{ //} //else { if (!(_scaling || _rotating || _translating) && (depth < 1.0f) && (_targetModel != null) && (_targetModel._boneList != null)) { MDL0BoneNode o = null; Vector3 point = modelPanel.UnProject(e.X, e.Y, depth); //Find orb near chosen point if (_editingAll) { foreach (MDL0Node m in _targetModels) foreach (MDL0BoneNode b in m._boneList) if (CompareDistanceRecursive(b, point, ref o)) break; } else foreach (MDL0BoneNode b in _targetModel._boneList) if (CompareDistanceRecursive(b, point, ref o)) break; if (_hiBone != null && _hiBone != SelectedBone) _hiBone._nodeColor = Color.Transparent; if ((_hiBone = o) != null) { _hiBone._nodeColor = Color.FromArgb(255, 128, 0); modelPanel.Cursor = Cursors.Hand; } } else if (_hiBone != null) { if (_hiBone != SelectedBone) _hiBone._nodeColor = Color.Transparent; _hiBone = null; } } modelPanel.Invalidate(); }
public MDL0Node ImportModel(string filePath) { MDL0Node model = new MDL0Node() { _name = Path.GetFileNameWithoutExtension(filePath) }; model.InitGroups(); if (_importOptions._setOrigPath) model._originalPath = filePath; //Parse the collada file and use the data to create an MDL0 using (DecoderShell shell = DecoderShell.Import(filePath)) try { model._version = _importOptions._modelVersion; Error = "There was a problem reading the model."; //Extract images, removing duplicates foreach (ImageEntry img in shell._images) { string name; MDL0TextureNode tex; if (img._path != null) name = Path.GetFileNameWithoutExtension(img._path); else name = img._name != null ? img._name : img._id; tex = model.FindOrCreateTexture(name); img._node = tex; } //Extract materials and create shaders int tempNo = -1; foreach (MaterialEntry mat in shell._materials) { tempNo += 1; MDL0MaterialNode matNode = new MDL0MaterialNode(); matNode._parent = model._matGroup; matNode._name = mat._name != null ? mat._name : mat._id; if (tempNo == 0) { MDL0ShaderNode shadNode = new MDL0ShaderNode(); shadNode._parent = model._shadGroup; shadNode._name = "Shader" + tempNo; model._shadList.Add(shadNode); } matNode.Shader = "Shader0"; matNode.ShaderNode = (MDL0ShaderNode)model._shadGroup.Children[0]; mat._node = matNode; matNode._cull = _importOptions._culling; //Find effect if (mat._effect != null) foreach (EffectEntry eff in shell._effects) if (eff._id == mat._effect) //Attach textures and effects to material if (eff._shader != null) foreach (LightEffectEntry l in eff._shader._effects) if (l._type == LightEffectType.diffuse && l._texture != null) { string path = l._texture; foreach (EffectNewParam p in eff._newParams) if (p._sid == l._texture) { path = p._sampler2D._url; if (!String.IsNullOrEmpty(p._sampler2D._source)) { foreach (EffectNewParam p2 in eff._newParams) if (p2._sid == p._sampler2D._source) path = p2._path; } } foreach (ImageEntry img in shell._images) if (img._id == path) { MDL0MaterialRefNode mr = new MDL0MaterialRefNode(); (mr._texture = img._node as MDL0TextureNode)._references.Add(mr); mr._name = mr._texture.Name; matNode._children.Add(mr); mr._parent = matNode; mr._minFltr = mr._magFltr = 1; mr._index1 = mr._index2 = mr.Index; mr._uWrap = mr._vWrap = (int)_importOptions._wrap; break; } } matNode._numTextures = (byte)matNode.Children.Count; model._matList.Add(matNode); } Say("Extracting scenes..."); //Extract scenes foreach (SceneEntry scene in shell._scenes) { //Parse joints first NodeEntry[] joints = scene._nodes.Where(x => x._type == NodeType.JOINT).ToArray(); NodeEntry[] nodes = scene._nodes.Where(x => x._type != NodeType.JOINT).ToArray(); foreach (NodeEntry node in joints) EnumNode(node, model._boneGroup, scene, model, shell); foreach (NodeEntry node in nodes) EnumNode(node, model._boneGroup, scene, model, shell); } //If there are no bones, rig all objects to a single bind. if (model._boneGroup._children.Count == 0) { for (int i = 0; i < 2; i++) { MDL0BoneNode bone = new MDL0BoneNode(); bone.Scale = new Vector3(1); bone._bindMatrix = bone._inverseBindMatrix = Matrix.Identity; switch (i) { case 0: bone._name = "TopN"; model._boneGroup._children.Add(bone); bone._parent = model._boneGroup; break; case 1: bone._name = "TransN"; model._boneGroup._children[0]._children.Add(bone); bone._parent = model._boneGroup._children[0]; bone.ReferenceCount = model._objList.Count; break; } } if (model._objList != null && model._objList.Count != 0) foreach (MDL0ObjectNode poly in model._objList) { poly._nodeId = 0; poly.MatrixNode = (MDL0BoneNode)model._boneGroup._children[0]._children[0]; } } else { //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 } } } //Remove original color buffers if option set if (_importOptions._ignoreColors) { if (model._objList != null && model._objList.Count != 0) foreach (MDL0ObjectNode p in model._objList) for (int x = 2; x < 4; x++) if (p._manager._faceData[x] != null) { p._manager._faceData[x].Dispose(); p._manager._faceData[x] = null; } } //Add color buffers if option set if (_importOptions._addClrs) { RGBAPixel pixel = _importOptions._dfltClr; //Add a color buffer to objects that don't have one if (model._objList != null && model._objList.Count != 0) foreach (MDL0ObjectNode p in model._objList) if (p._manager._faceData[2] == null) { RGBAPixel* pIn = (RGBAPixel*)(p._manager._faceData[2] = new UnsafeBuffer(4 * p._manager._pointCount)).Address; for (int i = 0; i < p._manager._pointCount; i++) *pIn++ = pixel; } } //Apply defaults to materials if (model._matList != null) foreach (MDL0MaterialNode p in model._matList) { if (_importOptions._mdlType == 0) { p._lSet = 20; p._fSet = 4; p._ssc = 3; p.C1ColorEnabled = true; p.C1AlphaMaterialSource = GXColorSrc.Vertex; p.C1ColorMaterialSource = GXColorSrc.Vertex; p.C1ColorDiffuseFunction = GXDiffuseFn.Clamped; p.C1ColorAttenuation = GXAttnFn.Spotlight; p.C1AlphaEnabled = true; p.C1AlphaDiffuseFunction = GXDiffuseFn.Clamped; p.C1AlphaAttenuation = GXAttnFn.Spotlight; p.C2ColorDiffuseFunction = GXDiffuseFn.Disabled; p.C2ColorAttenuation = GXAttnFn.None; p.C2AlphaDiffuseFunction = GXDiffuseFn.Disabled; p.C2AlphaAttenuation = GXAttnFn.None; } else { p._lSet = 0; p._fSet = 0; p._ssc = 1; p._chan1.Color = new LightChannelControl(1795); p._chan1.Alpha = new LightChannelControl(1795); p._chan2.Color = new LightChannelControl(1795); p._chan2.Alpha = new LightChannelControl(1795); } } //Set materials to use register color if option set if (_importOptions._useReg && model._objList != null) foreach (MDL0ObjectNode p in model._objList) { MDL0MaterialNode m = p.OpaMaterialNode; if (m != null && p._manager._faceData[2] == null && p._manager._faceData[3] == null) { m.C1MaterialColor = _importOptions._dfltClr; m.C1ColorMaterialSource = GXColorSrc.Register; m.C1AlphaMaterialSource = GXColorSrc.Register; } } //Remap materials if option set if (_importOptions._rmpMats && model._matList != null && model._objList != null) { foreach (MDL0ObjectNode p in model._objList) foreach (MDL0MaterialNode m in model._matList) if (m.Children.Count > 0 && m.Children[0] != null && p.OpaMaterialNode != null && p.OpaMaterialNode.Children.Count > 0 && p.OpaMaterialNode.Children[0] != null && m.Children[0].Name == p.OpaMaterialNode.Children[0].Name && m.C1ColorMaterialSource == p.OpaMaterialNode.C1ColorMaterialSource) { p.OpaMaterialNode = m; break; } //Remove unused materials for (int i = 0; i < model._matList.Count; i++) if (((MDL0MaterialNode)model._matList[i])._objects.Count == 0) model._matList.RemoveAt(i--); } Error = "There was a problem writing the model."; //Clean the model and then build it! if (model != null) { model.CleanGroups(); model.BuildFromScratch(this); } } catch (Exception x) { MessageBox.Show("Cannot continue importing this model.\n" + Error + "\n\nException:\n" + x.ToString()); model = null; Close(); } finally { //Clean up the mess we've made GC.Collect(GC.MaxGeneration, GCCollectionMode.Forced); } return model; }
private static unsafe void WriteBone(MDL0BoneNode bone, XmlWriter writer) { writer.WriteStartElement("node"); writer.WriteAttributeString("id", bone.Name); writer.WriteAttributeString("name", bone._name); writer.WriteAttributeString("sid", bone.Name); writer.WriteAttributeString("type", "JOINT"); //writer.WriteStartElement("matrix"); //writer.WriteString(WriteMatrix(bone._bindState._transform)); //writer.WriteEndElement(); //matrix if (bone._bindState._translate != new Vector3()) { writer.WriteStartElement("translate"); writer.WriteString( bone._bindState._translate._x.ToString(CultureInfo.InvariantCulture.NumberFormat) + " " + bone._bindState._translate._y.ToString(CultureInfo.InvariantCulture.NumberFormat) + " " + bone._bindState._translate._z.ToString(CultureInfo.InvariantCulture.NumberFormat)); writer.WriteEndElement(); //translate } if (bone._bindState._rotate._z != 0) { writer.WriteStartElement("rotate"); writer.WriteString("0 0 1 " + bone._bindState._rotate._z.ToString(CultureInfo.InvariantCulture.NumberFormat)); writer.WriteEndElement(); //rotate } if (bone._bindState._rotate._y != 0) { writer.WriteStartElement("rotate"); writer.WriteString("0 1 0 " + bone._bindState._rotate._y.ToString(CultureInfo.InvariantCulture.NumberFormat)); writer.WriteEndElement(); //rotate } if (bone._bindState._rotate._x != 0) { writer.WriteStartElement("rotate"); writer.WriteString("1 0 0 " + bone._bindState._rotate._x.ToString(CultureInfo.InvariantCulture.NumberFormat)); writer.WriteEndElement(); //rotate } if (bone._bindState._scale != new Vector3(1)) { writer.WriteStartElement("scale"); writer.WriteString( bone._bindState._scale._x.ToString(CultureInfo.InvariantCulture.NumberFormat) + " " + bone._bindState._scale._y.ToString(CultureInfo.InvariantCulture.NumberFormat) + " " + bone._bindState._scale._z.ToString(CultureInfo.InvariantCulture.NumberFormat)); writer.WriteEndElement(); //scale } //Write single-bind geometry //foreach (MDL0PolygonNode poly in bone._infPolys) // WritePolyInstance(poly, writer); foreach (MDL0BoneNode b in bone.Children) WriteBone(b, writer); writer.WriteEndElement(); //node }
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; } }
private void FixChildren(MDL0BoneNode node, int axis) { KeyframeEntry kfe; foreach (MDL0BoneNode b in node.Children) { CHR0EntryNode _target = (CHR0EntryNode)FindChild(b.Name, true); if (_target != null) { switch (axis) { case 0: //X, correct Y and Z for (int l = 0; l < _target.FrameCount; l++) { for (int g = 0x13; g < 0x16; g++) { if (g != 0x13) { if ((kfe = _target.GetKeyframe((KeyFrameMode)g, l)) != null) { kfe._value *= -1; } } } } break; case 1: //Y, correct X and Z for (int l = 0; l < _target.FrameCount; l++) { for (int g = 0x13; g < 0x16; g++) { if (g != 0x14) { if ((kfe = _target.GetKeyframe((KeyFrameMode)g, l)) != null) { kfe._value *= -1; } } } } break; case 2: //Z, correct X and Y for (int l = 0; l < _target.FrameCount; l++) { for (int g = 0x13; g < 0x16; g++) { if (g != 0x15) { if ((kfe = _target.GetKeyframe((KeyFrameMode)g, l)) != null) { kfe._value *= -1; } } } } break; } } FixChildren(b, axis); } }
public Color GetWeightColor(MDL0BoneNode targetBone) { float weight = -1; if (_matrixNode == null || targetBone == null) return Color.Transparent; if (_matrixNode is MDL0BoneNode) if (_matrixNode == targetBone) weight = 1.0f; else return Color.Transparent; else foreach (BoneWeight b in ((Influence)_matrixNode)._weights) if (b.Bone == targetBone) { weight = b.Weight; break; } if (weight == -1) return Color.Transparent; int r = ((int)(weight * 255.0f)).Clamp(0, 0xFF); return Color.FromArgb(r, 0, 0xFF - r); }
public void RemoveBone(MDL0BoneNode bone) { foreach (MDL0BoneNode b in bone.Children) RemoveBone(b); // _influences.RemoveBone(bone); // foreach (MDL0ObjectNode o in _polyList) // if (o.MatrixNode == bone) // o.MatrixNode = bone.Parent as MDL0BoneNode; //Top: // if (bone.References.Count != 0) // { // bone.References[bone.References.Count - 1].MatrixNode = bone.Parent as MDL0BoneNode; // goto Top; // } }
public int IndexOfBone(MDL0BoneNode b) { return Array.IndexOf(GetBones(), b); }
public BoneWeight(MDL0BoneNode bone) : this(bone, 1.0f) { }
public BoneWeight WeightForBone(MDL0BoneNode b) { int i = IndexOfBone(b); if (i == -1) return null; return GetBoneWeights()[i]; }
private unsafe void RenderOrb(MDL0BoneNode bone, GLDisplayList list) { Matrix m = Matrix.TransformMatrix(new Vector3(MDL0BoneNode._nodeRadius), new Vector3(), bone._frameMatrix.GetPoint()); GL.PushMatrix(); GL.MultMatrix((float*)&m); list.Call(); GL.PopMatrix(); }
private bool CompareDistanceRecursive(MDL0BoneNode bone, Vector3 point, ref MDL0BoneNode match) { Vector3 center = bone._frameMatrix.GetPoint(); float dist = center.TrueDistance(point); if (Math.Abs(dist - MDL0BoneNode._nodeRadius) < 0.01) { match = bone; return true; } foreach (MDL0BoneNode b in bone.Children) if (CompareDistanceRecursive(b, point, ref match)) return true; return false; }
public static void AssignParent(MDL0BoneNode pBone, ModelBone child, MDL0BoneNode cBone, ModelBone parent) { if (pBone._entryIndex == child._parentBoneIndex) { //Link child to its parent (cBone._parent = pBone)._children.Add(cBone); //Convert the world point into a local point relative to the bone's parent Matrix m = (Matrix.TranslationMatrix(child._wPos) * Matrix.Invert(Matrix.TranslationMatrix(parent._wPos))); //Derive to state and recalc bind matrices cBone._bindState = m.Derive(); cBone.RecalcBindState(); } else //Parent not found, continue searching children. foreach (MDL0BoneNode pMatch in pBone._children) AssignParent(pMatch, child, cBone, parent); }
internal void Parse(MDL0Node model) { Influence inf; ModelLinker linker = model._linker; switch (_type) { 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. ExtractGroup(linker.Bones, typeof(MDL0BoneNode)); //Cache flat list linker.BoneCache = _children.ToArray(); //Reset children so we can rebuild _children.Clear(); //Populate node cache MDL0BoneNode bone = null; int index; int count = linker.BoneCache.Length; for (int i = 0; i < count; i++) { //bone = linker.BoneCache[i] as MDL0BoneNode; linker.NodeCache[(bone = linker.BoneCache[i] as MDL0BoneNode)._nodeIndex] = bone; } //Now that bones and primary influences have been cached, we can create weighted influences. foreach (ResourcePair p in *linker.Defs) { if (p.Name == "NodeTree") { //Use node tree to rebuild bone heirarchy 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) { _children.Add(bone); } else { (bone._parent = linker.NodeCache[index] as ResourceNode)._children.Add(bone); } 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(count); //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. for (int i = 0; i < count; i++, nEntry++) { inf._weights[i] = new BoneWeight(linker.NodeCache[nEntry->_id] as MDL0BoneNode, nEntry->_value); } //Add influence to model object, while adding it to the cache. linker.NodeCache[index] = model._influences.AddOrCreate(inf); //Move data pointer to next entry pData = (byte *)nEntry; goto Top; //Type 5 is for primary influences case 5: pData += 5; goto Top; } } } 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.Polygons: //Break if no polygons defined if (linker.Polygons == null) { break; } //Extract ExtractGroup(linker.Polygons, typeof(MDL0PolygonNode)); //Attach materials to polygons. //This assumes that materials have already been parsed. List <ResourceNode> matList = ((MDL0Node)_parent)._matList; MDL0PolygonNode poly; MDL0MaterialNode mat; //Find DrawOpa or DrawXlu entry in Definition list foreach (ResourcePair p in *linker.Defs) { if ((p.Name == "DrawOpa") || (p.Name == "DrawXlu")) { byte *pData = (byte *)p.Data; while (*pData++ == 4) { //Get polygon from index poly = _children[*(bushort *)(pData + 2)] as MDL0PolygonNode; //Get material from index mat = matList[*(bushort *)pData] as MDL0MaterialNode; //Assign material to polygon poly._material = mat; //Add polygon to material reference list mat._polygons.Add(poly); //Increment pointer pData += 7; } } } break; } }
private void FixChildren(MDL0BoneNode node, int axis) { KeyframeEntry kfe; foreach (MDL0BoneNode b in node.Children) { CHR0EntryNode _target = (CHR0EntryNode)FindChild(b.Name, true); if (_target != null) switch (axis) { case 0: //X, correct Y and Z for (int l = 0; l < _target.FrameCount; l++) for (int g = 0x13; g < 0x16; g++) if (g != 0x13) if ((kfe = _target.GetKeyframe((KeyFrameMode)g, l)) != null) kfe._value *= -1; break; case 1: //Y, correct X and Z for (int l = 0; l < _target.FrameCount; l++) for (int g = 0x13; g < 0x16; g++) if (g != 0x14) if ((kfe = _target.GetKeyframe((KeyFrameMode)g, l)) != null) kfe._value *= -1; break; case 2: //Z, correct X and Y for (int l = 0; l < _target.FrameCount; l++) for (int g = 0x13; g < 0x16; g++) if (g != 0x15) if ((kfe = _target.GetKeyframe((KeyFrameMode)g, l)) != null) kfe._value *= -1; break; } FixChildren(b, axis); } }
internal unsafe void RenderVerts(TKContext ctx, IMatrixNode _singleBind, MDL0BoneNode selectedBone, Vector3 cam, bool pass2) { if (!_render) return; foreach (Vertex3 v in _vertices) { Color w = v._highlightColor != Color.Transparent ? v._highlightColor : (_singleBind != null && _singleBind == selectedBone) ? Color.Red : v.GetWeightColor(selectedBone); if (w != Color.Transparent) GL.Color4(w); else GL.Color4(DefaultVertColor); float d = cam.DistanceTo(_singleBind == null ? v.WeightedPosition : _singleBind.Matrix * v.WeightedPosition); if (d == 0) d = 0.000000000001f; GL.PointSize((5000 / d).Clamp(1.0f, !pass2 ? 5.0f : 8.0f)); GL.Begin(BeginMode.Points); GL.Vertex3(v.WeightedPosition._x, v.WeightedPosition._y, v.WeightedPosition._z); GL.End(); } }