public void Initialize(IModel model, DecoderShell shell) { PrimitiveManager m; if (_weighted) { m = DecodePrimitivesWeighted(_bindMatrix, _g, _skin, _scene, model.Influences, BoneType); } else { m = DecodePrimitivesUnweighted(_bindMatrix, _g); } switch (ModelType) { case ImportType.MDL0: CreateMDL0Object(_inst, _node, _parent, m, (MDL0Node)model, shell); break; } }
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 } } } }
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); }
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); } } } } }
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 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); } } }
private void CreateObject(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); int i = 0; foreach (Vertex3 v in manager._vertices) v._index = i++; MDL0ObjectNode poly = new MDL0ObjectNode() { _manager = manager }; poly._manager._polygon = poly; poly._name = node._name != null ? node._name : node._id; //Attach single-bind if (parent != null && parent is MDL0BoneNode) poly.MatrixNode = (MDL0BoneNode)parent; //Attach material if (inst._material != null) foreach (MaterialEntry mat in shell._materials) if (mat._id == inst._material._target) { (poly._opaMaterial = (mat._node as MDL0MaterialNode))._objects.Add(poly); break; } model._numFaces += poly._numFaces = manager._faceCount = manager._pointCount / 3; model._numFacepoints += poly._numFacepoints = manager._pointCount; poly._parent = model._objGroup; model._objList.Add(poly); } }