public AssetStorage(ModelLinker linker) { int index; //Vertices if (linker.Vertices != null) { Assets[0] = new UnsafeBuffer[linker.Vertices->_numEntries]; index = 0; foreach (ResourcePair p in *linker.Vertices) { Assets[0][index++] = VertexCodec.Decode((MDL0VertexData *)p.Data); } } //Normals if (linker.Normals != null) { Assets[1] = new UnsafeBuffer[linker.Normals->_numEntries]; index = 0; foreach (ResourcePair p in *linker.Normals) { Assets[1][index++] = VertexCodec.Decode((MDL0NormalData *)p.Data); } } //Colors if (linker.Colors != null) { Assets[2] = new UnsafeBuffer[linker.Colors->_numEntries]; index = 0; foreach (ResourcePair p in *linker.Colors) { Assets[2][index++] = ColorCodec.Decode((MDL0ColorData *)p.Data); } } //UVs if (linker.UVs != null) { Assets[3] = new UnsafeBuffer[linker.UVs->_numEntries]; index = 0; foreach (ResourcePair p in *linker.UVs) { Assets[3][index++] = VertexCodec.Decode((MDL0UVData *)p.Data); } } }
public override void OnRebuild(VoidPtr address, int length, bool force) { if (Model._isImport || _forceRebuild) { MDL0FurPosData* header = (MDL0FurPosData*)address; header->_dataLen = length; header->_dataOffset = 0x40; header->_index = _entryIndex; header->_isXYZ = _enc._hasZ ? 1 : 0; header->_type = (int)_enc._type; header->_divisor = (byte)_enc._scale; header->_entryStride = (byte)_enc._dstStride; header->_numVertices = (short)_enc._srcCount; header->_numLayers = NumLayers; header->_offsetOfLayer = LayerOffset; //Write data _enc.Write(Vertices, (byte*)address + 0x40); _enc.Dispose(); _enc = null; _forceRebuild = false; } else base.OnRebuild(address, length, force); }
public override int OnCalculateSize(bool force) { if (Model._isImport || _forceRebuild) { _enc = new VertexCodec(Vertices, false, _forceFloat); return _enc._dataLen.Align(0x20) + 0x40; } else return base.OnCalculateSize(force); }
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)); }
public static int CalcSize(Collada form, ModelLinker linker) { MDL0Node model = linker.Model; 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) { mixLen += 6; } } foreach (MDL0BoneNode b in linker.BoneCache) { if (b._weightCount > 0) { mixLen += 5; } } //DrawOpa and DrawXlu //Get assigned materials and categorize if (model._matList != null) { for (int i = 0; i < model._matList.Count; i++) { //Entries are ordered by material, not by polygon. MDL0MaterialNode mat = model._matList[i] as MDL0MaterialNode; if (!mat.isMetal) { for (int l = 0; l < mat._polygons.Count; l++) { if (!mat.XLUMaterial) { 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._polyList; if (polyList == null) { break; } string str = ""; //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++) { MDL0PolygonNode p = polyList[i] as MDL0PolygonNode; for (int x = aInd; x < aLen; x++) { if (p._manager._faceData[x] != null) { if (model._importOptions._rmpClrs && model._importOptions._addClrs) { if (i > 0 && x == 2 && model._noColors == true) { p._elementIndices[x] = 0; continue; } else if (i >= 0 && x == 3 && model._noColors == true) { p._elementIndices[x] = -1; break; } } p._elementIndices[x] = (short)aList.Count; if (form != null) { form.Say("Encoding " + str + (x - aInd) + " for Object " + i + ": " + p.Name); } switch (aInd) { case 0: VertexCodec vert; aList.Add(vert = new VertexCodec(p._manager.RawVertices, false, model._importOptions._fltVerts)); assetLen += vert._dataLen.Align(0x20) + 0x40; break; case 1: aList.Add(vert = new VertexCodec(p._manager.RawNormals, false, model._importOptions._fltNrms)); assetLen += vert._dataLen.Align(0x20) + 0x20; break; case 2: ColorCodec col; aList.Add(col = new ColorCodec(p._manager.Colors(x - 2))); assetLen += col._dataLen.Align(0x20) + 0x20; break; default: aList.Add(vert = new VertexCodec(p._manager.UVs(x - 4), model._importOptions._fltUVs)); assetLen += vert._dataLen.Align(0x20) + 0x40; break; } } else { p._elementIndices[x] = -1; } } } 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 { 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._polyList != null) { entryList = model._polyList; } break; case MDLResourceType.Shaders: if ((entryList = model.GetUsedShaders()) != null && model._matList != null) { entries = model._matList.Count; } break; case MDLResourceType.Textures: if (model._texList != null) { foreach (MDL0TextureNode tex in model._texList) { texLen += (tex._references.Count * 8) + 4; } linker._texCount = entries = model._texList.Count; } break; case MDLResourceType.Palettes: if (model._pltList != null) { foreach (MDL0TextureNode pal in model._pltList) { texLen += (pal._references.Count * 8) + 4; } linker._palCount = entries = model._pltList.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); } e._entryIndex = index++; if (index == 1) { if ((temp = (e._mdlOffset = headerLen + tableLen + groupLen + texLen + defLen + boneLen).Align(0x10)) != e._mdlOffset) { e._dataAlign = temp - e._mdlOffset; } } else { e._mdlOffset = (prev = ((MDL0MaterialNode)model._matList[index - 1]))._mdlOffset + prev._calcSize; } dataLen += e.CalculateSize(true); } } 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) + (model._part2Entries.Count > 0 ? 0x1C + model._part2Entries.Count * 0x2C : 0)); }
public override void OnRebuild(VoidPtr address, int length, bool force) { if (Model._isImport || _forceRebuild) { MDL0UVData* header = (MDL0UVData*)address; header->_dataLen = length; header->_dataOffset = 0x40; header->_index = _entryIndex; header->_format = (int)_enc._type; header->_divisor = (byte)_enc._scale; header->_isST = 1; header->_entryStride = (byte)_enc._dstStride; header->_numEntries = (ushort)_enc._srcCount; header->_min = (Vector2)_enc._min; header->_min = (Vector2)_enc._max; header->_pad1 = header->_pad2 = header->_pad3 = header->_pad4 = 0; _enc.Write(Points, (byte*)address + 0x40); _enc.Dispose(); _enc = null; _forceRebuild = false; } else base.OnRebuild(address, length, force); }
public static int CalcSize(ModelLinker linker) { MDL0Node model = linker.Model; int headerLen, groupLen = 0x18, tableLen = 0, texLen = 0, dataLen = 0; int treeLen = 0, mixLen = 0, opaLen = 0, xluLen = 0; int texCount = 0, decCount = 0; int aInd, aLen, temp; //Get header length switch (linker.Version) { case 0x09: headerLen = 0x80; break; default: headerLen = 0; 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; //entries = 0; switch (resType) { case MDLResourceType.Defs: { //NodeTree treeLen = linker.BoneCache.Length * 5; //NodeMix foreach (IMatrixNode i in linker.NodeCache) { if (!i.IsPrimaryNode) { mixLen += ((Influence)i)._weights.Length * 8 + 4; } else if (i.ReferenceCount > 0) { mixLen += 5; } } //DrawOpa, DrawXlu //Get assigned materials and categorize foreach (MDL0PolygonNode poly in linker.Model.PolygonList) { if (poly._material == null) { continue; } //Is material transparent? if (poly._material.EnableBlend) { opaLen += 8; } else { xluLen += 8; } } //Add terminate byte and set model def flags if (linker.Model._hasTree = (treeLen > 0)) { treeLen++; entries++; } if (linker.Model._hasMix = (mixLen > 0)) { mixLen++; entries++; } if (linker.Model._hasOpa = (opaLen > 0)) { opaLen++; entries++; } if (linker.Model._hasXlu = (xluLen > 0)) { xluLen++; entries++; } //Align data dataLen += (treeLen + mixLen + opaLen + xluLen).Align(4); break; } case MDLResourceType.Vertices: aInd = 0; aLen = 1; EvalAssets: List <ResourceNode> polyList = linker.Model._polyList; if (polyList == null) { break; } //What about merging? //Create asset lists IList aList; switch (aInd) { case 0: aList = linker._vertices = new List <VertexCodec>(polyList.Count); break; case 1: aList = linker._normals = new List <VertexCodec>(polyList.Count); break; case 2: aList = linker._colors = new List <ColorCodec>(polyList.Count); break; default: aList = linker._uvs = new List <VertexCodec>(polyList.Count); break; } aLen += aInd; temp = polyList.Count; for (int i = 0; i < temp; i++) { MDL0PolygonNode p = polyList[i] as MDL0PolygonNode; //object c; for (int x = aInd; x < aLen; x++) { if (p._manager._faceData[x] != null) { p._elementIndices[x] = (short)aList.Count; switch (aInd) { case 0: VertexCodec vert; aList.Add(vert = new VertexCodec(p._manager.RawPoints, true)); dataLen += vert._dataLen.Align(0x20) + 0x40; break; case 1: aList.Add(vert = new VertexCodec((Vector3 *)p._manager._faceData[x].Address, p._manager._pointCount, false)); dataLen += vert._dataLen.Align(0x20) + 0x20; break; case 2: ColorCodec col; aList.Add(col = new ColorCodec((RGBAPixel *)p._manager._faceData[x].Address, p._manager._pointCount)); dataLen += col._dataLen.Align(0x20) + 0x20; break; default: aList.Add(vert = new VertexCodec((Vector2 *)p._manager._faceData[x].Address, p._manager._pointCount)); dataLen += vert._dataLen.Align(0x20) + 0x40; break; } } else { p._elementIndices[x] = -1; } } } entries = aList.Count; break; case MDLResourceType.Normals: aInd = 1; aLen = 1; goto EvalAssets; case MDLResourceType.Colors: aInd = 2; aLen = 2; goto EvalAssets; case MDLResourceType.UVs: aInd = 4; aLen = 8; goto EvalAssets; case MDLResourceType.Bones: entryList = linker.BoneCache; break; case MDLResourceType.Materials: entryList = linker.Model._matList; break; case MDLResourceType.Polygons: entryList = linker.Model._polyList; break; case MDLResourceType.Shaders: if ((entryList = linker.Model._shadList) != null) { entries = linker.Model._shadList.Count; } break; case MDLResourceType.Textures: TextureRef[] tex = linker.Model._textures.GetTextures(); entries = tex.Length; foreach (TextureRef t in tex) { texCount++; texLen += t._texRefs.Count * 8 + 4; } break; case MDLResourceType.Decals: TextureRef[] dec = linker.Model._textures.GetDecals(); entries = dec.Length; foreach (TextureRef t in dec) { decCount++; texLen += t._decRefs.Count * 8 + 4; } break; } if (entryList != null) { int index = 0; foreach (MDL0EntryNode e in entryList) { e._entryIndex = index++; dataLen += e.CalculateSize(true); } if (entries == 0) { entries = index; } } if (entries > 0) { groupLen += entries * 0x10 + 0x18; } } linker._headerLen = headerLen; linker._tableLen = tableLen; linker._groupLen = groupLen; linker._texLen = texLen; linker._texCount = texCount; linker._decCount = decCount; linker._dataLen = dataLen; return(headerLen + tableLen + groupLen + texLen + dataLen); }
public static int CalcSize(Collada form, ModelLinker linker) { MDL0Node model = linker.Model; model._needsNrmMtxArray = model._needsTexMtxArray = false; model._numFacepoints = model._numFaces = 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) if (w.Bone != null && w.Weight != 0 && w.Bone._nodeIndex < linker.NodeCache.Length && w.Bone._nodeIndex >= 0 && linker.NodeCache[w.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._numFaces += poly._numFaces; model._numFacepoints += poly._numFacepoints; if (poly.OpaMaterialNode != null) opaLen += 8; if (poly.XluMaterialNode != null) 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>(); 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(); 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; if (model._objList.Count > 0) { model._needsNrmMtxArray = true; foreach (MDL0ObjectNode n in model._objList) if (n.HasTexMtx) model._needsTexMtxArray = true; } } break; case MDLResourceType.Shaders: if ((entryList = model.GetUsedShaders()) != null && model._matList != null) entries = model._matList.Count; break; case MDLResourceType.Textures: if (model._texList != null) { foreach (MDL0TextureNode tex in model._texList) texLen += (tex._references.Count * 8) + 4; linker._texCount = entries = model._texList.Count; } break; case MDLResourceType.Palettes: if (model._pltList != null) { foreach (MDL0TextureNode pal in model._pltList) texLen += (pal._references.Count * 8) + 4; linker._palCount = entries = model._pltList.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); e._entryIndex = index++; if (index == 1) { if ((temp = (e._mdlOffset = headerLen + tableLen + groupLen + texLen + defLen + boneLen).Align(0x10)) != e._mdlOffset) e._dataAlign = temp - e._mdlOffset; } else e._mdlOffset = (prev = ((MDL0MaterialNode)model._matList[index - 1]))._mdlOffset + prev._calcSize; dataLen += e.CalculateSize(true); } } 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); }
public override void OnRebuild(VoidPtr address, int length, bool force) { if (Model._isImport || _forceRebuild) { MDL0NormalData* header = (MDL0NormalData*)address; header->_dataLen = length; header->_dataOffset = 0x20; header->_index = _entryIndex; header->_isNBT = 0; header->_type = (int)_enc._type; header->_divisor = (byte)_enc._scale; header->_entryStride = (byte)_enc._dstStride; header->_numVertices = (ushort)_enc._srcCount; _enc.Write(Normals, (byte*)header + 0x20); _enc.Dispose(); _enc = null; _forceRebuild = false; } else base.OnRebuild(address, length, force); }