//This only modifies vertices after ApplyCHR0 has weighted them. //It cannot be used without calling ApplyCHR0 first. public void ApplySHP(SHP0Node node, int index) { _currentSHP = node; _currentSHPIndex = index; if (node == null || index == 0) return; SHP0EntryNode n; if (_objList != null) foreach (MDL0ObjectNode poly in _objList) if ((n = node.FindChild(poly.VertexNode, true) as SHP0EntryNode) != null) { //Max amount of morphs allowed is 32 float[] weights = new float[n.Children.Count]; MDL0VertexNode[] nodes = new MDL0VertexNode[n.Children.Count]; foreach (SHP0VertexSetNode v in n.Children) { MDL0VertexNode vNode = null; foreach (MDL0VertexNode vn in _vertList) if (vn.Name == v.Name) { vNode = vn; break; } weights[v.Index] = vNode != null ? v.Keyframes.GetFrameValue(index - 1, SHP0VertexSetNode._linear) : 0; nodes[v.Index] = vNode; } float totalWeight = 0; foreach (float f in weights) totalWeight += f; float baseWeight = 1.0f - totalWeight; //Calculate barycenter per vertex and set as weighted pos for (int i = 0; i < poly._manager._vertices.Count; i++) { int x = 0; Vertex3 v3 = poly._manager._vertices[i]; v3._weightedPosition *= baseWeight; foreach (MDL0VertexNode vNode in nodes) if (vNode != null) v3._weightedPosition += (v3.GetMatrix() * vNode.Vertices[v3._facepoints[0]._vertexIndex]) * weights[x++]; v3._weightedPosition /= (totalWeight + baseWeight); v3.weights = weights; v3.nodes = nodes; v3.baseWeight = baseWeight; v3.bCenter = v3._weightedPosition; } } }
//Write assets will only be used for model imports. private static void WriteAssets(Collada form, ModelLinker linker, ref byte* pData) { int index; MDL0Node model = linker.Model; if (linker._vertices != null && linker._vertices.Count != 0) { model.LinkGroup(new MDL0GroupNode(MDLResourceType.Vertices)); model._vertGroup._parent = model; index = 0; foreach (VertexCodec c in linker._vertices) { MDL0VertexNode node = new MDL0VertexNode(); node._name = model.Name + "_" + model._objList[index]._name; if (((MDL0ObjectNode)model._objList[index])._opaMaterial != null) node._name += "_" + ((MDL0ObjectNode)model._objList[index])._opaMaterial._name; if (form != null) form.Say("Writing Vertices - " + node.Name); MDL0VertexData* header = (MDL0VertexData*)pData; header->_dataLen = c._dataLen.Align(0x20) + 0x40; header->_dataOffset = 0x40; header->_index = index++; header->_isXYZ = c._hasZ ? 1 : 0; header->_type = (int)c._type; header->_divisor = (byte)c._scale; header->_entryStride = (byte)c._dstStride; header->_numVertices = (short)c._dstCount; header->_eMin = c._min; header->_eMax = c._max; header->_pad1 = header->_pad2 = 0; c.Write(pData + 0x40); node._replSrc = node._replUncompSrc = new DataSource(header, header->_dataLen); model._vertGroup.AddChild(node, false); pData += header->_dataLen; } } if (linker._normals != null && linker._normals.Count != 0) { model.LinkGroup(new MDL0GroupNode(MDLResourceType.Normals)); model._normGroup._parent = model; index = 0; foreach (VertexCodec c in linker._normals) { MDL0NormalNode node = new MDL0NormalNode(); node._name = model.Name + "_" + model._objList[index]._name; if (((MDL0ObjectNode)model._objList[index])._opaMaterial != null) node._name += "_" + ((MDL0ObjectNode)model._objList[index])._opaMaterial._name; if (form != null) form.Say("Writing Normals - " + node.Name); MDL0NormalData* header = (MDL0NormalData*)pData; header->_dataLen = c._dataLen.Align(0x20) + 0x20; header->_dataOffset = 0x20; header->_index = index++; header->_isNBT = 0; header->_type = (int)c._type; header->_divisor = (byte)c._scale; header->_entryStride = (byte)c._dstStride; header->_numVertices = (ushort)c._dstCount; c.Write(pData + 0x20); node._replSrc = node._replUncompSrc = new DataSource(header, header->_dataLen); model._normGroup.AddChild(node, false); pData += header->_dataLen; } } if (linker._colors != null && linker._colors.Count != 0) { model.LinkGroup(new MDL0GroupNode(MDLResourceType.Colors)); model._colorGroup._parent = model; index = 0; foreach (ColorCodec c in linker._colors) { MDL0ColorNode node = new MDL0ColorNode(); node._name = model.Name + "_" + model._objList[index]._name; if (((MDL0ObjectNode)model._objList[index])._opaMaterial != null) node._name += "_" + ((MDL0ObjectNode)model._objList[index])._opaMaterial._name; if (form != null) form.Say("Writing Colors - " + node.Name); MDL0ColorData* header = (MDL0ColorData*)pData; header->_dataLen = c._dataLen.Align(0x20) + 0x20; header->_dataOffset = 0x20; header->_index = index++; header->_isRGBA = c._hasAlpha ? 1 : 0; header->_format = (int)c._outType; header->_entryStride = (byte)c._dstStride; header->_pad = 0; header->_numEntries = (ushort)c._dstCount; c.Write(pData + 0x20); node._replSrc = node._replUncompSrc = new DataSource(header, header->_dataLen); model._colorGroup.AddChild(node, false); pData += header->_dataLen; } } if (linker._uvs != null && linker._uvs.Count != 0) { model.LinkGroup(new MDL0GroupNode(MDLResourceType.UVs)); model._uvGroup._parent = model; index = 0; foreach (VertexCodec c in linker._uvs) { MDL0UVNode node = new MDL0UVNode() { _name = "#" + index }; if (form != null) form.Say("Writing UVs - " + node.Name); MDL0UVData* header = (MDL0UVData*)pData; header->_dataLen = c._dataLen.Align(0x20) + 0x40; header->_dataOffset = 0x40; header->_index = index++; header->_format = (int)c._type; header->_divisor = (byte)c._scale; header->_isST = 1; header->_entryStride = (byte)c._dstStride; header->_numEntries = (ushort)c._dstCount; header->_min = (Vector2)c._min; header->_max = (Vector2)c._max; header->_pad1 = header->_pad2 = header->_pad3 = header->_pad4 = 0; c.Write(pData + 0x40); node._replSrc = node._replUncompSrc = new DataSource(header, header->_dataLen); model._uvGroup.AddChild(node, false); pData += header->_dataLen; } } //Clean groups if (model._vertList != null && model._vertList.Count > 0) { model._children.Add(model._vertGroup); linker.Groups[(int)(MDLResourceType)Enum.Parse(typeof(MDLResourceType), model._vertGroup.Name)] = model._vertGroup; } else model.UnlinkGroup(model._vertGroup); if (model._normList != null && model._normList.Count > 0) { model._children.Add(model._normGroup); linker.Groups[(int)(MDLResourceType)Enum.Parse(typeof(MDLResourceType), model._normGroup.Name)] = model._normGroup; } else model.UnlinkGroup(model._normGroup); if (model._uvList != null && model._uvList.Count > 0) { model._children.Add(model._uvGroup); linker.Groups[(int)(MDLResourceType)Enum.Parse(typeof(MDLResourceType), model._uvGroup.Name)] = model._uvGroup; } else model.UnlinkGroup(model._uvGroup); if (model._colorList != null && model._colorList.Count > 0) { model._children.Add(model._colorGroup); linker.Groups[(int)(MDLResourceType)Enum.Parse(typeof(MDLResourceType), model._colorGroup.Name)] = model._colorGroup; } else model.UnlinkGroup(model._colorGroup); //Link sets if (model._objList != null) foreach (MDL0ObjectNode poly in model._objList) { if (poly._elementIndices[0] != -1 && model._vertList != null && model._vertList.Count > poly._elementIndices[0]) poly._vertexNode = (MDL0VertexNode)model._vertGroup._children[poly._elementIndices[0]]; if (poly._elementIndices[1] != -1 && model._normList != null && model._normList.Count > poly._elementIndices[1]) poly._normalNode = (MDL0NormalNode)model._normGroup._children[poly._elementIndices[1]]; for (int i = 2; i < 4; i++) if (poly._elementIndices[i] != -1 && model._colorList != null && model._colorList.Count > poly._elementIndices[i]) poly._colorSet[i - 2] = (MDL0ColorNode)model._colorGroup._children[poly._elementIndices[i]]; for (int i = 4; i < 12; i++) if (poly._elementIndices[i] != -1 && model._uvList != null && model._uvList.Count > poly._elementIndices[i]) poly._uvSet[i - 4] = (MDL0UVNode)model._uvGroup._children[poly._elementIndices[i]]; } }
public void SetPosition(MDL0VertexNode node, Vector3 pos) { node.Vertices[_facepoints[0]._vertexIndex] = pos; node.ForceRebuild = true; if (node.Format == WiiVertexComponentType.Float) node.ForceFloat = true; }
//public void AutoMetal() //{ // ((MDL0Node)_resource).AutoMetalMaterials = true; //} public MDL0VertexNode NewVertex() { if (_modelViewerOpen) return null; MDL0Node model = ((MDL0Node)_resource); MDL0GroupNode g = model._vertGroup; if (g == null) { model.AddChild(g = new MDL0GroupNode(MDLResourceType.Vertices), true); model._vertGroup = g; model._vertList = g.Children; } MDL0VertexNode node = new MDL0VertexNode() { Name = "VertexSet" + ((MDL0Node)_resource)._vertList.Count }; node.Vertices = new Vector3[] { new Vector3(0) }; g.AddChild(node, true); node._forceRebuild = true; node.Rebuild(true); node.SignalPropertyChange(); FindResource(node, true).EnsureVisible(); return node; }
private void listBox2_SelectedValueChanged(object sender, EventArgs e) { button2.Enabled = listBox2.SelectedItem != null; _selectedDest = listBox2.SelectedItem as MDL0VertexNode; _mainWindow.KeyframePanel.TargetSequence = VertexSetDest; _mainWindow.UpdatePropDisplay(); }
public override bool OnInitialize() { MDL0Object* header = Header; _nodeId = header->_nodeId; SetSizeInternal(_totalLength = header->_totalLength); _mdl0Offset = header->_mdl0Offset; _stringOffset = header->_stringOffset; ModelLinker linker = Model._linker; MatrixNode = (_nodeId >= 0 && _nodeId < Model._linker.NodeCache.Length) ? Model._linker.NodeCache[_nodeId] : null; _vertexFormat = header->_vertexFormat; _vertexSpecs = header->_vertexSpecs; _arrayFlags = header->_arrayFlags; HasPosMatrix = _arrayFlags.HasPosMatrix; for (int i = 0; i < 8; i++) HasTextureMatrix[i] = _arrayFlags.GetHasTexMatrix(i); _numFacepoints = header->_numVertices; _numFaces = header->_numFaces; _flag = header->_flag; _primBufferSize = header->_primitives._bufferSize; _primSize = header->_primitives._size; _primOffset = header->_primitives._offset; _defBufferSize = header->_defintions._bufferSize; _defSize = header->_defintions._size; _defOffset = header->_defintions._offset; _entryIndex = header->_index; //Conditional name assignment if ((_name == null) && (header->_stringOffset != 0)) if (!_replaced) _name = header->ResourceString; else _name = "polygon" + Index; //Link nodes if (header->_vertexId >= 0 && Model._vertList != null) foreach (MDL0VertexNode v in Model._vertList) if (header->_vertexId == v.ID) { (_vertexNode = v)._objects.Add(this); break; } if (header->_normalId >= 0 && Model._normList != null) foreach (MDL0NormalNode n in Model._normList) if (header->_normalId == n.ID) { (_normalNode = n)._objects.Add(this); break; } int id; for (int i = 0; i < 2; i++) if ((id = ((bshort*)header->_colorIds)[i]) >= 0 && Model._colorList != null) foreach (MDL0ColorNode c in Model._colorList) if (id == c.ID) { (_colorSet[i] = c)._objects.Add(this); break; } for (int i = 0; i < 8; i++) if ((id = ((bshort*)header->_uids)[i]) >= 0 && Model._uvList != null) foreach (MDL0UVNode u in Model._uvList) if (id == u.ID) { (_uvSet[i] = u)._objects.Add(this); break; } if (Model._version > 9) { if (header->_furVectorId >= 0) foreach (MDL0FurVecNode v in Model._furVecList) if (header->_furVectorId == v.ID) { (_furVecNode = v)._objects.Add(this); break; } if (header->_furLayerCoordId >= 0) foreach (MDL0FurPosNode n in Model._furPosList) if (header->_furLayerCoordId == n.ID) { (_furPosNode = n)._objects.Add(this); break; } } //Link element indices for rebuild _elementIndices[0] = (short)(_vertexNode != null ? _vertexNode.Index : -1); _elementIndices[1] = (short)(_normalNode != null ? _normalNode.Index : -1); for (int i = 2; i < 4; i++) _elementIndices[i] = (short)(_colorSet[i - 2] != null ? _colorSet[i - 2].Index : -1); for (int i = 4; i < 12; i++) _elementIndices[i] = (short)(_uvSet[i - 4] != null ? _uvSet[i - 4].Index : -1); _elementIndices[12] = (short)(_furVecNode != null ? _furVecNode.Index : -1); _elementIndices[13] = (short)(_furPosNode != null ? _furPosNode.Index : -1); //Create primitive manager if (_parent != null) { int i = 0; _manager = new PrimitiveManager(header, Model._assets, linker.NodeCache, this); if (_manager._vertices != null) foreach (Vertex3 v in _manager._vertices) { v._index = i++; v._object = this; } } //Get polygon UVAT groups MDL0PolygonDefs* Defs = (MDL0PolygonDefs*)header->DefList; UVATGroups = new CPElementSpec( (uint)Defs->UVATA, (uint)Defs->UVATB, (uint)Defs->UVATC); //Read internal object node cache and read influence list if (Model._linker.NodeCache != null) { if (_matrixNode == null) { _influences = new List<IMatrixNode>(); bushort* weights = header->WeightIndices(Model._version); int count = *(bint*)weights; weights += 2; for (int i = 0; i < count; i++) if (*weights < Model._linker.NodeCache.Length) _influences.Add(Model._linker.NodeCache[*weights++]); else weights++; } } //Check for errors if (header->_totalLength % 0x20 != 0) { Model._errors.Add("Object " + Index + " has an improper data length."); SignalPropertyChange(); _rebuild = true; } if ((int)(0x24 + header->_primitives._offset) % 0x20 != 0) { Model._errors.Add("Object " + Index + " has an improper primitives start offset."); SignalPropertyChange(); _rebuild = true; } if (CheckVertexFormat()) { Model._errors.Add("Object " + Index + " has a facepoint descriptor that does not match its linked nodes."); SignalPropertyChange(); _rebuild = true; for (int i = 0; i < 2; i++) if (_colorSet[i] != null && _manager._faceData[i + 2] == null) { _manager._faceData[i + 2] = new UnsafeBuffer(_manager._pointCount * 4); _colorChanged[i] = true; } } if (HasTexMtx && !Weighted) { Model._errors.Add("Object " + Index + " has texture matrices but is not weighted."); for (int i = 0; i < 8; i++) HasTextureMatrix[i] = false; SignalPropertyChange(); _rebuild = true; } //if (!Weighted) //{ // bool notFloat = HasANonFloatAsset; // foreach (PrimitiveGroup p in _primGroups) // { // bool o = false; // foreach (PrimitiveHeader ph in p._headers) // if (ph.Type != WiiPrimitiveType.TriangleList && notFloat) // { // Model._errors.Add("Object " + Index + " will explode in-game due to assets that are not written as float."); // SignalPropertyChange(); // if (_vertexNode.Format != WiiVertexComponentType.Float) // _vertexNode._forceRebuild = _vertexNode._forceFloat = true; // if (_normalNode != null && _normalNode.Format != WiiVertexComponentType.Float) // _normalNode._forceRebuild = _normalNode._forceFloat = true; // for (int i = 4; i < 12; i++) // if (_uvSet[i - 4] != null && _uvSet[i - 4].Format != WiiVertexComponentType.Float) // _uvSet[i - 4]._forceRebuild = _uvSet[i - 4]._forceFloat = true; // o = true; // break; // } // if (o) // break; // } //} return false; }