/// <summary> /// Loads a PC monster model from Pokémon. /// </summary> /// <param name="data">The data</param> /// <returns>The Model group with the monster meshes</returns> public static RenderBase.OModelGroup load(Stream data) { RenderBase.OModelGroup models = new RenderBase.OModelGroup(); OContainer container = PkmnContainer.load(data); models = BCH.load(new MemoryStream(container.content[0].data)); return(models); }
/// <summary> /// Loads a GR map model from Pokémon. /// </summary> /// <param name="data">The data</param> /// <returns>The Model group with the map meshes</returns> public static RenderBase.OModelGroup load(Stream data) { RenderBase.OModelGroup models; OContainer container = PkmnContainer.load(data); models = BCH.load(new MemoryStream(container.ElementAt(1).data)); return(models); }
/// <summary> /// Loads a BS animation file from Pokémon. /// </summary> /// <param name="data">The data</param> /// <returns>The Model group with the animations</returns> public static RenderBase.OModelGroup load(Stream data) { List <RenderBase.OModelGroup> models = new List <RenderBase.OModelGroup>(); OContainer naCont = PkmnContainer.load(data); //Get NA containers from BS for (int i = 1; i < naCont.content.Count; i++) { //Skip first entry because its not a NA (TODO: figure out this data) OContainer bchCont = PkmnContainer.load(new MemoryStream(naCont.content[1].data)); //Get BCH from NA containers models.Add(BCH.load(new System.IO.MemoryStream(bchCont.content[0].data))); } return(models[0]); //TODO: Figure out how to load all anim BCHs }
/// <summary> /// Loads a BS animation file from Pokémon. /// </summary> /// <param name="data">The data</param> /// <returns>The Model group with the animations</returns> public static RenderBase.OModelGroup load(Stream data) { List <RenderBase.OModelGroup> models = new List <RenderBase.OModelGroup>(); OContainer naCont = PkmnContainer.load(data); //Get NA containers from BS var naList = naCont.GetList(); foreach (var entry in naCont.Skip(1)) { OContainer bchCont = PkmnContainer.load(new MemoryStream(entry.data)); //Get BCH from NA containers models.Add(BCH.load(new MemoryStream(bchCont.First().data))); } return(models[0]); //TODO: Figure out how to load all anim BCHs }
public static RenderBase.OModelGroup load(Stream data) { RenderBase.OModelGroup group = new RenderBase.OModelGroup(); RenderBase.OModelGroup tempGroup; byte[] buffer; BinaryReader input = new BinaryReader(data); data.Seek(8, SeekOrigin.Begin); uint begin; uint end; uint length; bool eof = false; begin = 0; end = 0; for (int i = 0; eof == false; i++) { try { data.Seek(12 + i * 8, SeekOrigin.Begin); } catch { eof = true; } try { begin = input.ReadUInt32(); end = input.ReadUInt32(); if (begin < data.Length && end < data.Length) { //PK files seem to vary in their order of variables. if (end > begin) { length = end - begin; } else { length = begin - end; } if (length > 0) { if (end > begin) { data.Seek(begin, SeekOrigin.Begin); } else { data.Seek(end, SeekOrigin.Begin); } buffer = new byte[length]; input.Read(buffer, 0, (int)length); if (buffer[0] == 0x42 && buffer[1] == 0x43 && buffer[2] == 0x48) { tempGroup = BCH.load(new MemoryStream(buffer)); for (int j = 0; j < tempGroup.skeletalAnimation.list.Count; j++) { group.skeletalAnimation.list.Add(tempGroup.skeletalAnimation.list[j]); } for (int j = 0; j < tempGroup.materialAnimation.list.Count; j++) { group.materialAnimation.list.Add(tempGroup.materialAnimation.list[j]); } for (int j = 0; j < tempGroup.visibilityAnimation.list.Count; j++) { group.visibilityAnimation.list.Add(tempGroup.visibilityAnimation.list[j]); } } } } } catch { eof = true; } } data.Close(); if (group.skeletalAnimation.list.Count > 0) { MessageBox.Show("This animation file contains skeletal animations."); } return(group); }
public static file load(Stream data) { //Too small if (data.Length < 0x10) { data.Close(); return(new file { type = formatType.unsupported }); } BinaryReader input = new BinaryReader(data); uint magic, length; switch (peek(input)) { case 0x00010000: return(new file { data = GfModel.load(data), type = formatType.model }); case 0x00060000: return(new file { data = GfMotion.loadAnim(input), type = formatType.anims }); case 0x15041213: return(new file { data = GfTexture.load(data), type = formatType.image }); case 0x15122117: RenderBase.OModelGroup mdls = new RenderBase.OModelGroup(); mdls.model.Add(GfModel.loadModel(data)); return(new file { data = mdls, type = formatType.model }); } switch (getMagic(input, 5)) { case "MODEL": return(new file { data = DQVIIPack.load(data), type = formatType.container }); } switch (getMagic(input, 4)) { case "CGFX": return(new file { data = CGFX.load(data), type = formatType.model }); case "CRAG": return(new file { data = GARC.load(data), type = formatType.container }); case "darc": return(new file { data = DARC.load(data), type = formatType.container }); case "FPT0": return(new file { data = FPT0.load(data), type = formatType.container }); case "IECP": magic = input.ReadUInt32(); length = input.ReadUInt32(); return(load(new MemoryStream(LZSS.decompress(data, length)))); case "NLK2": data.Seek(0x80, SeekOrigin.Begin); return(new file { data = CGFX.load(data), type = formatType.model }); case "SARC": return(new file { data = SARC.load(data), type = formatType.container }); case "SMES": return(new file { data = NLP.loadMesh(data), type = formatType.model }); case "Yaz0": magic = input.ReadUInt32(); length = IOUtils.endianSwap(input.ReadUInt32()); data.Seek(8, SeekOrigin.Current); return(load(new MemoryStream(Yaz0.decompress(data, length)))); case "zmdl": return(new file { data = ZMDL.load(data), type = formatType.model }); case "ztex": return(new file { data = ZTEX.load(data), type = formatType.texture }); } //Check if is a BCLIM or BFLIM file (header on the end) if (data.Length > 0x28) { data.Seek(-0x28, SeekOrigin.End); string clim = IOUtils.readStringWithLength(input, 4); if (clim == "CLIM" || clim == "FLIM") { return new file { data = BCLIM.load(data), type = formatType.image } } ; } switch (getMagic(input, 3)) { case "BCH": byte[] buffer = new byte[data.Length]; input.Read(buffer, 0, buffer.Length); data.Close(); return(new file { data = BCH.load(new MemoryStream(buffer)), type = formatType.model }); case "DMP": return(new file { data = DMP.load(data), type = formatType.image }); } string magic2b = getMagic(input, 2); switch (magic2b) { case "AD": return(new file { data = AD.load(data), type = formatType.model }); case "BM": return(new file { data = MM.load(data), type = formatType.model }); case "BS": return(new file { data = BS.load(data), type = formatType.anims }); case "CM": return(new file { data = CM.load(data), type = formatType.model }); case "CP": return(new file { data = CP.load(data), type = formatType.model }); case "GR": return(new file { data = GR.load(data), type = formatType.model }); case "MM": return(new file { data = MM.load(data), type = formatType.model }); case "PC": return(new file { data = PC.load(data), type = formatType.model }); case "PT": return(new file { data = PT.load(data), type = formatType.texture }); } if (magic2b.Length == 2) { if ((magic2b[0] >= 'A' && magic2b[0] <= 'Z') && (magic2b[1] >= 'A' && magic2b[1] <= 'Z')) { return(new file { data = PkmnContainer.load(data), type = formatType.container }); } } //Compressions data.Seek(0, SeekOrigin.Begin); uint cmp = input.ReadUInt32(); if ((cmp & 0xff) == 0x13) { cmp = input.ReadUInt32(); } switch (cmp & 0xff) { case 0x11: return(load(new MemoryStream(LZSS_Ninty.decompress(data, cmp >> 8)))); case 0x90: byte[] buffer = BLZ.decompress(data); byte[] newData = new byte[buffer.Length - 1]; Buffer.BlockCopy(buffer, 1, newData, 0, newData.Length); return(load(new MemoryStream(newData))); } data.Close(); return(new file { type = formatType.unsupported }); }
public static RenderBase.OModelGroup load(string fileName) { FileStream data = new FileStream(fileName, FileMode.Open); BinaryReader input = new BinaryReader(data); RenderBase.OModelGroup models; RenderBase.OModel model; string extension = Path.GetExtension(fileName).ToLower(); string bchFile = fileName.Replace(extension, ".bch"); bool isBCHLoaded = false; if (File.Exists(bchFile)) { models = BCH.load(bchFile); model = models.model[0]; models.model.Clear(); isBCHLoaded = true; } else { models = new RenderBase.OModelGroup(); model = new RenderBase.OModel(); model.name = "model"; model.material.Add(new RenderBase.OMaterial()); } ushort format = input.ReadUInt16(); bool isDataWithinHeader = format == 4; input.ReadUInt16(); //-1? uint contentFlags = input.ReadUInt32(); bool hasNameTable = (contentFlags & 2) > 0; uint mode = input.ReadUInt32(); uint meshCount = input.ReadUInt32(); List <vtxEntry> vtxDescriptors = new List <vtxEntry>(); List <idxEntry> idxDescriptors = new List <idxEntry>(); for (int i = 0; i < meshCount; i++) { if (mode == 1 && i == 0) { vtxDescriptors.Add(getVtxDescriptor(input)); } uint facesCount = input.ReadUInt32(); for (int j = 0; j < facesCount; j++) { idxEntry face = new idxEntry(); face.meshIndex = i; uint nodesCount = input.ReadUInt32(); for (int k = 0; k < nodesCount; k++) { face.nodeList.Add(input.ReadUInt32()); } face.primitiveCount = input.ReadUInt32(); if (hasNameTable) { face.nameId = input.ReadUInt32(); } if (isDataWithinHeader) { face.buffer = new ushort[face.primitiveCount]; for (int k = 0; k < face.primitiveCount; k++) { face.buffer[k] = input.ReadUInt16(); } alignWord(input); } idxDescriptors.Add(face); } if (mode == 0) { if (isDataWithinHeader) { vtxEntry desc = getVtxDescriptor(input); desc.buffer = new byte[desc.length]; input.Read(desc.buffer, 0, desc.buffer.Length); vtxDescriptors.Add(desc); alignWord(input); } else { vtxDescriptors.Add(getVtxDescriptor(input)); } } } List <string> objNameTable = new List <string>(); if (hasNameTable) { for (int i = 0; i < meshCount; i++) { byte index = input.ReadByte(); objNameTable.Add(IOUtils.readString(input, (uint)data.Position, true)); } } if (!isDataWithinHeader) { align(input); } byte[] vtxBuffer = null; vtxEntry currVertex = null; int faceIndex = 0; for (int i = 0; i < meshCount; i++) { if (mode == 0 || i == 0) { currVertex = vtxDescriptors[i]; if (!isDataWithinHeader) { vtxBuffer = new byte[vtxDescriptors[i].length]; input.Read(vtxBuffer, 0, vtxBuffer.Length); align(input); } else { vtxBuffer = currVertex.buffer; } } RenderBase.OMesh obj; if (isBCHLoaded) { obj = model.mesh[0]; model.mesh.RemoveAt(0); } else { obj = new RenderBase.OMesh(); obj.name = "mesh_" + i.ToString(); } for (int j = 0; j < currVertex.attributes.Count; j++) { switch (currVertex.attributes[j].type) { case vtxAttributeType.normal: obj.hasNormal = true; break; case vtxAttributeType.color: obj.hasColor = true; break; case vtxAttributeType.textureCoordinate0: obj.texUVCount = 1; break; case vtxAttributeType.textureCoordinate1: obj.texUVCount = 2; break; case vtxAttributeType.boneIndex: obj.hasNode = true; break; case vtxAttributeType.boneWeight: obj.hasWeight = true; break; } } for (;;) { int indexBufferPos = 0; for (int j = 0; j < idxDescriptors[faceIndex].primitiveCount; j++) { ushort index; if (isDataWithinHeader) { index = idxDescriptors[faceIndex].buffer[indexBufferPos++]; } else { index = input.ReadUInt16(); } RenderBase.OVertex vertex = new RenderBase.OVertex(); vertex.diffuseColor = 0xffffffff; for (int k = 0; k < currVertex.attributes.Count; k++) { vtxAttribute att = currVertex.attributes[k]; int pos = (int)(index * currVertex.stride + att.offset); float scale = att.scale; switch (currVertex.attributes[k].type) { case vtxAttributeType.position: vertex.position = getVector3(vtxBuffer, pos, att.format, scale); break; case vtxAttributeType.normal: vertex.normal = getVector3(vtxBuffer, pos, att.format, scale); break; case vtxAttributeType.color: RenderBase.OVector4 c = getVector4(vtxBuffer, pos, att.format, scale); uint r = MeshUtils.saturate(c.x * 0xff); uint g = MeshUtils.saturate(c.y * 0xff); uint b = MeshUtils.saturate(c.z * 0xff); uint a = MeshUtils.saturate(c.w * 0xff); vertex.diffuseColor = b | (g << 8) | (r << 16) | (a << 24); break; case vtxAttributeType.textureCoordinate0: vertex.texture0 = getVector2(vtxBuffer, pos, att.format, scale); break; case vtxAttributeType.textureCoordinate1: vertex.texture1 = getVector2(vtxBuffer, pos, att.format, scale); break; case vtxAttributeType.boneIndex: byte n0 = vtxBuffer[pos]; byte n1 = vtxBuffer[pos + 1]; vertex.node.Add((int)idxDescriptors[faceIndex].nodeList[n0]); vertex.node.Add((int)idxDescriptors[faceIndex].nodeList[n1]); break; case vtxAttributeType.boneWeight: RenderBase.OVector2 w = getVector2(vtxBuffer, pos, att.format, scale); vertex.weight.Add(w.x); vertex.weight.Add(w.y); break; } } MeshUtils.calculateBounds(model, vertex); obj.vertices.Add(vertex); } faceIndex++; if (!isDataWithinHeader) { align(input); } if (faceIndex >= idxDescriptors.Count) { break; } if (idxDescriptors[faceIndex].meshIndex == i) { continue; } break; } model.mesh.Add(obj); } models.model.Add(model); data.Close(); return(models); }