public override void OnRebuild(VoidPtr address, int length, bool force) { MDL0Object* header = (MDL0Object*)address; MDL0Node model = Model; if (_uvSet[7] != null) _defSize = 224; else if (_uvSet[5] != null) _defSize = 192; else if (_uvSet[2] != null) _defSize = 160; else _defSize = 128; if (model._rebuildAllObj || model._isImport || _rebuild || _reOptimized) { //Set Header header->_totalLength = length; header->_numVertices = _numFacepoints; header->_numFaces = _numFaces; _primBufferSize = header->_primitives._bufferSize = _primitiveSize; _primSize = header->_primitives._size = _primitiveSize; _primOffset = header->_primitives._offset = _tableLen + 0xBC; _defOffset = _tableLen - 0x18; header->_defintions._bufferSize = _defBufferSize; header->_defintions._size = _defSize; header->_defintions._offset = _defOffset; header->_flag = _flag; header->_index = _entryIndex; if (model._version < 10) header->_nodeTableOffset = 0x64; else { *(bshort*)((byte*)header + 0x60) = _elementIndices[12]; *(bshort*)((byte*)header + 0x62) = _elementIndices[13]; //Table offset *(byte*)((byte*)header + 0x67) = 0x68; } //Set the node id if (_matrixNode != null) header->_nodeId = _nodeId = (ushort)_matrixNode.NodeIndex; else header->_nodeId = _nodeId = -1; //Set asset ids header->_vertexId = model._isImport && model._linker._forceDirectAssets[0] ? (short)-1 : (short)(_elementIndices[0] >= 0 ? _elementIndices[0] : -1); header->_normalId = model._isImport && model._linker._forceDirectAssets[1] ? (short)-1 : (short)(_elementIndices[1] >= 0 ? _elementIndices[1] : -1); for (int i = 2; i < 4; i++) *(bshort*)&header->_colorIds[i - 2] = model._isImport && model._linker._forceDirectAssets[i] ? (short)-1 : (short)(_elementIndices[i] >= 0 ? _elementIndices[i] : -1); for (int i = 4; i < 12; i++) *(bshort*)&header->_uids[i - 4] = model._isImport && model._linker._forceDirectAssets[i] ? (short)-1 : (short)(_elementIndices[i] >= 0 ? _elementIndices[i] : -1); //Write def list MDL0PolygonDefs* Defs = (MDL0PolygonDefs*)header->DefList; *Defs = MDL0PolygonDefs.Default; //Array flags are already set header->_arrayFlags = _arrayFlags; //Set vertex flags using descriptor list (sets the flags to this object) _manager.WriteVertexDescriptor(_descList, this); //Set UVAT groups using format list (writes directly to header) _manager.WriteVertexFormat(_fmtList, header); //Write newly set flags header->_vertexFormat._lo = Defs->VtxFmtLo = _vertexFormat._lo; header->_vertexFormat._hi = Defs->VtxFmtHi = _vertexFormat._hi; header->_vertexSpecs = Defs->VtxSpecs = _vertexSpecs; //Display UVAT groups that were written UVATGroups = new CPElementSpec( (uint)Defs->UVATA, (uint)Defs->UVATB, (uint)Defs->UVATC); //Write weight table only if the object is weighted if (_matrixNode == null) WriteWeightTable(header->WeightIndices(Model._version)); //Write primitives _manager.WritePrimitives(this, header); } else { //Move raw data over base.OnRebuild(address, length, force); CorrectNodeIds(header); header->_vertexId = _elementIndices[0]; header->_normalId = _elementIndices[1]; for (int i = 2; i < 4; i++) *(bshort*)&header->_colorIds[i - 2] = (short)(_elementIndices[i] >= 0 ? _elementIndices[i] : -1); for (int i = 4; i < 12; i++) *(bshort*)&header->_uids[i - 4] = (short)(_elementIndices[i] >= 0 ? _elementIndices[i] : -1); if (model._version >= 10) { *(bshort*)((byte*)header + 0x60) = _elementIndices[12]; *(bshort*)((byte*)header + 0x62) = _elementIndices[13]; } header->_defintions._size = _defSize; } _rebuild = _reOptimized = false; }
public ElementDescriptor(MDL0Object* polygon) { byte* pData = (byte*)polygon->DefList; byte* pCom; ElementDef* pDef; CPElementSpec UVATGroups; int format; //0 for direct, 1 for byte, 2 for short //Create remap table for vertex weights RemapTable = new int[polygon->_numVertices]; RemapSize = 0; Stride = 0; HasData = new bool[12]; Nodes = new ushort[16]; Commands = new byte[31]; Defs = new int[12]; _points = new List<List<Facepoint>>(); //Read element descriptor from polygon display list MDL0PolygonDefs* Definitons = (MDL0PolygonDefs*)polygon->DefList; int fmtLo = (int)Definitons->VtxFmtLo; int fmtHi = (int)Definitons->VtxFmtHi; UVATGroups = new CPElementSpec( (uint)Definitons->UVATA, (uint)Definitons->UVATB, (uint)Definitons->UVATC); //Build extract script. //What we're doing is assigning extract commands for elements in the polygon, in true order. //This allows us to process the polygon blindly, assuming that the definition is accurate. //Theoretically, this should offer a significant speed bonus. fixed (int* pDefData = Defs) fixed (byte* pComData = Commands) { pCom = pComData; pDef = (ElementDef*)pDefData; //Pos/Norm weight if (Weighted = (fmtLo & 1) != 0) { //Set the first command as the weight *pCom++ = (byte)DecodeOp.PosWeight; Stride++; //Increment stride by a byte (the length of the facepoints) } //Tex matrix for (int i = 0; i < 8; i++) if (((fmtLo >> (i + 1)) & 1) != 0) { //Set the command for each texture matrix *pCom++ = (byte)(DecodeOp.TexMtx0 + i); Stride++; //Increment stride by a byte (the length of the facepoints) } //Positions format = ((fmtLo >> 9) & 3) - 1; if (format >= 0) { HasData[0] = true; //Set the definitions input pDef->Format = (byte)format; //Set the type to Positions pDef->Type = 0; if (format == 0) { int f = (int)UVATGroups.PositionDef.DataFormat; //Clamp format to even value and add length to stride Stride += f.RoundDownToEven().Clamp(1, 4) * (!UVATGroups.PositionDef.IsSpecial ? 2 : 3); pDef->Scale = (byte)UVATGroups.PositionDef.Scale; pDef->Output = (byte)((!UVATGroups.PositionDef.IsSpecial ? (int)ElementCodec.CodecType.XY : (int)ElementCodec.CodecType.XYZ) + (byte)UVATGroups.PositionDef.DataFormat); *pCom++ = (byte)DecodeOp.ElementDirect; } else { Stride += format; //Add to stride (the length of the facepoints) pDef->Output = 12; //Set the output *pCom++ = (byte)DecodeOp.ElementIndexed; } pDef++; } //Normals format = ((fmtLo >> 11) & 3) - 1; if (format >= 0) { HasData[1] = true; //Set the definitions input pDef->Format = (byte)format; //Set the type to Normals pDef->Type = 1; if (format == 0) { int f = (int)UVATGroups.NormalDef.DataFormat; Stride += f.RoundDownToEven().Clamp(1, 4) * 3; pDef->Scale = (byte)UVATGroups.NormalDef.Scale; pDef->Output = (byte)(((int)ElementCodec.CodecType.XYZ) + (byte)UVATGroups.NormalDef.DataFormat); *pCom++ = (byte)DecodeOp.ElementDirect; } else { Stride += format; //Add to stride (the length of the facepoints) pDef->Output = 12; //Set the output *pCom++ = (byte)DecodeOp.ElementIndexed; } pDef++; } //Colors for (int i = 0; i < 2; i++) { format = ((fmtLo >> (i * 2 + 13)) & 3) - 1; if (format >= 0) { HasData[i + 2] = true; //Set the definitions input pDef->Format = (byte)format; //Set the type to Colors pDef->Type = (byte)(i + 2); if (format == 0) { //pDef->Output = pDef->Scale = 0; *pCom++ = (byte)DecodeOp.ElementDirect; } else { Stride += format; //Add to stride (the length of the facepoints) pDef->Output = 4; //Set the output *pCom++ = (byte)DecodeOp.ElementIndexed; } pDef++; } } //UVs for (int i = 0; i < 8; i++) { format = ((fmtHi >> (i * 2)) & 3) - 1; if (format >= 0) { HasData[i + 4] = true; //Set the definitions input pDef->Format = (byte)format; //Set the type to UVs pDef->Type = (byte)(i + 4); if (format == 0) { int f = (int)UVATGroups.GetUVDef(i).DataFormat; Stride += f.RoundDownToEven().Clamp(1, 4); pDef->Output = (byte)((!UVATGroups.GetUVDef(i).IsSpecial ? (int)ElementCodec.CodecType.S : (int)ElementCodec.CodecType.ST) + (byte)UVATGroups.GetUVDef(i).DataFormat); pDef->Scale = (byte)UVATGroups.GetUVDef(i).Scale; *pCom++ = (byte)DecodeOp.ElementDirect; } else { Stride += format; //Add to stride (the length of the facepoints) pDef->Output = 8; //Set the output *pCom++ = (byte)DecodeOp.ElementIndexed; } pDef++; } } *pCom = 0; } }
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; }