private static void SerializeObject(BinaryWriter bw, Polymodel model, short version) { int size = 32; int padBytes = 0; if (version >= 8) { padBytes = 4 - (((int)bw.BaseStream.Position + size + 8) % 4); if (padBytes == 4) { padBytes = 0; } size += padBytes; } bw.Write(0x5244484F); bw.Write(size); bw.Write(model.NumSubmodels); bw.Write(model.Radius.value); bw.Write(model.Mins.X.value); bw.Write(model.Mins.Y.value); bw.Write(model.Mins.Z.value); bw.Write(model.Maxs.X.value); bw.Write(model.Maxs.Y.value); bw.Write(model.Maxs.Z.value); for (int i = 0; i < padBytes; i++) { bw.Write((byte)0); } }
private static void SerializeAnim(BinaryWriter bw, Polymodel model, short version) { int size = 2 + 6 * model.NumSubmodels * Robot.NumAnimationStates; int padBytes = 0; if (version >= 8) { padBytes = 4 - (((int)bw.BaseStream.Position + size + 8) % 4); if (padBytes == 4) { padBytes = 0; } size += padBytes; } bw.Write(0x4D494E41); bw.Write(size); bw.Write((short)Robot.NumAnimationStates); for (int i = 0; i < model.NumSubmodels; i++) { for (int f = 0; f < Robot.NumAnimationStates; f++) { bw.Write(model.AnimationMatrix[i, f].P); bw.Write(model.AnimationMatrix[i, f].B); bw.Write(model.AnimationMatrix[i, f].H); } } for (int i = 0; i < padBytes; i++) { bw.Write((byte)0); } }
private static void SerializeTextures(BinaryWriter bw, Polymodel model, short version) { int size = 2; int padBytes = 0; foreach (string texture in model.TextureList) { size += texture.Length + 1; } if (version >= 8) { padBytes = 4 - (((int)bw.BaseStream.Position + size + 8) % 4); if (padBytes == 4) { padBytes = 0; } size += padBytes; } bw.Write(0x52545854); bw.Write(size); bw.Write((short)model.TextureList.Count); foreach (string texture in model.TextureList) { size += texture.Length + 1; for (int i = 0; i < texture.Length; i++) { bw.Write((byte)texture[i]); } bw.Write((byte)0); } for (int i = 0; i < padBytes; i++) { bw.Write((byte)0); } }
private static void SerializeGuns(BinaryWriter bw, Polymodel model, short version) { int size; if (version >= 7) { size = (model.NumGuns * 28) + 4; } else { size = (model.NumGuns * 16) + 4; } bw.Write(0x534E5547); bw.Write(size); bw.Write(model.NumGuns); for (int i = 0; i < model.NumGuns; i++) { bw.Write((short)i); bw.Write((short)model.GunSubmodels[i]); bw.Write(model.GunPoints[i].X.value); bw.Write(model.GunPoints[i].Y.value); bw.Write(model.GunPoints[i].Z.value); if (version >= 7) { bw.Write(model.GunDirs[i].X.value); bw.Write(model.GunDirs[i].Y.value); bw.Write(model.GunDirs[i].Z.value); } } }
public Descent1PIGFile(bool macPig = false, bool loadData = true) { Textures = new ushort[800]; TMapInfo = new TMAPInfo[800]; SoundIDs = new byte[250]; AltSounds = new byte[250]; VClips = new VClip[70]; EClips = new EClip[60]; WClips = new WClip[30]; Robots = new Robot[30]; Joints = new JointPos[600]; Weapons = new Weapon[30]; Models = new Polymodel[85]; if (macPig) { Gauges = new ushort[85]; } else { Gauges = new ushort[80]; } ObjBitmaps = new ushort[210]; ObjBitmapPointers = new ushort[210]; Cockpits = new ushort[4]; ObjectTypes = new EditorObjectDefinition[100]; Powerups = new Powerup[29]; BitmapXLATData = new ushort[1800]; reactor = new Reactor(); Bitmaps = new List <PIGImage>(); Sounds = new List <SoundData>(); this.big = macPig; this.LoadData = loadData; }
public void WritePolymodel(Polymodel model, BinaryWriter bw) { bw.Write(model.NumSubmodels); bw.Write(model.ModelIDTASize); bw.Write(model.ModelIDTAPointer); for (int s = 0; s < 10; s++) { bw.Write(model.Submodels[s].Pointer); } for (int s = 0; s < 10; s++) { bw.Write(model.Submodels[s].Offset.X.value); bw.Write(model.Submodels[s].Offset.Y.value); bw.Write(model.Submodels[s].Offset.Z.value); } for (int s = 0; s < 10; s++) { bw.Write(model.Submodels[s].Normal.X.value); bw.Write(model.Submodels[s].Normal.Y.value); bw.Write(model.Submodels[s].Normal.Z.value); } for (int s = 0; s < 10; s++) { bw.Write(model.Submodels[s].Point.X.value); bw.Write(model.Submodels[s].Point.Y.value); bw.Write(model.Submodels[s].Point.Z.value); } for (int s = 0; s < 10; s++) { bw.Write(model.Submodels[s].Radius.value); } for (int s = 0; s < 10; s++) { bw.Write(model.Submodels[s].Parent); } for (int s = 0; s < 10; s++) { bw.Write(model.Submodels[s].Mins.X.value); bw.Write(model.Submodels[s].Mins.Y.value); bw.Write(model.Submodels[s].Mins.Z.value); } for (int s = 0; s < 10; s++) { bw.Write(model.Submodels[s].Maxs.X.value); bw.Write(model.Submodels[s].Maxs.Y.value); bw.Write(model.Submodels[s].Maxs.Z.value); } bw.Write(model.Mins.X.value); bw.Write(model.Mins.Y.value); bw.Write(model.Mins.Z.value); bw.Write(model.Maxs.X.value); bw.Write(model.Maxs.Y.value); bw.Write(model.Maxs.Z.value); bw.Write(model.Radius.value); bw.Write(model.NumTextures); bw.Write(model.FirstTexture); bw.Write(model.SimplerModels); }
public void RebuildModel(Polymodel model) { currentModel = model; List <BSPModel> data = ExtractModelData(model); submodels = data; BuildBSPTrees(data); RebuildModel(model, data); }
private List <BSPModel> ExtractModelData(Polymodel model) { PolymodelExtractor me = new PolymodelExtractor(); me.SetModel(model); var data = me.Extract(); if (me.IsPartitioned) { throw new ArgumentException("Model is already partitioned. Further partitioning will bloat data."); } return(data); }
public PSXDatFile() { Textures = new ushort[800]; TMapInfo = new TMAPInfo[800]; Sounds = new byte[250]; AltSounds = new byte[250]; VClips = new VClip[70]; EClips = new EClip[60]; WClips = new WClip[30]; Robots = new Robot[30]; Joints = new JointPos[600]; Weapons = new Weapon[30]; Models = new Polymodel[85]; Gauges = new ushort[80]; ObjBitmaps = new ushort[210]; ObjBitmapPointers = new ushort[210]; Cockpits = new ushort[4]; ObjectTypes = new EditorObjectDefinition[100]; Powerups = new Powerup[29]; BitmapXLATData = new ushort[1800]; reactor = new Reactor(); }
public static void SerializePolymodel(BinaryWriter bw, Polymodel model, short version) { bw.Write(0x4F505350); bw.Write(version); if (model.NumTextures > 0) { SerializeTextures(bw, model, version); } SerializeObject(bw, model, version); for (int i = 0; i < model.NumSubmodels; i++) { SerializeSubobject(bw, i, model.Submodels[i], version); } if (model.NumGuns > 0) { SerializeGuns(bw, model, version); } if (model.IsAnimated) { SerializeAnim(bw, model, version); } SerializeIDTA(bw, model, version); }
private static void SerializeIDTA(BinaryWriter bw, Polymodel model, short version) { int size = model.ModelIDTASize; int padBytes = 0; if (version >= 8) { padBytes = 4 - (((int)bw.BaseStream.Position + size + 8) % 4); if (padBytes == 4) { padBytes = 0; } size += padBytes; } bw.Write(0x41544449); bw.Write(size); bw.Write(model.InterpreterData); for (int i = 0; i < padBytes; i++) { bw.Write((byte)0); } }
private void RebuildModel(Polymodel newModel, List <BSPModel> bspModels) { int offset = 0; int vertexOffset = 0; //global scratch space. var data = new byte[1024 * 1024]; /*for (int i = 0; i < bspModels.Count; i++) * { * bspModels[i].CompileInterpreterData(vertexOffset); * vertexOffset += bspModels[i].NumVertices; * if (vertexOffset > 1000) * throw new ArgumentException("Model has too many vertices after partitioning."); * }*/ MetaInstructionBase hierarchy = this.GetHierarchy(0); hierarchy.Write(data, ref offset); SetShort(data, ref offset, 0); newModel.ModelIDTASize = offset; newModel.InterpreterData = data.Take(offset).ToArray(); }
private void Execute(byte[] data, int offset, Polymodel mainModel, Submodel model, BSPModel currentModel) { short instruction = GetShort(data, ref offset); while (true) { switch (instruction) { case ModelOpCode.End: return; case ModelOpCode.Points: { short pointc = GetShort(data, ref offset); for (int i = 0; i < pointc; i++) { interpPoints[i] = GetFixVector(data, ref offset); } } break; case ModelOpCode.FlatPoly: //FLATPOLY { short pointc = GetShort(data, ref offset); FixVector point = GetFixVector(data, ref offset); FixVector normal = GetFixVector(data, ref offset); short color = GetShort(data, ref offset); short[] points = new short[pointc]; //TODO: seems wasteful to do all these allocations? for (int i = 0; i < pointc; i++) { points[i] = GetShort(data, ref offset); } if (pointc % 2 == 0) { GetShort(data, ref offset); } if (pointc >= 3) { var triangle = new BSPFace(); triangle.Normal = new Vector3(normal.X, normal.Y, normal.Z); triangle.Point = new Vector3(point.X, point.Y, point.Z); triangle.Color = color; triangle.TextureID = -1; currentModel.Polygons.Add(triangle); for (int i = 0; i < pointc; i++) { var vxA = interpPoints[points[i]].X; var vyA = interpPoints[points[i]].Y; var vzA = interpPoints[points[i]].Z; triangle.Points.Add(new BSPVertex { Point = new Vector3(vxA, vyA, vzA), UVs = new Vector3(0.0f, 0.0f, 0.0f) }); } } } break; case ModelOpCode.TexturedPoly: //TMAPPOLY { short pointc = GetShort(data, ref offset); FixVector point = GetFixVector(data, ref offset); FixVector normal = GetFixVector(data, ref offset); short texture = GetShort(data, ref offset); short[] points = new short[pointc]; //TODO: seems wasteful to do all these allocations? FixVector[] uvls = new FixVector[pointc]; for (int i = 0; i < pointc; i++) { points[i] = GetShort(data, ref offset); } if (pointc % 2 == 0) { GetShort(data, ref offset); } for (int i = 0; i < pointc; i++) { uvls[i] = GetFixVector(data, ref offset); } if (pointc >= 3) { var triangle = new BSPFace(); triangle.Normal = new Vector3(normal.X, normal.Y, normal.Z); triangle.Point = new Vector3(point.X, point.Y, point.Z); triangle.TextureID = texture; currentModel.Polygons.Add(triangle); for (int i = 0; i < pointc; i++) { var vxA = interpPoints[points[i]].X; var vyA = interpPoints[points[i]].Y; var vzA = interpPoints[points[i]].Z; var uvxA = uvls[i].X; var uvyA = uvls[i].Y; triangle.Points.Add(new BSPVertex { Point = new Vector3(vxA, vyA, vzA), UVs = new Vector3(uvxA, uvyA, 0.0f) }); } } } break; case ModelOpCode.SortNormal: //SORTNORM { IsPartitioned = true; int baseOffset = offset - 2; int n_points = GetShort(data, ref offset); FixVector norm = GetFixVector(data, ref offset); FixVector point = GetFixVector(data, ref offset); short backOffset = GetShort(data, ref offset); short frontOffset = GetShort(data, ref offset); Execute(data, baseOffset + frontOffset, mainModel, model, currentModel); Execute(data, baseOffset + backOffset, mainModel, model, currentModel); } break; case ModelOpCode.Rod: //RODBM { offset += 34; } break; case ModelOpCode.SubCall: //SUBCALL { int baseOffset = offset - 2; short submodelNum = GetShort(data, ref offset); FixVector submodelOffset = GetFixVector(data, ref offset); short modelOffset = GetShort(data, ref offset); offset += 2; Submodel newModel = mainModel.Submodels[submodelNum]; currentModel.modelOffset = submodelOffset; Execute(data, baseOffset + modelOffset, mainModel, newModel, modelDatas[submodelNum]); } break; case ModelOpCode.DefinePointStart: //DEFPSTART { short pointc = GetShort(data, ref offset); short firstPoint = GetShort(data, ref offset); offset += 2; for (int i = 0; i < pointc; i++) { interpPoints[i + firstPoint] = GetFixVector(data, ref offset); } } break; case ModelOpCode.Glow: offset += 2; break; default: throw new Exception(string.Format("Unknown interpreter instruction {0} at offset {1}\n", instruction, offset)); } instruction = GetShort(data, ref offset); } }
public void SetModel(Polymodel model) { this.model = model; }
/// <summary> /// Loads an HXM file from a given stream. /// </summary> /// <param name="stream">The stream to load the HXM data from.</param> public void Read(Stream stream) { BinaryReader br; br = new BinaryReader(stream); HAMDataReader data = new HAMDataReader(); int sig = br.ReadInt32(); int ver = br.ReadInt32(); if (sig != 559435080) { br.Dispose(); throw new InvalidDataException("HXMFile::Read: HXM file has bad header."); } if (ver != 1) { br.Dispose(); throw new InvalidDataException(string.Format("HXMFile::Read: HXM file has bad version. Got {0}, but expected 1", ver)); } int replacedRobotCount = br.ReadInt32(); for (int x = 0; x < replacedRobotCount; x++) { int replacementID = br.ReadInt32(); Robot robot = data.ReadRobot(br); robot.replacementID = replacementID; ReplacedRobots.Add(robot); } int replacedJointCount = br.ReadInt32(); for (int x = 0; x < replacedJointCount; x++) { int replacementID = br.ReadInt32(); JointPos joint = new JointPos(); joint.JointNum = br.ReadInt16(); joint.Angles.P = br.ReadInt16(); joint.Angles.B = br.ReadInt16(); joint.Angles.H = br.ReadInt16(); joint.ReplacementID = replacementID; ReplacedJoints.Add(joint); } int modelsToReplace = br.ReadInt32(); for (int x = 0; x < modelsToReplace; x++) { int replacementID = br.ReadInt32(); Polymodel model = data.ReadPolymodelInfo(br); model.ReplacementID = replacementID; model.InterpreterData = br.ReadBytes(model.ModelIDTASize); ReplacedModels.Add(model); model.DyingModelnum = br.ReadInt32(); model.DeadModelnum = br.ReadInt32(); } int objBitmapsToReplace = br.ReadInt32(); for (int x = 0; x < objBitmapsToReplace; x++) { ReplacedBitmapElement objBitmap = new ReplacedBitmapElement(); objBitmap.ReplacementID = br.ReadInt32(); objBitmap.Data = br.ReadUInt16(); ReplacedObjBitmaps.Add(objBitmap); //Console.WriteLine("Loading replacement obj bitmap, replacing slot {0} with {1} ({2})", objBitmap.replacementID, objBitmap.data, baseFile.piggyFile.images[objBitmap.data].name); } int objBitmapPtrsToReplace = br.ReadInt32(); for (int x = 0; x < objBitmapPtrsToReplace; x++) { ReplacedBitmapElement objBitmap = new ReplacedBitmapElement(); objBitmap.ReplacementID = br.ReadInt32(); objBitmap.Data = br.ReadUInt16(); ReplacedObjBitmapPtrs.Add(objBitmap); } }
public static Polymodel ReadPOFFile(Stream stream) { BinaryReader br = new BinaryReader(stream); Polymodel model = new Polymodel(); int sig = br.ReadInt32(); short ver = br.ReadInt16(); if (ver < 6 || ver > 8) { throw new InvalidDataException(string.Format("POF File has unsupported version. Got {0}, but expected \"6\", \"7\", or \"8\".", ver)); } int chunk = br.ReadInt32(); int datasize = br.ReadInt32(); long dest = br.BaseStream.Position + datasize; while (true) { //1096041545 switch (chunk) { //TXTR case 1381259348: { short texcount = br.ReadInt16(); model.NumTextures = (byte)texcount; for (int x = 0; x < texcount; x++) { char[] texchars = new char[128]; texchars[0] = (char)br.ReadByte(); int i = 1; while (texchars[i - 1] != '\0') { texchars[i] = (char)br.ReadByte(); i++; } string name = new string(texchars); name = name.Trim(' ', '\0'); model.TextureList.Add(name.ToLower()); } } break; //OHDR case 1380206671: { model.NumSubmodels = br.ReadInt32(); model.Radius = new Fix(br.ReadInt32()); model.Mins = ReadVector(br); model.Maxs = ReadVector(br); for (int i = 0; i < model.NumSubmodels; i++) { model.Submodels.Add(new Submodel()); } } break; //SOBJ case 1245859667: { short modelnum = br.ReadInt16(); Submodel submodel = model.Submodels[modelnum]; submodel.ID = modelnum; short parentTest = br.ReadInt16(); submodel.Parent = (byte)parentTest; submodel.Normal = ReadVector(br); submodel.Point = ReadVector(br); submodel.Offset = ReadVector(br); submodel.Radius = new Fix(br.ReadInt32()); submodel.Pointer = br.ReadInt32(); if (submodel.Parent != 255) { model.Submodels[submodel.Parent].Children.Add(submodel); } } break; //GUNS case 0x534E5547: { int numGuns = br.ReadInt32(); model.NumGuns = numGuns; for (int i = 0; i < numGuns; i++) { short id = br.ReadInt16(); model.GunSubmodels[id] = br.ReadInt16(); model.GunPoints[id] = ReadVector(br); model.GunDirs[id] = ReadVector(br); } } break; //ANIM case 1296649793: { model.IsAnimated = true; //br.ReadBytes(datasize); int numFrames = br.ReadInt16(); for (int submodel = 0; submodel < model.NumSubmodels; submodel++) { for (int i = 0; i < numFrames; i++) { if (i < 5) //bounds check to avoid issues with more frames than intended { model.AnimationMatrix[submodel, i].P = br.ReadInt16(); model.AnimationMatrix[submodel, i].B = br.ReadInt16(); model.AnimationMatrix[submodel, i].H = br.ReadInt16(); } } } } break; //IDTA case 1096041545: { //model.ModelIDTASize = datasize; model.InterpreterData = br.ReadBytes(datasize); } break; default: br.ReadBytes(datasize); break; } //Maintain 4-byte alignment if (ver >= 8) { br.BaseStream.Seek(dest, SeekOrigin.Begin); } if (br.BaseStream.Position >= br.BaseStream.Length) { break; } chunk = br.ReadInt32(); datasize = br.ReadInt32(); dest = br.BaseStream.Position + datasize; } for (int i = 0; i < model.NumSubmodels; i++) { model.GetSubmodelMinMaxs(i); } br.Close(); return(model); }
public Polymodel ReadPolymodelInfoPSX(BinaryReader br) { Polymodel model = new Polymodel(Polymodel.MaxSubmodels); model.NumSubmodels = br.ReadInt32(); model.ModelIDTASize = br.ReadInt32(); model.ModelIDTAPointer = br.ReadInt32(); for (int s = 0; s < Polymodel.MaxSubmodels; s++) { model.Submodels[s].Pointer = br.ReadInt32(); } for (int s = 0; s < Polymodel.MaxSubmodels; s++) { model.Submodels[s].Offset.X = new Fix(br.ReadInt32()); model.Submodels[s].Offset.Y = new Fix(br.ReadInt32()); model.Submodels[s].Offset.Z = new Fix(br.ReadInt32()); } for (int s = 0; s < Polymodel.MaxSubmodels; s++) { model.Submodels[s].Normal.X = new Fix(br.ReadInt32()); model.Submodels[s].Normal.Y = new Fix(br.ReadInt32()); model.Submodels[s].Normal.Z = new Fix(br.ReadInt32()); } for (int s = 0; s < Polymodel.MaxSubmodels; s++) { model.Submodels[s].Point.X = new Fix(br.ReadInt32()); model.Submodels[s].Point.Y = new Fix(br.ReadInt32()); model.Submodels[s].Point.Z = new Fix(br.ReadInt32()); } for (int s = 0; s < Polymodel.MaxSubmodels; s++) { model.Submodels[s].Radius = new Fix(br.ReadInt32()); } for (int s = 0; s < Polymodel.MaxSubmodels; s++) { byte parent = br.ReadByte(); model.Submodels[s].Parent = parent; if (parent != 255) { model.Submodels[parent].Children.Add(model.Submodels[s]); } } short unk1 = br.ReadInt16(); for (int s = 0; s < Polymodel.MaxSubmodels; s++) { model.Submodels[s].Mins.X = new Fix(br.ReadInt32()); model.Submodels[s].Mins.Y = new Fix(br.ReadInt32()); model.Submodels[s].Mins.Z = new Fix(br.ReadInt32()); } for (int s = 0; s < Polymodel.MaxSubmodels; s++) { model.Submodels[s].Maxs.X = new Fix(br.ReadInt32()); model.Submodels[s].Maxs.Y = new Fix(br.ReadInt32()); model.Submodels[s].Maxs.Z = new Fix(br.ReadInt32()); } model.Mins = new FixVector(new Fix(br.ReadInt32()), new Fix(br.ReadInt32()), new Fix(br.ReadInt32())); model.Maxs = new FixVector(new Fix(br.ReadInt32()), new Fix(br.ReadInt32()), new Fix(br.ReadInt32())); model.Radius = new Fix(br.ReadInt32()); model.NumTextures = (byte)br.ReadInt16(); model.FirstTexture = br.ReadUInt16(); model.SimplerModels = (byte)br.ReadInt16(); short unk2 = br.ReadInt16(); return(model); }