public void Remap() { MDL0BoneNode b = _resource as MDL0BoneNode; if (b != null) { MDL0Node m = b.Model; if (m != null) { b._entryIndex = m._linker.BoneCache.Length; m._linker.RegenerateBoneCache(); OnUpdateProperties(null, null); b.SignalPropertyChange(); } } }
public DialogResult ShowDialog(MDL0Node internalModel, MDL0Node externalModel) { _internalModel = internalModel; _externalModel = externalModel; _externalModel.ApplyCHR(null, 0); externalModelChildren = _externalModel.FindChild("Objects", true).Children.ToArray(); 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 twice; before and after changes /// </summary> 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._boneFlags = (BoneFlags)284; bone.Scale = new Vector3(1, 1, 1); bone._bindMatrix = Matrix.Identity; bone._inverseBindMatrix = Matrix.Identity; bone.OnMoved(); break; } }
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); }
private static unsafe void WriteBone(MDL0BoneNode bone, XmlWriter writer) { writer.WriteStartElement("node"); writer.WriteAttributeString("id", bone._name); writer.WriteAttributeString("name", bone._name); writer.WriteAttributeString("type", "JOINT"); writer.WriteStartElement("matrix"); Matrix m = bone._bindState._transform; float *p = (float *)&m; for (int y = 0; y < 4; y++) { for (int x = 0; x < 4; x++) { if ((x != 0) || (y != 0)) { writer.WriteValue(" "); } writer.WriteValue(p[(x << 2) + y].ToString()); } } writer.WriteEndElement(); //matrix //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 }
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)); }
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 lstBones_SelectedValueChanged(object sender, EventArgs e) { if (_selectedBone != null) { _selectedBone._boneColor = _selectedBone._nodeColor = Color.Transparent; } if ((_targetObject = _selectedBone = lstBones.SelectedItem as MDL0BoneNode) != null) { _selectedBone._boneColor = Color.FromArgb(0, 128, 255); _selectedBone._nodeColor = Color.FromArgb(255, 128, 0); } if (SelectedBoneChanged != null) { SelectedBoneChanged(this, null); } if (RenderStateChanged != null) { RenderStateChanged(this, null); } }
public DialogResult ShowDialog(MDL0Node internalModel, MDL0Node externalModel) { if (internalModel?._linker?.BoneCache == null || internalModel._linker.BoneCache.Length == 0) { MessageBox.Show("The target model must have at least one bone.", "Import Error", MessageBoxButtons.OK, MessageBoxIcon.Error); return(DialogResult.Cancel); } ResourceNode[] objects = externalModel.FindChild("Objects", true)?.Children.ToArray(); if (objects == null || objects.Length == 0) { MessageBox.Show("The imported model must have at least one object.", "Import Error", MessageBoxButtons.OK, MessageBoxIcon.Error); return(DialogResult.Cancel); } _internalModel = internalModel; _externalModel = externalModel; comboBox1.Items.AddRange(objects); comboBox2.Items.AddRange(_internalModel._linker.BoneCache); comboBox1.SelectedIndex = comboBox2.SelectedIndex = comboBox3.SelectedIndex = 0; _parent = (MDL0BoneNode)comboBox2.SelectedItem; return(ShowDialog(null)); }
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, _entryIndex = model._linker.BoneCache.Length }; bone.FrameState = bone.BindState = FrameState.Neutral; _resource.AddChild(bone, true); bone.RecalcFrameState(); bone.RecalcBindState(false, false, false); model._linker.RegenerateBoneCache(); TreeView.EndUpdate(); Nodes[Nodes.Count - 1].EnsureVisible(); //TreeView.SelectedNode = Nodes[Nodes.Count - 1]; }
protected override void OnShown(EventArgs e) { modelEditControl1._openedFiles.Add(Program.RootNode); MainForm.Instance.Visible = !Properties.Settings.Default.ViewerSettings.HideMainWindow; if (_models.Count != 0) { for (int i = 0; i < _models.Count; i++) { if (_models[i] != null) { modelEditControl1.AppendTarget(_models[i]); } } modelEditControl1.TargetModel = _models[0]; modelEditControl1.EditingAll = _models.Count > 1; modelEditControl1.ResetBoneColors(); } else { modelEditControl1.TargetModel = null; } if (_collisions.Count != 0) { foreach (CollisionNode node in _collisions) { modelEditControl1.AppendTarget(node); // Link bones foreach (CollisionObject obj in node.Children) { if (obj._modelName == "" || obj._boneName == "") { continue; } MDL0Node model = _models.Where(m => m is MDL0Node && ((ResourceNode)m).Name == obj._modelName) .FirstOrDefault() as MDL0Node; if (model != null) { MDL0BoneNode bone = model._linker.BoneCache.Where(b => b.Name == obj._boneName) .FirstOrDefault() as MDL0BoneNode; if (bone != null) { obj._linkedBone = bone; } } } } } modelEditControl1.ModelPanel.Capture(); ReadSettings(); base.OnShown(e); }
public void RunEvent(int eventIndex) { //Get the current event and its id e = this[eventIndex]; //Run event only if allowed or if an exception if (e == null || !_runEvents && !_runExceptions.Contains(eventId >> 16)) { return; } uint eventIdTemp = eventId & 0xFFFFFF00; //Cut out unk value //if (_events.ContainsKey(eventIdTemp)) // _events[eventIdTemp].Invoke(this, null); //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 (eventIdTemp) { 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 = e[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(e[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(e[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(e[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 = e[0]; if (id < 0 || id >= RunTime._articles.Length) { break; } articleInfo = RunTime._articles[id]; if (articleInfo != null && articleInfo._model != null) { articleInfo._model.IsRendering = e[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)(e[0] & 0xFFFF); hitbox.HitboxSize = e[5]; RunTime._hitBoxes.Add(hitbox); break; case 0x06050100: //Body Collision _hurtBoxType = e[0]; break; case 0x06080200: //Bone Collision id = e[0]; if (Root.Model != null && Root.Model._linker.BoneCache.Length > id && id >= 0) { MDL0BoneNode bone = Root.Model._linker.BoneCache[id] as MDL0BoneNode; switch ((int)e[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 = e[0]; hitbox.HitboxSize = e[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)(e[0] & 0xFFFF); hitbox.HitboxSize = e[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 == e[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 == e[0] && hbox.IsCatch()) { RunTime._hitBoxes.RemoveAt(i--); break; } } break; case 0x061B0500: //Move hitbox foreach (HitBox hbox in RunTime._hitBoxes) { if (hbox.HitboxID == e[0] && hbox.IsOffensive(true)) { hbox._parameters[1] = e[1]; hbox._parameters[6] = e[2]; hbox._parameters[7] = e[3]; hbox._parameters[8] = e[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 = e[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; } if (Manager.SoundArchive != null) { RSARNode node = Manager.SoundArchive; List <RSAREntryNode> sounds = node._infoCache[0]; id = e[0]; if (sounds != null && 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 == null || Root.Model._objList == null || Root.Data._modelVis.Count == 0) { break; } visNode = Root.Data._modelVis; } if (visNode != null) { int refId = ((int)((eventId >> 16) & 0xFF)); int switchId = e[0]; int groupId = e[1]; visNode.ApplyVisibility(refId, switchId, groupId); } break; case 0x0B020100: //Model visibility if (Article == null) { Root.Model.IsRendering = e[0] != 0; } else if (Article.Index < RunTime._articles.Length && RunTime._articles[Article.Index]._model != null) { RunTime._articles[Article.Index]._model.IsRendering = e[0] != 0; } break; case 0x0D000200: //Concurrent Infinite Loop index = e[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 = e[0]; if (RunTime._concurrentLoopScripts.ContainsKey(index)) { RunTime._concurrentLoopScripts.Remove(index); } break; case 0x0E000100: //Set Air/Ground RunTime._location = (RunTime.Location)((int)e[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; MovesetNode 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 = e[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; } articleInfo.Running = !removeArticle; break; case 0x10040200: //Set Anchored Article SubAction case 0x10070200: //Set Remote Article SubAction id = e[0]; int sId = e[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(e[0]); reqInfo = new RequirementInfo(e[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(e[0], eCount == 2 && e[1] != 0); RunTime.AddSubActionChangeInfo(sChangeInfo); break; case 0x04010200: //Change Subaction sChangeInfo = new SubActionChangeInfo(e[0], false); sChangeInfo._requirements.Add(new RequirementInfo(e[1])); RunTime.AddSubActionChangeInfo(sChangeInfo); break; case 0x11010A00: //External Graphic Effect case 0x11001000: //Same as prev but with random offset and rotation bool random = ((eventId >> 16) & 0xFF) == 0; break; case 0x111A1000: //Graphic Effect; no file break; } }
public IModel ImportModel(string filePath, ImportType type) { IModel model = null; ModelType = type; BoneType = ModelType == ImportType.MDL0 ? typeof(MDL0BoneNode) : null; //TransformMatrix = Matrix.TransformMatrix(_importOptions._modifyScale, _importOptions._modifyRotation, new Vector3()); switch (type) { case ImportType.MDL0: MDL0Node m = new MDL0Node() { _name = Path.GetFileNameWithoutExtension(filePath), _version = _importOptions._modelVersion.Clamp(8, 11) }; if (_importOptions._setOrigPath) { m._originalPath = filePath; } m.BeginImport(); model = m; break; } CurrentModel = model; Error = "There was a problem reading the model."; using (DecoderShell shell = DecoderShell.Import(filePath)) try { Error = "There was a problem reading texture entries."; //Extract images, removing duplicates foreach (ImageEntry img in shell._images) { string name = img._path != null? Path.GetFileNameWithoutExtension(img._path) : img._name != null ? img._name : img._id; switch (type) { case ImportType.MDL0: img._node = ((MDL0Node)model).FindOrCreateTexture(name); break; } } Error = "There was a problem creating a default shader."; //Create a shader ResourceNode shader = null; switch (type) { case ImportType.MDL0: MDL0Node m = (MDL0Node)model; MDL0ShaderNode shadNode = new MDL0ShaderNode() { _ref0 = 0, _ref1 = -1, _ref2 = -1, _ref3 = -1, _ref4 = -1, _ref5 = -1, _ref6 = -1, _ref7 = -1, }; shadNode._parent = m._shadGroup; m._shadList.Add(shadNode); switch (_importOptions._mdlType) { case ImportOptions.MDLType.Character: for (int i = 0; i < 3; i++) { switch (i) { case 0: shadNode.AddChild(new MDL0TEVStageNode(0x28F8AF, 0x08F2F0, 0, TevKColorSel.ConstantColor0_RGB, TevKAlphaSel.ConstantColor0_Alpha, TexMapID.TexMap0, TexCoordID.TexCoord0, ColorSelChan.LightChannel0, true)); break; case 1: shadNode.AddChild(new MDL0TEVStageNode(0x08FEB0, 0x081FF0, 0, TevKColorSel.ConstantColor1_RGB, TevKAlphaSel.ConstantColor0_Alpha, TexMapID.TexMap7, TexCoordID.TexCoord7, ColorSelChan.LightChannel0, false)); break; case 2: shadNode.AddChild(new MDL0TEVStageNode(0x0806EF, 0x081FF0, 0, TevKColorSel.ConstantColor0_RGB, TevKAlphaSel.ConstantColor0_Alpha, TexMapID.TexMap7, TexCoordID.TexCoord7, ColorSelChan.Zero, false)); break; } } break; case ImportOptions.MDLType.Stage: shadNode.AddChild(new MDL0TEVStageNode(0x28F8AF, 0x08F2F0, 0, TevKColorSel.ConstantColor0_RGB, TevKAlphaSel.ConstantColor0_Alpha, TexMapID.TexMap0, TexCoordID.TexCoord0, ColorSelChan.LightChannel0, true)); break; } shader = shadNode; break; } Error = "There was a problem extracting materials."; //Extract materials foreach (MaterialEntry mat in shell._materials) { List <ImageEntry> imgEntries = new List <ImageEntry>(); //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) { imgEntries.Add(img); break; } } } } } } } } switch (type) { case ImportType.MDL0: MDL0MaterialNode matNode = new MDL0MaterialNode(); MDL0Node m = (MDL0Node)model; matNode._parent = m._matGroup; m._matList.Add(matNode); matNode._name = mat._name != null ? mat._name : mat._id; matNode.ShaderNode = shader as MDL0ShaderNode; mat._node = matNode; matNode._cull = _importOptions._culling; foreach (ImageEntry img in imgEntries) { 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._uWrap = mr._vWrap = (int)_importOptions._wrap; } break; } } Say("Extracting scenes..."); List <ObjectInfo> _objects = new List <ObjectInfo>(); ResourceNode boneGroup = null; switch (type) { case ImportType.MDL0: boneGroup = ((MDL0Node)model)._boneGroup; break; } //Extract bones and objects and create bone tree foreach (SceneEntry scene in shell._scenes) { foreach (NodeEntry node in scene._nodes) { EnumNode(node, boneGroup, scene, model, shell, _objects, TransformMatrix, Matrix.Identity); } } //Add root bone if there are no bones if (boneGroup.Children.Count == 0) { switch (type) { case ImportType.MDL0: MDL0BoneNode bone = new MDL0BoneNode(); bone.Scale = new Vector3(1); bone.RecalcBindState(false, false); bone._name = "TopN"; TempRootBone = bone; break; } } //Create objects foreach (ObjectInfo obj in _objects) { NodeEntry node = obj._node; string w = obj._weighted ? "" : "un"; string w2 = obj._weighted ? "\nOne or more vertices may not be weighted correctly." : ""; string n = node._name != null ? node._name : node._id; Error = String.Format("There was a problem decoding {0}weighted primitives for the object {1}.{2}", w, n, w2); Say(String.Format("Decoding {0}weighted primitives for {1}...", w, n)); obj.Initialize(model, shell); } //Finish switch (type) { case ImportType.MDL0: MDL0Node mdl0 = (MDL0Node)model; if (TempRootBone != null) { mdl0._boneGroup._children.Add(TempRootBone); TempRootBone._parent = mdl0._boneGroup; } FinishMDL0(mdl0); break; } } #if !DEBUG catch (Exception x) { MessageBox.Show("Cannot continue importing this model.\n" + Error + "\n\nException:\n" + x.ToString()); model = null; Close(); } #endif finally { //Clean up the mess we've made GC.Collect(GC.MaxGeneration, GCCollectionMode.Forced); } CurrentModel = null; Error = null; return(model); }
public void FlipY(bool allowBoundaryFix) { MDL0Node model = ((MDL0Node)_resource); bool boundaryFixActive = false; if (allowBoundaryFix) { if (model.Name == "StgPosition" || model.Name == "Stgposition" || model.Name == "stgPosition" || model.Name == "stgposition" || model.Name == "StagePosition" || model.Name == "Stageposition" || model.Name == "stagePosition" || model.Name == "stageposition") { boundaryFixActive = true; } else if (model.Name.Length == 13) { //Console.WriteLine(model + " was found to be 13 characters long"); if (model.Name.Substring(0, 11) == "PokeTrainer" || model.Name.Substring(0, 11) == "Poketrainer" || model.Name.Substring(0, 11) == "pokeTrainer" || model.Name.Substring(0, 11) == "poketrainer") { //Console.WriteLine("It's a pokemon trainer"); boundaryFixActive = true; } } } if (model.FindBoneByIndex(0) != null) { MDL0BoneNode b = model.FindBoneByIndex(0); MDL0BoneNode b2 = null; int j = 0; float camPositionSaverY = 0; float deathPositionSaverY = 0; bool camPositionSaved = false; bool deathPositionSaved = false; bool camPositionSet = false; bool deathPositionSet = false; bool isRestrictedName = false; while (b != null) { j++; if (boundaryFixActive) { // if (b.Name == "CamLimit0N" && !camPositionSet) { isRestrictedName = true; if (!camPositionSaved) { camPositionSaverY = b.getManualTranslation('Y'); camPositionSaved = true; } else { b2 = model.FindBone("CamLimit1N"); if (b2 != null) { float tempCam0 = b.getManualTranslation('Y'); b.setManualTranslation('Y', 0 - camPositionSaverY); b2.setManualTranslation('Y', 0 - tempCam0); camPositionSet = true; } } } else if (b.Name == "CamLimit1N" && !camPositionSet) { isRestrictedName = true; if (!camPositionSaved) { camPositionSaverY = b.getManualTranslation('Y'); camPositionSaved = true; } else { b2 = model.FindBone("CamLimit0N"); if (b2 != null) { float tempCam1 = b.getManualTranslation('Y'); b.setManualTranslation('Y', 0 - camPositionSaverY); b2.setManualTranslation('Y', 0 - tempCam1); camPositionSet = true; } } } else if (b.Name == "Dead0N" && !deathPositionSet) { isRestrictedName = true; if (!deathPositionSaved) { deathPositionSaverY = b.getManualTranslation('Y'); deathPositionSaved = true; } else { b2 = model.FindBone("Dead1N"); if (b2 != null) { float tempDead0 = b.getManualTranslation('Y'); b.setManualTranslation('Y', 0 - deathPositionSaverY); b2.setManualTranslation('Y', 0 - tempDead0); deathPositionSet = true; } } } else if (b.Name == "Dead1N" && !deathPositionSet) { isRestrictedName = true; if (!deathPositionSaved) { deathPositionSaverY = b.getManualTranslation('Y'); deathPositionSaved = true; } else { b2 = model.FindBone("Dead0N"); if (b2 != null) { float tempDead1 = b.getManualTranslation('Y'); b.setManualTranslation('Y', 0 - deathPositionSaverY); b2.setManualTranslation('Y', 0 - tempDead1); deathPositionSet = true; } } } else if (b.Name.EndsWith("E")) { //Console.WriteLine("Found E Bone: " + b); string b2Finder = b.Name.Remove(b.Name.Length - 1, 1) + "N"; //Console.WriteLine("Searching for " + b2Finder); b2 = model.FindBone(b2Finder); if (b2 != null) { //Console.WriteLine("Found! " + b2); float tempE = b.getManualTranslation('Y'); float tempN = b2.getManualTranslation('Y'); b.setManualTranslation('Y', 0 - tempN); b2.setManualTranslation('Y', 0 - tempE); isRestrictedName = true; } else { isRestrictedName = false; } } else if (b.Name.EndsWith("N")) { //Console.WriteLine("Found N Bone: " + b); string b2Finder = b.Name.Remove(b.Name.Length - 1, 1) + "E"; //Console.WriteLine("Searching for " + b2Finder); b2 = model.FindBone(b2Finder); if (b2 != null) { //Console.WriteLine("Found! Will not regenerate as was set by " + b2); isRestrictedName = true; } else { isRestrictedName = false; } } } if (!boundaryFixActive || !isRestrictedName) { b.setManualTranslation('Y', 0 - b.getManualTranslation('Y')); b.setManualRotation('Z', 0 - b.getManualRotation('Z')); } b = model.FindBoneByIndex(j); isRestrictedName = false; } } }
public void RenderBrawlStageData(ModelPanelViewport panel) { //If you ever make changes to GL attributes (enabled and disabled things) //and don't want to keep track of what you changed, //you can push all attributes and then pop them when you're done, like this. //This will make sure the GL state is back to how it was before you changed it. GL.PushAttrib(AttribMask.AllAttribBits); GL.Disable(EnableCap.DepthTest); if (RenderCollisions) { foreach (CollisionNode node in _collisions) { node.Render(); } } #region RenderOverlays List <MDL0BoneNode> ItemBones = new List <MDL0BoneNode>(); MDL0Node stgPos = null; MDL0BoneNode CamBone0 = null, CamBone1 = null, DeathBone0 = null, DeathBone1 = null; //Get bones and render spawns if checked if (_targetModel != null && _targetModel is MDL0Node && (((ResourceNode)_targetModel).Name.Contains("StgPosition") || ((ResourceNode)_targetModel).Name.Contains("stagePosition"))) { stgPos = _targetModel as MDL0Node; } else if (_targetModels != null) { stgPos = _targetModels.Find(x => x is MDL0Node && ((ResourceNode)x).Name.Contains("StgPosition") || ((ResourceNode)x).Name.Contains("stagePosition")) as MDL0Node; } if (stgPos != null) { foreach (MDL0BoneNode bone in stgPos._linker.BoneCache) { if (bone._name == "CamLimit0N") { CamBone0 = bone; } else if (bone.Name == "CamLimit1N") { CamBone1 = bone; } else if (bone.Name == "Dead0N") { DeathBone0 = bone; } else if (bone.Name == "Dead1N") { DeathBone1 = bone; } else if (bone._name.StartsWith("Player") && bone._name.Length == 8 && chkSpawns.Checked) { Vector3 position = bone._frameMatrix.GetPoint(); if (PointCollides(position)) { GL.Color4(0.0f, 1.0f, 0.0f, 0.5f); } else { GL.Color4(1.0f, 0.0f, 0.0f, 0.5f); } TKContext.DrawSphere(position, 5.0f, 32); if (int.TryParse(bone._name.Substring(6, 1), out int playernum)) { panel.NoSettingsScreenText[playernum.ToString()] = panel.Camera.Project(position) - new Vector3(8.0f, 8.0f, 0); } } else if (bone._name.StartsWith("Rebirth") && bone._name.Length == 9 && chkSpawns.Checked) { GL.Color4(1.0f, 1.0f, 1.0f, 0.1f); TKContext.DrawSphere(bone._frameMatrix.GetPoint(), 5.0f, 32); if (int.TryParse(bone._name.Substring(7, 1), out int playernum)) { panel.NoSettingsScreenText[playernum.ToString()] = panel.Camera.Project(bone._frameMatrix.GetPoint()) - new Vector3(8.0f, 8.0f, 0); } } else if (bone._name.StartsWith("Item")) { ItemBones.Add(bone); } } } //Render item fields if checked if (ItemBones != null && chkItems.Checked) { GL.Color4(0.5f, 0.0f, 1.0f, 0.4f); for (int i = 0; i < ItemBones.Count; i += 2) { Vector3 pos1, pos2; if (ItemBones[i]._frameMatrix.GetPoint()._y == ItemBones[i + 1]._frameMatrix.GetPoint()._y) { pos1 = new Vector3(ItemBones[i]._frameMatrix.GetPoint()._x, ItemBones[i]._frameMatrix.GetPoint()._y + 1.5f, 1.0f); pos2 = new Vector3(ItemBones[i + 1]._frameMatrix.GetPoint()._x, ItemBones[i + 1]._frameMatrix.GetPoint()._y - 1.5f, 1.0f); } else { pos1 = new Vector3(ItemBones[i]._frameMatrix.GetPoint()._x, ItemBones[i]._frameMatrix.GetPoint()._y, 1.0f); pos2 = new Vector3(ItemBones[i + 1]._frameMatrix.GetPoint()._x, ItemBones[i + 1]._frameMatrix.GetPoint()._y, 1.0f); } if (pos1._x != pos2._x) { TKContext.DrawBox(pos1, pos2); } else { TKContext.DrawSphere( new Vector3(ItemBones[i]._frameMatrix.GetPoint()._x, ItemBones[i]._frameMatrix.GetPoint()._y, pos1._z), 3.0f, 32); } } } //Render boundaries if checked if (CamBone0 != null && CamBone1 != null && chkBoundaries.Checked) { //GL.Clear(ClearBufferMask.DepthBufferBit); GL.Disable(EnableCap.DepthTest); GL.Disable(EnableCap.Lighting); GL.PolygonMode(MaterialFace.FrontAndBack, PolygonMode.Fill); GL.Enable(EnableCap.CullFace); GL.CullFace(CullFaceMode.Front); GL.Color4(Color.Blue); GL.Begin(BeginMode.LineLoop); GL.LineWidth(15.0f); Vector3 camBone0 = CamBone0._frameMatrix.GetPoint(), camBone1 = CamBone1._frameMatrix.GetPoint(), deathBone0 = DeathBone0._frameMatrix.GetPoint(), deathBone1 = DeathBone1._frameMatrix.GetPoint(); GL.Vertex2(camBone0._x, camBone0._y); GL.Vertex2(camBone1._x, camBone0._y); GL.Vertex2(camBone1._x, camBone1._y); GL.Vertex2(camBone0._x, camBone1._y); GL.End(); GL.Begin(BeginMode.LineLoop); GL.Color4(Color.Red); GL.Vertex2(deathBone0._x, deathBone0._y); GL.Vertex2(deathBone1._x, deathBone0._y); GL.Vertex2(deathBone1._x, deathBone1._y); GL.Vertex2(deathBone0._x, deathBone1._y); GL.End(); GL.Color4(0.0f, 0.5f, 1.0f, 0.3f); GL.Begin(BeginMode.TriangleFan); GL.Vertex2(camBone0._x, camBone0._y); GL.Vertex2(deathBone0._x, deathBone0._y); GL.Vertex2(deathBone1._x, deathBone0._y); GL.Vertex2(camBone1._x, camBone0._y); GL.End(); GL.Begin(BeginMode.TriangleFan); GL.Vertex2(camBone1._x, camBone1._y); GL.Vertex2(deathBone1._x, deathBone1._y); GL.Vertex2(deathBone0._x, deathBone1._y); GL.Vertex2(camBone0._x, camBone1._y); GL.End(); GL.Begin(BeginMode.TriangleFan); GL.Vertex2(camBone1._x, camBone0._y); GL.Vertex2(deathBone1._x, deathBone0._y); GL.Vertex2(deathBone1._x, deathBone1._y); GL.Vertex2(camBone1._x, camBone1._y); GL.End(); GL.Begin(BeginMode.TriangleFan); GL.Vertex2(camBone0._x, camBone1._y); GL.Vertex2(deathBone0._x, deathBone1._y); GL.Vertex2(deathBone0._x, deathBone0._y); GL.Vertex2(camBone0._x, camBone0._y); GL.End(); } #endregion GL.PopAttrib(); }
static void Weight(PrimitiveManager manager, SkinEntry skin, DecoderShell shell, GeometryEntry geo, InfluenceManager iMan) { 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; ushort * pVInd = (ushort *)manager._indices.Address; List <Vertex3> vertList = new List <Vertex3>(skin._weightCount); 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; } } break; } } //Populate bone list boneCount = jointStrings.Length; boneList = new MDL0BoneNode[boneCount]; for (int i = 0; i < boneCount; i++) { boneList[i] = shell.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; } } //Construct Vertex from new weight for (int i = 0; i < skin._weightCount; i++) { //Create influence int iCount = skin._weights.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[x] = new BoneWeight(bone, weight); } } //Match with manager inf = iMan.AddOrCreateInf(inf); //Create Vertex and look for match Vertex3 v = new Vertex3(pVert[*pVInd], inf); int index = 0; while (index < vertList.Count) { if (v.Equals(vertList[i])) { break; } index++; } if (index == vertList.Count) { vertList.Add(v); } //Assign new index *pVInd++ = (ushort)index; } }
private static unsafe void WriteControllers(MDL0Node model, XmlWriter writer) { if (model._polyList == 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); //} List <float> weightSet = new List <float>(); Matrix m; bool first; foreach (MDL0PolygonNode poly in model._polyList) { 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; } float *fPtr = (float *)&m; first = true; for (int y = 0; y < 4; y++) { for (int x = 0; x < 4; x++) { if (first) { first = false; } else { writer.WriteString(" "); } writer.WriteValue(fPtr[(x << 2) + y]); } } writer.WriteEndElement(); //Get list of used bones and weights //int index = 0; if (poly._singleBind != null) { foreach (BoneWeight w in poly._singleBind.Weights) { //if (!boneSet.Contains(w.Bone)) //{ // boneSet.Add(w.Bone); // w.Bone._nodeIndex = index++; //} if (!weightSet.Contains(w.Weight)) { weightSet.Add(w.Weight); } } } else { foreach (Vertex3 v in verts) { foreach (BoneWeight w in v._influence.Weights) { //if (!boneSet.Contains(w.Bone)) //{ // boneSet.Add(w.Bone); // w.Bone._nodeIndex = index++; //} if (!weightSet.Contains(w.Weight)) { weightSet.Add(w.Weight); } } } } //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 boneSet) foreach (MDL0BoneNode b in bones) { m = b.InverseBindMatrix; fPtr = (float *)&m; for (int y = 0; y < 4; y++) { for (int x = 0; x < 4; x++) { if (first) { first = false; } else { writer.WriteString(" "); } writer.WriteValue(fPtr[(x << 2) + y]); } } } 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.Count.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.Count.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._singleBind != null) { for (int i = 0; i < verts.Count; i++) { if (first) { first = false; } else { writer.WriteString(" "); } writer.WriteString(poly._singleBind.Weights.Length.ToString()); } } else { foreach (Vertex3 v in verts) { if (first) { first = false; } else { writer.WriteString(" "); } writer.WriteString(v._influence.Weights.Length.ToString()); } } writer.WriteEndElement(); //vcount writer.WriteStartElement("v"); first = true; if (poly._singleBind != null) { for (int i = 0; i < verts.Count; i++) { foreach (BoneWeight w in poly._singleBind.Weights) { if (first) { first = false; } else { writer.WriteString(" "); } //writer.WriteString(w.Bone._nodeIndex.ToString()); writer.WriteString(Array.IndexOf(bones, w.Bone).ToString()); writer.WriteString(" "); writer.WriteString(weightSet.IndexOf(w.Weight).ToString()); } } } else { foreach (Vertex3 v in verts) { foreach (BoneWeight w in v._influence.Weights) { if (first) { first = false; } else { writer.WriteString(" "); } //writer.WriteString(w.Bone._nodeIndex.ToString()); writer.WriteString(Array.IndexOf(bones, w.Bone).ToString()); writer.WriteString(" "); writer.WriteString(weightSet.IndexOf(w.Weight).ToString()); } } } writer.WriteEndElement(); //v writer.WriteEndElement(); //vertex_weights writer.WriteEndElement(); //skin writer.WriteEndElement(); //controller //boneSet.Clear(); weightSet.Clear(); } writer.WriteEndElement(); }
static PrimitiveManager DecodePrimitivesWeighted(GeometryEntry geo, SkinEntry skin, SceneEntry scene, InfluenceManager infManager, ref string Error) { PrimitiveManager manager = DecodePrimitives(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; //List<int> FixedIndices = new List<int>(); 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]; } } //if (bone != null) // if (bone.Name == "TopN" || bone.Name == "XRotN" || bone.Name == "YRotN" || bone.Name == "TransN" || bone.Name == "ThrowN" || bone.Name == "FacePattern") // Console.WriteLine(bone.Name); // else if (bone.Parent != null) // if (bone.Parent.Name == "FacePattern") // Console.WriteLine(bone.Name); inf._weights[x] = 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.Length > 1) { //Match with manager inf = infManager.AddOrCreate(inf); v = new Vertex3(skin._bindMatrix * pVert[i], inf); //World position } else { bone = inf._weights[0].Bone; v = new Vertex3(bone._inverseBindMatrix * skin._bindMatrix * pVert[i], bone); //Local position } ////Create Vertex, set to world position. //v = new Vertex3(skin._bindMatrix * pVert[i], inf); ////Fix single-bind vertices //v.Position = inf._weights[0].Bone._inverseBindMatrix * v.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._influence != null) { if (v._influence.Weights.Length > 1) { pNorms[i] = skin._bindMatrix.GetRotationMatrix() * pNorms[i]; } else { pNorms[i] = skin._bindMatrix.GetRotationMatrix() * v._influence.Weights[0].Bone._inverseBindMatrix.GetRotationMatrix() * pNorms[i]; } } } remap.Dispose(); //manager.MergeTempData(); return(manager); }
protected unsafe virtual void modelPanel1_MouseMove(object sender, MouseEventArgs e) { if (_playing) { return; } ModelPanel panel = sender as ModelPanel; ModelPanelViewport viewport = panel.CurrentViewport; Vector3?point; if (_boneSelection.IsMoving() && SelectedBone != null) { Vector3 transform = GetLocalTransform(e, viewport, GetBoneWorldMtx(), GetBoneInvWorldMtx(), GetBoneParentTransformMtx(), _boneSelection, out point); if (Alt && !_createdNewBone) { if (SelectedBone is MDL0BoneNode) { _createdNewBone = true; MDL0BoneNode b = SelectedBone as MDL0BoneNode; MDL0Node model = b.Model; MDL0BoneNode newBone = new MDL0BoneNode(); string name = "NewBone"; if (model != null) { name += "0"; int id = 1; Top: foreach (MDL0BoneNode x in model._linker.BoneCache) { if (x.Name == name) { name = "NewBone" + id++; goto Top; } } newBone._entryIndex = model._linker.BoneCache.Length; } newBone.Name = name; newBone.FrameState = newBone.BindState = FrameState.Neutral; b.AddChild(newBone); newBone.RecalcFrameState(); newBone.RecalcBindState(false, false, false); model?._linker.RegenerateBoneCache(); BonesPanel?.Reset(); SelectedBone = newBone; } } if (point != null) { for (int i = 0; i < 3; i++) { _boneTransform[(int)ControlType](i, transform[i]); } _boneSelection._lastPointLocal = GetBoneInvWorldMtx() * point.Value; } } if (_vertexSelection.IsMoving() && VertexLoc != null) { Vector3 center = VertexLoc.Value; Vector3 transform = GetLocalTransform(e, viewport, Matrix.TranslationMatrix(center), Matrix.TranslationMatrix(-center), Matrix.Identity, _vertexSelection, out point); if (point != null) { switch (ControlType) { case TransformType.Scale: foreach (Vertex3 vertex in _selectedVertices) { vertex.WeightedPosition = Maths.ScaleAboutPoint(vertex.WeightedPosition, center, transform); } break; case TransformType.Rotation: foreach (Vertex3 vertex in _selectedVertices) { vertex.WeightedPosition = Maths.RotateAboutPoint(vertex.WeightedPosition, center, transform); } break; case TransformType.Translation: foreach (Vertex3 vertex in _selectedVertices) { vertex.WeightedPosition += transform; } break; } _vertexLoc = null; _vertexSelection._lastPointLocal = Matrix.TranslationMatrix(-VertexLoc.Value) * point.Value; } UpdateModel(); } bool allowHighlight = !DoNotHighlightOnMouseMove; bool draggingSelection = viewport.Selecting; //if not dragging a point AND (highlighting is allowed, or not but selecting) if (!_boneSelection.IsMoving() && !_vertexSelection.IsMoving() && (allowHighlight || (!allowHighlight && draggingSelection))) { HighlightStuff(e, panel); } }
private void GetBaseInfluence() { if (_node != null) { modelPanel1.RemoveReference(_node); } MDL0BoneNode[] boneCache = _externalModel._linker.BoneCache; if ((_node = (MDL0ObjectNode)comboBox1.SelectedItem).Weighted) { int least = int.MaxValue; foreach (IMatrixNode inf in _node.Influences) { if (inf is MDL0BoneNode && ((MDL0BoneNode)inf).BoneIndex < least) { least = ((MDL0BoneNode)inf).BoneIndex; } } if (least != int.MaxValue) { MDL0BoneNode temp = boneCache[least]; _baseInf = (IMatrixNode)temp.Parent; } } else { _baseInf = _node.MatrixNode; } if (_baseInf is Influence) { label2.Hide(); comboBox2.Hide(); } else if (_baseInf is MDL0BoneNode) { label2.Show(); comboBox2.Show(); } baseBone.Text = _baseInf.ToString(); if (comboBox3.SelectedIndex == 0 && _baseInf is MDL0BoneNode) { int i = 0; foreach (MDL0BoneNode s in comboBox2.Items) { if (s.Name == baseBone.Text) { comboBox2.SelectedIndex = i; break; } i++; } } _node.IsRendering = true; modelPanel1.ClearTargets(); modelPanel1.AddTarget(_node, false); modelPanel1.SetCamWithBox(_node.GetBox()); }
public Influence(MDL0BoneNode bone) { _weights = new BoneWeight[] { new BoneWeight(bone) }; }
public static void Serialize(CHR0Node node, bool bake, string output) { MDL0Node model; OpenFileDialog dlgOpen = new OpenFileDialog(); dlgOpen.Filter = "MDL0 Model (*.mdl0)|*.mdl0"; dlgOpen.Title = "Select the model this animation is for..."; if (dlgOpen.ShowDialog() != DialogResult.OK || (model = (MDL0Node)NodeFactory.FromFile(null, dlgOpen.FileName)) == null) { return; } using (StreamWriter file = new StreamWriter(output)) { file.WriteLine("animVersion 1.1;"); file.WriteLine("mayaVersion 2015;"); file.WriteLine("timeUnit ntsc;"); file.WriteLine("linearUnit cm;"); file.WriteLine("angularUnit deg;"); file.WriteLine("startTime 1;"); file.WriteLine(String.Format("endTime {0};", node.FrameCount)); foreach (CHR0EntryNode e in node.Children) { MDL0BoneNode bone = model.FindChild("Bones/" + e.Name, true) as MDL0BoneNode; if (bone == null) { continue; } KeyframeCollection c = e.Keyframes; for (int index = 0; index < 9; index++) { KeyframeArray array = c._keyArrays[index]; if (array._keyCount <= 0) { continue; } file.WriteLine(String.Format("anim {0}.{0}{1} {0}{1} {2} {3} {4} {5}", types[index / 3], axes[index % 3], e.Name, 0, bone.Children.Count, index < 6 ? (index + 3) : index - 6)); file.WriteLine("animData {"); file.WriteLine(" input time;"); file.WriteLine(String.Format(" output {0};", index > 2 && index < 6 ? "angular" : "linear")); file.WriteLine(" weighted 0;"); file.WriteLine(" preInfinity constant;"); file.WriteLine(" postInfinity constant;"); file.WriteLine(" keys {"); for (KeyframeEntry entry = array._keyRoot._next; (entry != array._keyRoot); entry = entry._next) { bool single = entry._next._index < 0 && entry._prev._index < 0; //float angle = (float)Math.Atan(entry._tangent) * Maths._rad2degf; //if (single) { file.WriteLine(String.Format(" {0} {1} {2} {2} {3} {4} {5};", entry._index + 1, entry._value.ToString(CultureInfo.InvariantCulture.NumberFormat), "auto",//single ? "auto" : "fixed", "1", "1", "0")); } } file.WriteLine(" }"); file.WriteLine("}"); } } } }
public BoneWeight(MDL0BoneNode bone) : this(bone, 1.0f) { }
//Gets world-point of specified mouse point projected onto the selected bone's local space. //Intersects the projected ray with the appropriate plane using the snap flags. private bool GetOrbPoint(Vector2 mousePoint, out Vector3 point) { MDL0BoneNode bone = SelectedBone; if (bone == null) { point = new Vector3(); return(false); } Vector3 lineStart = ModelPanel.UnProject(mousePoint._x, mousePoint._y, 0.0f); Vector3 lineEnd = ModelPanel.UnProject(mousePoint._x, mousePoint._y, 1.0f); Vector3 center = bone._frameMatrix.GetPoint(); Vector3 camera = ModelPanel._camera.GetPoint(); Vector3 normal = new Vector3(); float radius = center.TrueDistance(camera) / _orbRadius * 0.1f; switch (_editType) { case TransformType.Rotation: if (_snapX) { normal = (bone._frameMatrix * new Vector3(1.0f, 0.0f, 0.0f)).Normalize(center); } else if (_snapY) { normal = (bone._frameMatrix * new Vector3(0.0f, 1.0f, 0.0f)).Normalize(center); } else if (_snapZ) { normal = (bone._frameMatrix * new Vector3(0.0f, 0.0f, 1.0f)).Normalize(center); } else if (_snapCirc) { radius *= _circOrbScale; normal = camera.Normalize(center); } else if (Maths.LineSphereIntersect(lineStart, lineEnd, center, radius, out point)) { return(true); } else { normal = camera.Normalize(center); } if (Maths.LinePlaneIntersect(lineStart, lineEnd, center, normal, out point)) { point = Maths.PointAtLineDistance(center, point, radius); return(true); } break; case TransformType.Translation: case TransformType.Scale: if (_snapX && _snapY) { normal = new Vector3(0.0f, 0.0f, 1.0f); } else if (_snapX && _snapZ) { normal = new Vector3(0.0f, 1.0f, 0.0f); } else if (_snapY && _snapZ) { normal = new Vector3(1.0f, 0.0f, 0.0f); } else if (_snapX) { normal = new Vector3(0.0f, 1.0f, 0.0f); } else if (_snapY) { normal = new Vector3(1.0f, 0.0f, 0.0f); } else if (_snapZ) { normal = new Vector3(0.0f, 1.0f, 0.0f); } else if (_editType == TransformType.Scale && _snapX && _snapY && _snapZ) { normal = camera.Normalize(center); } break; } return(Maths.LinePlaneIntersect(lineStart, lineEnd, center, normal, out point)); }
public BoneWeight(MDL0BoneNode bone, float weight) { Bone = bone; Weight = weight; }
private void EnumNode( NodeEntry node, ResourceNode parent, SceneEntry scene, IModel model, DecoderShell shell, List <ObjectInfo> objects, Matrix bindMatrix, Matrix parentInvMatrix) { bindMatrix *= node._matrix; if (node._type == NodeType.JOINT || (node._type == NodeType.NONE && node._instances.Count == 0)) { Error = "There was a problem creating a new bone."; Influence inf = null; switch (ModelType) { case ImportType.MDL0: MDL0BoneNode bone = new MDL0BoneNode(); bone._name = node._name != null ? node._name : node._id; bone._bindState = node._matrix.Derive(); node._node = bone; parent._children.Add(bone); bone._parent = parent; bone.RecalcBindState(false, false); bone.CalcFlags(); parent = bone; inf = new Influence(bone); break; } if (inf != null) { model.Influences._influences.Add(inf); } } //parentInvMatrix *= node._matrix.Invert(); foreach (NodeEntry e in node._children) { EnumNode(e, parent, scene, model, shell, objects, bindMatrix, parentInvMatrix); } 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) { objects.Add(new ObjectInfo(true, g, bindMatrix, skin, scene, inst, parent, node)); break; } } break; } } } else if (inst._type == InstanceType.Geometry) { foreach (GeometryEntry g in shell._geometry) { if (g._id == inst._url) { objects.Add(new ObjectInfo(false, g, bindMatrix, null, null, inst, parent, node)); break; } } } else { foreach (NodeEntry e in shell._nodes) { if (e._id == inst._url) { EnumNode(e, parent, scene, model, shell, objects, bindMatrix, parentInvMatrix); } } } } }
public static int CalcSize(Collada form, ModelLinker linker) { MDL0Node model = linker.Model; model._needsNrmMtxArray = model._needsTexMtxArray = false; model._numFacepoints = model._numTriangles = 0; int headerLen, groupLen = 0, tableLen = 0, texLen = 0, boneLen = 0, dataLen = 0, defLen = 0, assetLen = 0, treeLen = 0, mixLen = 0, opaLen = 0, xluLen = 0; int aInd, aLen; //Get header length switch (linker.Version) { case 0x08: case 0x09: headerLen = 0x80; break; case 0x0A: headerLen = 0x88; break; case 0x0B: headerLen = 0x8C; break; default: headerLen = 0x80; //Unsupported version. Change to 9 as default. linker.Version = 9; break; } //Assign node indices AssignNodeIndices(linker); //Get table length tableLen = (linker._nodeCount + 1) << 2; //Get group/data length List <MDLResourceType> iList = ModelLinker.IndexBank[linker.Version]; foreach (MDLResourceType resType in iList) { IEnumerable entryList = null; int entries = 0; switch (resType) { case MDLResourceType.Definitions: //NodeTree treeLen = linker.BoneCache.Length * 5; //NodeMix foreach (Influence i in model._influences._influences) { mixLen += 4; foreach (BoneWeight w in i.Weights) { MDL0BoneNode bone = w.Bone as MDL0BoneNode; if (bone != null && w.Weight != 0 && bone._nodeIndex < linker.NodeCache.Length && bone._nodeIndex >= 0 && linker.NodeCache[bone._nodeIndex] is MDL0BoneNode) { mixLen += 6; } } } foreach (MDL0BoneNode b in linker.BoneCache) { if (b._weightCount > 0) { mixLen += 5; } } //DrawOpa and DrawXlu //Get assigned materials and categorize if (model._objList != null) { for (int i = 0; i < model._objList.Count; i++) { //Entries are ordered by material, not by polygon. //Using the material's attached polygon list is untrustable if the definitions were corrupt on parse. MDL0ObjectNode poly = model._objList[i] as MDL0ObjectNode; model._numTriangles += poly._numFaces; model._numFacepoints += poly._numFacepoints; foreach (DrawCall c in poly._drawCalls) { if (c.DrawPass == DrawCall.DrawPassType.Opaque) { opaLen += 8; } else { xluLen += 8; } } } } //Add terminate byte and set model def flags if (model._hasTree = (treeLen > 0)) { treeLen++; entries++; } if (model._hasMix = (mixLen > 0)) { mixLen++; entries++; } if (model._hasOpa = (opaLen > 0)) { opaLen++; entries++; } if (model._hasXlu = (xluLen > 0)) { xluLen++; entries++; } //Align data defLen += (treeLen + mixLen + opaLen + xluLen).Align(4); break; case MDLResourceType.Vertices: if (model._vertList != null) { entryList = model._vertList; break; } else { aInd = 0; //Set the ID aLen = 1; //Offset count } EvalAssets: List <ResourceNode> polyList = model._objList; if (polyList == null) { break; } string str = ""; bool direct = linker._forceDirectAssets[aInd]; //Create asset lists IList aList; switch (aInd) //Switch by the set ID { case 0: aList = linker._vertices = new List <VertexCodec>(polyList.Count); str = "Vertices "; break; case 1: aList = linker._normals = new List <VertexCodec>(polyList.Count); str = "Normals "; break; case 2: aList = linker._colors = new List <ColorCodec>(polyList.Count); str = "Colors "; break; default: aList = linker._uvs = new List <VertexCodec>(polyList.Count); str = "UVs "; break; } aLen += aInd; for (int i = 0; i < polyList.Count; i++) { MDL0ObjectNode obj = polyList[i] as MDL0ObjectNode; for (int x = aInd; x < aLen; x++) { if (obj._manager._faceData[x] != null) { //Remap color nodes if ((x == 2 || x == 3)) { if (Collada._importOptions._rmpClrs) { obj._elementIndices[x] = -1; foreach (MDL0ObjectNode thatObj in polyList.OrderBy(c => - ((MDL0ObjectNode)c)._manager.GetColors(x - 2, false).Length)) { //Only compare up to the current object if (thatObj == obj) { break; } var thatArr = thatObj._manager.GetColors(x - 2, false); var thisArr = obj._manager.GetColors(x - 2, false); bool equals = true; if (thisArr.Length == thatArr.Length) { for (int n = 0; n < thisArr.Length; n++) { if (thisArr[n] != thatArr[n]) { equals = false; break; } } } else { foreach (RGBAPixel px in thisArr) { if (Array.IndexOf(thatArr, px) < 0) { equals = false; break; } } } if (equals) { //Found a match obj._elementIndices[x] = thatObj._elementIndices[x]; obj._manager._newClrObj[x - 2] = thatObj.Index; break; } } if (obj._elementIndices[x] != -1) { continue; } } else { obj._manager._newClrObj[x - 2] = i; } } obj._elementIndices[x] = (short)aList.Count; if (form != null) { form.Say("Encoding " + str + (x - aInd) + " for Object " + i + ": " + obj.Name); } VertexCodec vert; switch (aInd) { case 0: vert = new VertexCodec(obj._manager.GetVertices(false), false, Collada._importOptions._fltVerts); aList.Add(vert); if (!direct) { assetLen += vert._dataLen.Align(0x20) + 0x40; } break; case 1: vert = new VertexCodec(obj._manager.GetNormals(false), false, Collada._importOptions._fltNrms); aList.Add(vert); if (!direct) { assetLen += vert._dataLen.Align(0x20) + 0x20; } break; case 2: ColorCodec col = new ColorCodec(obj._manager.GetColors(x - 2, false)); aList.Add(col); if (!direct) { assetLen += col._dataLen.Align(0x20) + 0x20; } break; default: vert = new VertexCodec(obj._manager.GetUVs(x - 4, false), Collada._importOptions._fltUVs); aList.Add(vert); if (!direct) { assetLen += vert._dataLen.Align(0x20) + 0x40; } break; } } else { obj._elementIndices[x] = -1; } } } if (!direct) { entries = aList.Count; } break; case MDLResourceType.Normals: if (model._normList != null) { entryList = model._normList; } else { aInd = 1; //Set the ID aLen = 1; //Offset count goto EvalAssets; } break; case MDLResourceType.Colors: if (model._colorList != null) { entryList = model._colorList; } else { if (Collada._importOptions._useOneNode) { HashSet <RGBAPixel> pixels = new HashSet <RGBAPixel>(); if (model._objList != null) { foreach (MDL0ObjectNode obj in model._objList) { for (int i = 0; i < 2; i++) { var arr = obj._manager.GetColors(i, false); if (arr.Length > 0) { obj._elementIndices[i + 2] = 0; foreach (RGBAPixel p in arr) { pixels.Add(p); } } else { obj._elementIndices[i + 2] = -1; } } } } var le = pixels.ToList(); le.Sort(); if (le.Count == 0) { break; } Collada._importOptions._singleColorNodeEntries = le.ToArray(); ColorCodec col = new ColorCodec(Collada._importOptions._singleColorNodeEntries); linker._colors = new List <ColorCodec>() { col }; assetLen += col._dataLen.Align(0x20) + 0x20; entries = 1; } else { aInd = 2; //Set the ID aLen = 2; //Offset count goto EvalAssets; } } break; case MDLResourceType.UVs: if (model._uvList != null) { entryList = model._uvList; } else { aInd = 4; //Set the ID aLen = 8; //Offset count goto EvalAssets; } break; case MDLResourceType.Bones: int index = 0; foreach (MDL0BoneNode b in linker.BoneCache) { if (form != null) { form.Say("Calculating the size of the Bones - " + b.Name); } b._entryIndex = index++; boneLen += b.CalculateSize(true); } entries = linker.BoneCache.Length; break; case MDLResourceType.Materials: if (model._matList != null) { entries = model._matList.Count; } break; case MDLResourceType.Objects: if (model._objList != null) { entryList = model._objList; foreach (MDL0ObjectNode n in model._objList) { if (n.NormalNode != null || n._manager._faceData[1] != null) { model._needsNrmMtxArray = true; } if (n.HasTexMtx) { model._needsTexMtxArray = true; } } } break; case MDLResourceType.Shaders: if (model._matList != null && (entryList = model.GetUsedShaders()) != null) { entries = model._matList.Count; } break; case MDLResourceType.Textures: if (model._texList != null) { List <MDL0TextureNode> texNodes = new List <MDL0TextureNode>(); foreach (MDL0TextureNode tex in model._texList) { texNodes.Add(tex); texLen += (tex._references.Count * 8) + 4; } entries = (linker._texList = texNodes).Count; } break; case MDLResourceType.Palettes: if (model._pltList != null) { List <MDL0TextureNode> pltNodes = new List <MDL0TextureNode>(); foreach (MDL0TextureNode plt in model._pltList) { pltNodes.Add(plt); texLen += (plt._references.Count * 8) + 4; } entries = (linker._pltList = pltNodes).Count; } break; } if (entryList != null) { int index = 0; foreach (MDL0EntryNode e in entryList) { if (form != null) { if (resType == MDLResourceType.Objects) { form.Say("Encoding the " + resType.ToString() + " - " + e.Name); } else { form.Say("Calculating the size of the " + resType.ToString() + " - " + e.Name); } } e._entryIndex = index++; dataLen += e.CalculateSize(true); } if (entries == 0) { entries = index; } } if (entries > 0) { groupLen += (entries * 0x10) + 0x18; } } //Align the materials perfectly using the data length int temp = 0; if (model._matList != null && iList.IndexOf(MDLResourceType.Materials) != -1) { int index = 0; MDL0MaterialNode prev = null; foreach (MDL0MaterialNode e in model._matList) { if (form != null) { form.Say("Calculating the size of the Materials - " + e.Name); } if (index != 0) { e._mdlOffset = (prev = ((MDL0MaterialNode)model._matList[index - 1]))._mdlOffset + prev._calcSize; } else if ((temp = (e._mdlOffset = headerLen + tableLen + groupLen + texLen + defLen + boneLen).Align(0x10)) != e._mdlOffset) { e._dataAlign = temp - e._mdlOffset; } e._entryIndex = index++; dataLen += e.CalculateSize(true); } } if (model._isImport && model._objList != null) { foreach (MDL0ObjectNode obj1 in model._objList) { if (obj1 == null || obj1._drawCalls == null || obj1._drawCalls.Count == 0) { continue; } MDL0MaterialNode p = obj1._drawCalls[0].MaterialNode; if (p == null) { continue; } //Set materials to use register color if option set if (!Collada._importOptions._useReg && linker._colors != null && linker._colors.Count > 0) { p.C1AlphaMaterialSource = GXColorSrc.Vertex; p.C1ColorMaterialSource = GXColorSrc.Vertex; } else { p.C1MaterialColor = Collada._importOptions._dfltClr; p.C1ColorMaterialSource = GXColorSrc.Register; p.C1AlphaMaterialSource = GXColorSrc.Register; } } } return ((linker._headerLen = headerLen) + (linker._tableLen = tableLen) + (linker._groupLen = groupLen) + (linker._texLen = texLen) + (linker._defLen = defLen) + (linker._boneLen = boneLen) + (linker._assetLen = assetLen) + (linker._dataLen = dataLen) + (linker.Version > 9 ? model._userEntries.GetSize() : 0)); }
private static void CreateMDL0Object( InstanceEntry inst, NodeEntry node, ResourceNode parent, PrimitiveManager manager, MDL0Node model, DecoderShell shell) { if (manager != null) { Error = "There was a problem creating a new object for " + (node._name != null ? node._name : node._id); MDL0ObjectNode poly = new MDL0ObjectNode() { _manager = manager, _name = node._name != null ? node._name : node._id, _drawCalls = new BindingList <DrawCall>() }; //Attach material if (inst._material != null) { foreach (MaterialEntry mat in shell._materials) { if (mat._id == inst._material._target) { poly._drawCalls.Add(new DrawCall(poly) { MaterialNode = mat._node as MDL0MaterialNode }); } } } model._numTriangles += poly._numFaces = manager._faceCount = manager._pointCount / 3; model._numFacepoints += poly._numFacepoints = manager._pointCount; poly._parent = model._objGroup; model._objList.Add(poly); model.ResetToBindState(); //Attach single-bind if (parent != null && parent is MDL0BoneNode) { MDL0BoneNode bone = (MDL0BoneNode)parent; poly.DeferUpdateAssets(); poly.MatrixNode = bone; foreach (DrawCall c in poly._drawCalls) { c.VisibilityBoneNode = bone; } } else if (model._boneList.Count == 0) { Error = String.Format("There was a problem rigging {0} to a single bone.", poly._name); Box box = poly.GetBox(); MDL0BoneNode bone = new MDL0BoneNode() { Scale = Vector3.One, Translation = (box.Max + box.Min) / 2.0f, _name = "TransN_" + poly.Name, Parent = TempRootBone, }; poly.DeferUpdateAssets(); poly.MatrixNode = bone; ((MDL0BoneNode)TempRootBone).RecalcBindState(true, false, false); foreach (DrawCall c in poly._drawCalls) { c.VisibilityBoneNode = bone; } } else { Error = String.Format("There was a problem checking if {0} is rigged to a single bone.", poly._name); foreach (DrawCall c in poly._drawCalls) { c.VisibilityBoneNode = model._boneList[0] as MDL0BoneNode; } IMatrixNode mtxNode = null; bool singlebind = true; foreach (Vertex3 v in poly._manager._vertices) { if (v.MatrixNode != null) { if (mtxNode == null) { mtxNode = v.MatrixNode; } if (v.MatrixNode != mtxNode) { singlebind = false; break; } } } if (singlebind && poly._matrixNode == null) { //Reassign reference entries if (poly._manager._vertices[0].MatrixNode != null) { poly._manager._vertices[0].MatrixNode.Users.Add(poly); } foreach (Vertex3 v in poly._manager._vertices) { if (v.MatrixNode != null) { v.MatrixNode.Users.Remove(v); } } poly._nodeId = -2; //Continued on polygon rebuild } } } }
private static void WriteDefs(ModelLinker linker, ref byte *pGroup, ref byte *pData) { MDL0Node mdl = linker.Model; //This should never happen! if (!mdl._hasMix && !mdl._hasOpa && !mdl._hasTree && !mdl._hasXlu) { return; } ResourceNode[] polyList = null; if (mdl._objList != null) { polyList = new ResourceNode[mdl._objList.Count]; Array.Copy(mdl._objList.ToArray(), polyList, mdl._objList.Count); } DrawCall drawCall; int entryCount = 0; byte * floor = pData; int dataLen; ResourceGroup *group = linker.Defs = (ResourceGroup *)pGroup; ResourceEntry *entry = &group->_first + 1; //NodeTree if (mdl._hasTree) { //Write group entry entry[entryCount++]._dataOffset = (int)(pData - pGroup); int bCount = linker.BoneCache.Length; for (int i = 0; i < bCount; i++) { MDL0BoneNode bone = linker.BoneCache[i] as MDL0BoneNode; *pData = 2; //Entry tag *(bushort *)(pData + 1) = (ushort)bone._entryIndex; *(bushort *)(pData + 3) = (ushort)(bone._parent is MDL0BoneNode ? ((MDL0BoneNode)bone._parent)._nodeIndex : 0); pData += 5; //Advance } *pData++ = 1; //Terminate } //NodeMix //Only weight references go here. //First list bones used by weight groups, in bone order //Then list weight groups that use bones. Ordered by entry count. if (mdl._hasMix) { //Write group entry entry[entryCount++]._dataOffset = (int)(pData - pGroup); //Add bones first (using flat bone list) foreach (MDL0BoneNode b in linker.BoneCache) { if (b._weightCount > 0) { *pData = 5; //Tag *(bushort *)(pData + 1) = (ushort)b._nodeIndex; *(bushort *)(pData + 3) = (ushort)b._entryIndex; pData += 5; //Advance } } //Add weight groups (using sorted influence list) foreach (Influence i in mdl._influences._influences) { *pData++ = 3; //Tag *(bushort *)pData = (ushort)i._index; pData += 2; byte *countAddr = pData++; byte count = 0; foreach (BoneWeight w in i.Weights) { MDL0BoneNode bone = w.Bone as MDL0BoneNode; if (bone == null || w.Weight == 0 || bone._nodeIndex >= linker.NodeCache.Length || bone._nodeIndex < 0) { continue; } *(bushort *)pData = (ushort)bone._nodeIndex; *(bfloat *)(pData + 2) = w.Weight; pData += 6; //Advance if (linker.NodeCache[bone._nodeIndex] is MDL0BoneNode) { count++; } } *countAddr = count; } *pData++ = 1; //Terminate } //DrawOpa if (mdl._hasOpa && polyList != null) { var objects = polyList. SelectMany(x => ((MDL0ObjectNode)x)._drawCalls). Where(x => x.DrawPass == DrawCall.DrawPassType.Opaque). ToArray(); Array.Sort(objects, DrawCall.DrawCompare); //Write group entry entry[entryCount++]._dataOffset = (int)(pData - pGroup); for (int i = 0; i < objects.Length; i++) { drawCall = objects[i]; *pData = 4; //Tag *(bushort *)(pData + 1) = (ushort)drawCall.MaterialNode._entryIndex; *(bushort *)(pData + 3) = (ushort)drawCall._parentObject._entryIndex; *(bushort *)(pData + 5) = (ushort)(drawCall.VisibilityBoneNode != null ? drawCall.VisibilityBoneNode.BoneIndex : 0); pData[7] = drawCall.DrawPriority; pData += 8; //Advance } *pData++ = 1; //Terminate } //DrawXlu if (mdl._hasXlu && polyList != null) { var objects = polyList. SelectMany(x => ((MDL0ObjectNode)x)._drawCalls). Where(x => x.DrawPass == DrawCall.DrawPassType.Transparent). ToArray(); Array.Sort(objects, DrawCall.DrawCompare); //Write group entry entry[entryCount++]._dataOffset = (int)(pData - pGroup); for (int i = 0; i < objects.Length; i++) { drawCall = objects[i]; *pData = 4; //Tag *(bushort *)(pData + 1) = (ushort)drawCall.MaterialNode._entryIndex; *(bushort *)(pData + 3) = (ushort)drawCall._parentObject._entryIndex; *(bushort *)(pData + 5) = (ushort)(drawCall.VisibilityBoneNode != null ? drawCall.VisibilityBoneNode.BoneIndex : 0); pData[7] = drawCall.DrawPriority; pData += 8; //Advance } *pData++ = 1; //Terminate } //Align data dataLen = (int)(pData - floor); while ((dataLen++ & 3) != 0) { *pData++ = 0; } //Set header *group = new ResourceGroup(entryCount); //Advance group poiner pGroup += group->_totalSize; }