private void WriteGroup(int groupIndex, ref int baseIndex, ModelEntity model) { _streamWriter.WriteLine("g group" + groupIndex); _streamWriter.WriteLine("usemtl mtl{0}", model.TexturePage); for (var k = 0; k < model.Triangles.Length; k++) { _streamWriter.WriteLine("f {2}/{2}/{2} {1}/{1}/{1} {0}/{0}/{0}", baseIndex++, baseIndex++, baseIndex++); } }
private void WriteModel(ModelEntity model) { if (model.Texture != null) { if (_mtlExporter.AddMaterial((int)model.TexturePage)) { _pngExporter.Export(model.Texture, (int)model.TexturePage, _selectedPath); } } var worldMatrix = model.WorldMatrix; foreach (var triangle in model.Triangles) { var vertexColor0 = string.Empty; var vertexColor1 = string.Empty; var vertexColor2 = string.Empty; var c0 = triangle.Colors[0]; var c1 = triangle.Colors[1]; var c2 = triangle.Colors[2]; if (_experimentalVertexColor) { vertexColor0 = string.Format(" {0} {1} {2}", (c0.R).ToString(GeomUtils.FloatFormat, CultureInfo.InvariantCulture), (c0.G).ToString(GeomUtils.FloatFormat, CultureInfo.InvariantCulture), (c0.B).ToString(GeomUtils.FloatFormat, CultureInfo.InvariantCulture)); vertexColor1 = string.Format(" {0} {1} {2}", (c1.R).ToString(GeomUtils.FloatFormat, CultureInfo.InvariantCulture), (c1.G).ToString(GeomUtils.FloatFormat, CultureInfo.InvariantCulture), (c1.B).ToString(GeomUtils.FloatFormat, CultureInfo.InvariantCulture)); vertexColor2 = string.Format(" {0} {1} {2}", (c2.R).ToString(GeomUtils.FloatFormat, CultureInfo.InvariantCulture), (c2.G).ToString(GeomUtils.FloatFormat, CultureInfo.InvariantCulture), (c2.B).ToString(GeomUtils.FloatFormat, CultureInfo.InvariantCulture)); } var v0 = Vector3.TransformPosition(triangle.Vertices[0], worldMatrix); var v1 = Vector3.TransformPosition(triangle.Vertices[1], worldMatrix); var v2 = Vector3.TransformPosition(triangle.Vertices[2], worldMatrix); _streamWriter.WriteLine("v {0} {1} {2} {3}", (v0.X).ToString(GeomUtils.FloatFormat, CultureInfo.InvariantCulture), (-v0.Y).ToString(GeomUtils.FloatFormat, CultureInfo.InvariantCulture), (-v0.Z).ToString(GeomUtils.FloatFormat, CultureInfo.InvariantCulture), vertexColor0); _streamWriter.WriteLine("v {0} {1} {2} {3}", (v1.X).ToString(GeomUtils.FloatFormat, CultureInfo.InvariantCulture), (-v1.Y).ToString(GeomUtils.FloatFormat, CultureInfo.InvariantCulture), (-v1.Z).ToString(GeomUtils.FloatFormat, CultureInfo.InvariantCulture), vertexColor1); _streamWriter.WriteLine("v {0} {1} {2} {3}", (v2.X).ToString(GeomUtils.FloatFormat, CultureInfo.InvariantCulture), (-v2.Y).ToString(GeomUtils.FloatFormat, CultureInfo.InvariantCulture), (-v2.Z).ToString(GeomUtils.FloatFormat, CultureInfo.InvariantCulture), vertexColor2); } foreach (var triangle in model.Triangles) { var n0 = Vector3.TransformNormal(triangle.Normals[0], worldMatrix); var n1 = Vector3.TransformNormal(triangle.Normals[1], worldMatrix); var n2 = Vector3.TransformNormal(triangle.Normals[2], worldMatrix); _streamWriter.WriteLine("vn {0} {1} {2}", (n0.X).ToString(GeomUtils.FloatFormat, CultureInfo.InvariantCulture), (-n0.Y).ToString(GeomUtils.FloatFormat, CultureInfo.InvariantCulture), (-n0.Z).ToString(GeomUtils.FloatFormat, CultureInfo.InvariantCulture)); _streamWriter.WriteLine("vn {0} {1} {2}", (n1.X).ToString(GeomUtils.FloatFormat, CultureInfo.InvariantCulture), (-n1.Y).ToString(GeomUtils.FloatFormat, CultureInfo.InvariantCulture), (-n1.Z).ToString(GeomUtils.FloatFormat, CultureInfo.InvariantCulture)); _streamWriter.WriteLine("vn {0} {1} {2}", (n2.X).ToString(GeomUtils.FloatFormat, CultureInfo.InvariantCulture), (-n2.Y).ToString(GeomUtils.FloatFormat, CultureInfo.InvariantCulture), (-n2.Z).ToString(GeomUtils.FloatFormat, CultureInfo.InvariantCulture)); } foreach (var triangle in model.Triangles) { var uv0 = triangle.Uv[0]; var uv1 = triangle.Uv[1]; var uv2 = triangle.Uv[2]; _streamWriter.WriteLine("vt {0} {1}", uv0.X.ToString(GeomUtils.FloatFormat, CultureInfo.InvariantCulture), (1f - uv0.Y).ToString(GeomUtils.FloatFormat, CultureInfo.InvariantCulture)); _streamWriter.WriteLine("vt {0} {1}", uv1.X.ToString(GeomUtils.FloatFormat, CultureInfo.InvariantCulture), (1f - uv1.Y).ToString(GeomUtils.FloatFormat, CultureInfo.InvariantCulture)); _streamWriter.WriteLine("vt {0} {1}", uv2.X.ToString(GeomUtils.FloatFormat, CultureInfo.InvariantCulture), (1f - uv2.Y).ToString(GeomUtils.FloatFormat, CultureInfo.InvariantCulture)); } }
private void ProccessPrimitive(BinaryReader reader, List <ModelEntity> modelEntities, List <Animation> animations, List <Texture> textures, uint primitiveIndex, uint primitiveSetTop, uint primitiveHeaderTop) { var groupedTriangles = new Dictionary <uint, List <Triangle> >(); while (true) { reader.BaseStream.Seek(_offset + primitiveSetTop, SeekOrigin.Begin); var nextPrimitivePointer = reader.ReadUInt32(); var primitiveHeaderPointer = reader.ReadUInt32() * 4; ReadMappedValue(reader, out var typeCountMapped, out var typeCount); if (typeCount > Program.MaxHMDTypeCount) { return; } for (var j = 0; j < typeCount; j++) { //0: Polygon data 1: Shared polygon data 2: Image data 3: Animation data 4: MIMe data 5: Ground data var type = reader.ReadUInt32(); var developerId = (type >> 27) & 0b00001111; //4 var category = (type >> 24) & 0b00001111; //4 var driver = (type >> 16) & 0b11111111; //8 var primitiveType = type & 0xFFFF; //16 ReadMappedValue16(reader, out var dataCountMapped, out var dataCount); ReadMappedValue16(reader, out var dataSizeMapped, out var dataSize); if (dataCount > Program.MaxHMDDataSize) { return; } if (dataSize > Program.MaxHMDDataSize) { return; } if (category > 5) { return; } if (Program.Debug) { Program.Logger.WriteLine($"HMD Type: {type} of category {category} and primitive type {primitiveType}"); } if (Program.Debug) { Program.Logger.WriteLine("Primitive type bits:" + new BitArray(BitConverter.GetBytes(primitiveType)).ToBitString()); } if (category == 0) { if (Program.Debug) { Program.Logger.WriteLine($"HMD Non-Shared Vertices Geometry"); } var polygonIndex = reader.ReadUInt32() * 4; ProcessNonSharedGeometryData(groupedTriangles, reader, driver, primitiveType, primitiveHeaderPointer, nextPrimitivePointer, polygonIndex, dataSize); } else if (category == 1) { if (Program.Debug) { Program.Logger.WriteLine($"HMD Shared Vertices Geometry"); } } else if (category == 1) { if (Program.Debug) { Program.Logger.WriteLine($"HMD Image Data"); } var hasClut = primitiveType == 1; var texture = ProcessImageData(reader, driver, hasClut, primitiveHeaderPointer, nextPrimitivePointer); if (texture != null) { textures.Add(texture); } } else if (category == 3) { if (Program.Debug) { Program.Logger.WriteLine($"HMD Animation"); } } else if (category == 4) { var code1 = (primitiveType & 0b11100000) > 0; var rst = (primitiveType & 0b00010000) > 0; var code0 = (primitiveType & 0b00001110) > 0; if (Program.Debug) { Program.Logger.WriteLine($"HMD Mime Animation: {code1}|{rst}|{code0}"); } //todo: docs are broken! if (!code0) { var diffTop = reader.ReadUInt32() * 4; Animation animation = null; if (code1) { animation = ProcessMimeVertexData(groupedTriangles, reader, driver, primitiveType, primitiveHeaderPointer, nextPrimitivePointer, diffTop, dataSize, rst); } if (animation != null) { animations.Add(animation); } } } else if (category == 5) { if (Program.Debug) { Program.Logger.WriteLine($"HMD Grid"); } var polygonIndex = reader.ReadUInt32() * 4; var gridIndex = reader.ReadUInt32() * 4; var vertexIndex = reader.ReadUInt32() * 4; ProcessGroundData(groupedTriangles, reader, driver, primitiveType, primitiveHeaderPointer, nextPrimitivePointer, polygonIndex, dataCount / 4, gridIndex, vertexIndex); } } if (nextPrimitivePointer != 0xFFFFFFFF) { primitiveSetTop = nextPrimitivePointer * 4; continue; } break; } foreach (var key in groupedTriangles.Keys) { var triangles = groupedTriangles[key]; var model = new ModelEntity { Triangles = triangles.ToArray(), TexturePage = key, TMDID = primitiveIndex, //todo //PrimitiveIndex = primitiveIndex }; modelEntities.Add(model); } }
private RootEntity ParsePMD(BinaryReader reader) { var primPoint = reader.ReadUInt32(); var vertPoint = reader.ReadUInt32(); var nObj = reader.ReadUInt32(); if (nObj < 1 || nObj > 4000) { return(null); } var models = new List <ModelEntity>(); for (var o = 0; o < nObj; o++) { var model = new ModelEntity(); var triangles = new List <Triangle>(); var nPointers = reader.ReadUInt32(); if (nPointers < 1 || nPointers > 4000) { return(null); } for (var p = 0; p < nPointers; p++) { var position = reader.BaseStream.Position; var pointer = reader.ReadUInt32(); reader.BaseStream.Seek(_offset + pointer, SeekOrigin.Begin); var nPacket = reader.ReadUInt16(); if (nPacket > 4000) { return(null); } var primType = reader.ReadUInt16(); if (primType > 15) { return(null); } for (var pk = 0; pk < nPacket; pk++) { switch (primType) { case 0x00: triangles.Add(ReadPolyFT3(reader)); break; case 0x01: triangles.AddRange(ReadPolyFT4(reader)); break; case 0x02: triangles.Add(ReadPolyGT3(reader)); break; case 0x03: triangles.AddRange(ReadPolyGT4(reader)); break; case 0x04: triangles.Add(ReadPolyF3(reader)); break; case 0x05: triangles.AddRange(ReadPolyF4(reader)); break; case 0x06: triangles.Add(ReadPolyG3(reader)); break; case 0x07: triangles.AddRange(ReadPolyG4(reader)); break; case 0x08: triangles.Add(ReadPolyFT3(reader, true, _offset + vertPoint)); break; case 0x09: triangles.AddRange(ReadPolyFT4(reader, true, _offset + vertPoint)); break; case 0x0a: triangles.Add(ReadPolyGT3(reader, true, _offset + vertPoint)); break; case 0x0b: triangles.AddRange(ReadPolyGT4(reader, true, _offset + vertPoint)); break; case 0x0c: triangles.Add(ReadPolyF3(reader, true, _offset + vertPoint)); break; case 0x0d: triangles.AddRange(ReadPolyF4(reader, true, _offset + vertPoint)); break; case 0x0e: triangles.Add(ReadPolyG3(reader, true, _offset + vertPoint)); break; case 0x0f: triangles.AddRange(ReadPolyG4(reader, true, _offset + vertPoint)); break; default: if (Program.Debug) { Program.Logger.WriteErrorLine("Unknown primitive:" + primType); } goto EndObject; } } reader.BaseStream.Seek(position + 4, SeekOrigin.Begin); } EndObject: model.Triangles = triangles.ToArray(); models.Add(model); } EndModel: if (models.Count > 0) { var entity = new RootEntity(); foreach (var model in models) { model.ParentEntity = entity; } entity.ChildEntities = models.ToArray(); entity.ComputeBounds(); return(entity); } return(null); }
private RootEntity ParseTmd(BinaryReader reader, string fileTitle) { var flags = reader.ReadUInt32(); if (flags != 0 && flags != 1) { return(null); } var nObj = reader.ReadUInt32(); if (nObj == 0 || nObj > Program.MaxTMDObjects) { return(null); } var models = new List <ModelEntity>(); var objBlocks = new ObjBlock[nObj]; var objOffset = reader.BaseStream.Position; for (var o = 0; o < nObj; o++) { var vertTop = reader.ReadUInt32(); var nVert = reader.ReadUInt32(); var normalTop = reader.ReadUInt32(); var nNormal = reader.ReadUInt32(); var primitiveTop = reader.ReadUInt32(); var nPrimitive = reader.ReadUInt32(); var scale = reader.ReadInt32(); if (flags == 0) { vertTop += (uint)objOffset; normalTop += (uint)objOffset; primitiveTop += (uint)objOffset; } if (nPrimitive > Program.MaxTMDPrimitives) { return(null); } objBlocks[o] = new ObjBlock { VertTop = vertTop, NVert = nVert, NormalTop = normalTop, NNormal = nNormal, PrimitiveTop = primitiveTop, NPrimitive = nPrimitive, Scale = scale }; } for (uint o = 0; o < objBlocks.Length; o++) { var objBlock = objBlocks[o]; var vertices = new Vector3[objBlock.NVert]; if (Program.IgnoreTmdVersion && objBlock.VertTop < _offset) { return(null); } reader.BaseStream.Seek(objBlock.VertTop, SeekOrigin.Begin); for (var v = 0; v < objBlock.NVert; v++) { var vx = reader.ReadInt16(); var vy = reader.ReadInt16(); var vz = reader.ReadInt16(); var pad = reader.ReadInt16(); if (pad != 0) { if (Program.Debug) { Program.Logger.WriteLine($"Found suspicious pad value of: {pad} at index:{v}"); } } var vertex = new Vector3 { X = vx, Y = vy, Z = vz }; vertices[v] = vertex; } var normals = new Vector3[objBlock.NNormal]; if (Program.IgnoreTmdVersion && objBlock.NormalTop < _offset) { return(null); } reader.BaseStream.Seek(objBlock.NormalTop, SeekOrigin.Begin); for (var n = 0; n < objBlock.NNormal; n++) { var nx = TMDHelper.ConvertNormal(reader.ReadInt16()); var ny = TMDHelper.ConvertNormal(reader.ReadInt16()); var nz = TMDHelper.ConvertNormal(reader.ReadInt16()); var pad = reader.ReadInt16(); if (pad != 0) { if (Program.Debug) { Program.Logger.WriteLine($"Found suspicious pad value of: {pad} at index:{n}"); } } var normal = new Vector3 { X = nx, Y = ny, Z = nz }; normals[n] = normal.Normalized(); } var groupedTriangles = new Dictionary <uint, List <Triangle> >(); reader.BaseStream.Seek(objBlock.PrimitiveTop, SeekOrigin.Begin); if (Program.IgnoreTmdVersion && objBlock.PrimitiveTop < _offset) { return(null); } if (Program.Debug) { Program.Logger.WriteLine($"Primitive count:{objBlock.NPrimitive} {fileTitle}"); } for (var p = 0; p < objBlock.NPrimitive; p++) { var olen = reader.ReadByte(); var ilen = reader.ReadByte(); var flag = reader.ReadByte(); var mode = reader.ReadByte(); var offset = reader.BaseStream.Position; var packetStructure = TMDHelper.CreateTMDPacketStructure(flag, mode, reader, p); if (packetStructure != null) { TMDHelper.AddTrianglesToGroup(groupedTriangles, packetStructure, delegate(uint index) { if (index >= vertices.Length) { if (Program.IgnoreTmdVersion) { return(new Vector3(index, 0, 0)); } Program.Logger.WriteErrorLine("Vertex index error : " + fileTitle); throw new Exception("Vertex index error: " + fileTitle); } return(vertices[index]); }, delegate(uint index) { if (index >= normals.Length) { if (Program.IgnoreTmdVersion) { return(new Vector3(index, 0, 0)); } Program.Logger.WriteErrorLine("Vertex index error: " + fileTitle); throw new Exception("Vertex index error: " + fileTitle); } return(normals[index]); }); } var newOffset = offset + ilen * 4; if (Program.IgnoreTmdVersion && newOffset < _offset) { return(null); } reader.BaseStream.Seek(newOffset, SeekOrigin.Begin); } foreach (var kvp in groupedTriangles) { var triangles = kvp.Value; if (triangles.Count > 0) { var model = new ModelEntity { Triangles = triangles.ToArray(), TexturePage = kvp.Key, TMDID = o }; models.Add(model); } } } if (models.Count > 0) { var entity = new RootEntity(); foreach (var model in models) { model.ParentEntity = entity; } entity.ChildEntities = models.ToArray(); entity.ComputeBounds(); return(entity); } return(null); }
private static RootEntity ReadModels(BinaryReader reader) { var count = BRenderHelper.ReadU16BE(reader.BaseStream); if (count == 0 || count > 10000) { return(null); } var flags = BRenderHelper.ReadU16BE(reader.BaseStream); var models = new List <ModelEntity>(); for (var i = 0; i < count; i++) { var modelEntity = new ModelEntity(); var radius = (int)BRenderHelper.ReadU32BE(reader.BaseStream); for (var j = 0; j < 9; j++) { for (var k = 0; k < 4; k++) { BRenderHelper.ReadU16BE(reader.BaseStream); } } var countVerts = BRenderHelper.ReadU32BE(reader.BaseStream); if (countVerts == 0 || countVerts > 1000) { return(null); } var vertices = new Vector3[countVerts]; var normals = new Vector3[countVerts]; for (var j = 0; j < countVerts; j++) { var x = (short)BRenderHelper.ReadU16BE(reader.BaseStream) / 16f; var z = (short)BRenderHelper.ReadU16BE(reader.BaseStream) / 16f; var y = -(short)BRenderHelper.ReadU16BE(reader.BaseStream) / 16f; BRenderHelper.ReadU16BE(reader.BaseStream); vertices[j] = new Vector3(x, y, z); } for (var j = 0; j < countVerts; j++) { var x = (short)BRenderHelper.ReadU16BE(reader.BaseStream) / 16f; var z = (short)BRenderHelper.ReadU16BE(reader.BaseStream) / 16f; var y = -(short)BRenderHelper.ReadU16BE(reader.BaseStream) / 16f; BRenderHelper.ReadU16BE(reader.BaseStream); normals[j] = new Vector3(x, y, z); } var countFaces = BRenderHelper.ReadU32BE(reader.BaseStream); var triangles = new List <Triangle>(); //var header = Encoding.ASCII.GetString(reader.ReadBytes(64)); for (var j = 0; j < countFaces; j++) { var unk1 = reader.BaseStream.ReadByte(); var unk2 = reader.BaseStream.ReadByte(); var unk3 = reader.BaseStream.ReadByte(); var unk4 = reader.BaseStream.ReadByte(); var unk5 = reader.BaseStream.ReadByte(); var unk6 = reader.BaseStream.ReadByte(); var unk7 = reader.BaseStream.ReadByte(); var unk8 = reader.BaseStream.ReadByte(); var f0 = BRenderHelper.ReadU16BE(reader.BaseStream); var f1 = BRenderHelper.ReadU16BE(reader.BaseStream); var f2 = BRenderHelper.ReadU16BE(reader.BaseStream); var f3 = BRenderHelper.ReadU16BE(reader.BaseStream); if (f0 >= vertices.Length || f1 >= vertices.Length || f2 >= vertices.Length || f3 >= vertices.Length) { return(null); } var unk9 = BRenderHelper.ReadU16BE(reader.BaseStream); var unk10 = reader.BaseStream.ReadByte(); var primFlags = reader.BaseStream.ReadByte(); var vertex0 = vertices[f0]; var vertex1 = vertices[f1]; var vertex2 = vertices[f2]; var normal0 = normals[f0]; var normal1 = normals[f1]; var normal2 = normals[f2]; //if (Math.Abs((normal0 + normal1 + normal2).Length) <= 0.0f) //{ normal0 = Vector3.Cross(vertex1 - vertex0, vertex2 - vertex0).Normalized(); normal1 = normal0; normal2 = normal0; //} triangles.Add(new Triangle { Vertices = new[] { vertex0, vertex1, vertex2 }, Normals = new[] { normal0, normal1, normal2 }, Colors = new[] { Color.Grey, Color.Grey, Color.Grey }, Uv = new[] { Vector3.Zero, Vector3.Zero, Vector3.Zero }, AttachableIndices = new [] { uint.MaxValue, uint.MaxValue, uint.MaxValue } }); if ((primFlags & 0x8) != 0) { var vertex3 = vertices[f3]; var normal3 = normals[f3]; //if (Math.Abs((normal1 + normal3 + normal2).Length) <= 0.0f) { normal3 = Vector3.Cross(vertex3 - vertex1, vertex2 - vertex1).Normalized(); normal1 = normal3; normal2 = normal3; } triangles.Add(new Triangle { Vertices = new[] { vertex1, vertex3, vertex2 }, Normals = new[] { normal1, normal3, normal2 }, Colors = new[] { Color.Grey, Color.Grey, Color.Grey }, Uv = new[] { Vector3.Zero, Vector3.Zero, Vector3.Zero }, AttachableIndices = new[] { uint.MaxValue, uint.MaxValue, uint.MaxValue } }); } } modelEntity.Triangles = triangles.ToArray(); models.Add(modelEntity); } if (models.Count > 0) { var entity = new RootEntity(); foreach (var model in models) { model.ParentEntity = entity; } entity.ChildEntities = models.ToArray(); entity.ComputeBounds(); return(entity); } return(null); }
private RootEntity ReadModels(BinaryReader reader, Dictionary <uint, List <Triangle> > groupedTriangles) { void AddTriangle(Triangle triangle, uint tPage) { List <Triangle> triangles; if (groupedTriangles.ContainsKey(tPage)) { triangles = groupedTriangles[tPage]; } else { triangles = new List <Triangle>(); groupedTriangles.Add(tPage, triangles); } triangles.Add(triangle); } //var id0 = reader.ReadByte(); //var id1 = reader.ReadByte(); //var id2 = reader.ReadByte(); //var id3 = reader.ReadByte(); //if ((char)id0 != 'P' || (char)id1 != 'S' || (char)id2 != 'I' || id3 != 1) //{ // return null; //} // //var version = reader.ReadUInt32(); //var flags = reader.ReadUInt32(); //var name = Encoding.ASCII.GetString(reader.ReadBytes(32)); //var meshNum = reader.ReadUInt32(); //var vertNum = reader.ReadUInt32(); //var primNum = reader.ReadUInt32(); //var primOffset = reader.ReadUInt32(); //var animStart = reader.ReadUInt16(); //var animEnd = reader.ReadUInt16(); //var animNum = reader.ReadUInt32(); //var animSegListOffset = reader.ReadUInt32(); //var numTex = reader.ReadUInt32(); //var texOff = reader.ReadUInt32(); //var firstMeshOff = reader.ReadUInt32(); //var radius = reader.ReadUInt32(); //var pad = reader.ReadBytes(192 - 88); // //var models = new List<ModelEntity>(); //var position = reader.BaseStream.Position; //{ // reader.BaseStream.Seek(_offset + firstMeshOff, SeekOrigin.Begin); // var vertTop = reader.ReadUInt32(); // var vertCount = reader.ReadUInt32(); // var normTop = reader.ReadUInt32(); // var normCount = reader.ReadUInt32(); // var scale = reader.ReadUInt32(); // // var meshName = Encoding.ASCII.GetString(reader.ReadBytes(16)); // var childTop = reader.ReadUInt32(); // var nextTop = reader.ReadUInt32(); // // var numScaleKeys = reader.ReadUInt16(); // var numMoveKeys = reader.ReadUInt16(); // var numRotKeys = reader.ReadUInt16(); // var pad1 = reader.ReadUInt16(); // // var scaleKeysTop = reader.ReadUInt32(); // var moveKeysTop = reader.ReadUInt32(); // var rotateKeysTop = reader.ReadUInt32(); // // var sortListSize0 = reader.ReadUInt16(); // var sortListSize1 = reader.ReadUInt16(); // var sortListSize2 = reader.ReadUInt16(); // var sortListSize3 = reader.ReadUInt16(); // var sortListSize4 = reader.ReadUInt16(); // var sortListSize5 = reader.ReadUInt16(); // var sortListSize6 = reader.ReadUInt16(); // var sortListSize7 = reader.ReadUInt16(); // // var sortListSizeTop0 = reader.ReadUInt32(); // var sortListSizeTop1 = reader.ReadUInt32(); // var sortListSizeTop2 = reader.ReadUInt32(); // var sortListSizeTop3 = reader.ReadUInt32(); // var sortListSizeTop4 = reader.ReadUInt32(); // var sortListSizeTop5 = reader.ReadUInt32(); // var sortListSizeTop6 = reader.ReadUInt32(); // var sortListSizeTop7 = reader.ReadUInt32(); // // var lastScaleKey = reader.ReadUInt16(); // var lastMoveKey = reader.ReadUInt16(); // var lastRotKey = reader.ReadUInt16(); // var pad2 = reader.ReadUInt16(); //} #if SHORT_MAP_VERTNOS var BFF_FMA_MESH_ID = 5; var BFF_FMA_MESH4_ID = 6; #else var BFF_FMA_MESH_ID = 1; var BFF_FMA_MESH4_ID = 4; #endif var id0 = reader.ReadByte(); var id1 = reader.ReadByte(); var id2 = reader.ReadByte(); var id3 = reader.ReadByte(); //4 or 1 if ((char)id0 != 'F' || (char)id1 != 'M' || (char)id2 != 'M' || id3 != BFF_FMA_MESH_ID && id3 != BFF_FMA_MESH4_ID) { return(null); } var models = new List <ModelEntity>(); // // Version 1 mesh headers include flat-poly information. Like what skies used to. //#define BFF_FMA_MESH_ID (('F'<<0) | ('M'<<8) | ('M'<<16) | (1<<24)) // //#define BFF_FMA_SKYMESH_ID (('F'<<0) | ('M'<<8) | ('S'<<16) | (0<<24)) //#define BFF_FMA_MESH4_ID (('F'<<0) | ('M'<<8) | ('M'<<16) | (4<<24)) var length = ReadInt(reader); var nameCrc = ReadLong(reader); var minX = ReadIntP(reader); var minY = ReadIntP(reader); var minZ = ReadIntP(reader); var maxX = ReadIntP(reader); var maxY = ReadIntP(reader); var maxZ = ReadIntP(reader); // //var offsetX = ReadIntP(reader); //var offsetY = ReadIntP(reader); //var offsetZ = ReadIntP(reader); //var rotX = ReadShort(reader); //var rotY = ReadShort(reader); //var rotZ = ReadShort(reader); //var rotW = ReadShort(reader); //var dummy1 = ReadShort(reader); //var dummy2 = ReadShort(reader); var polyListTop = ReadLong(reader); var dummy1 = ReadShort(reader); var dummy2 = ReadShort(reader); var radius = ReadInt(reader); var numVerts = ReadInt(reader); var vertsTop = ReadLong(reader); var position = reader.BaseStream.Position; //var offset = reader.BaseStream.Position - _offset; reader.BaseStream.Seek(_offset + vertsTop, SeekOrigin.Begin); // reader.BaseStream.Seek(288852, SeekOrigin.Begin); var vertices = new Vector3[numVerts]; var uvs = new Vector2[numVerts]; for (var i = 0; i < numVerts; i++) { var x = ReadShort(reader); var y = ReadShort(reader); var z = ReadShort(reader); var tu = reader.ReadByte(); var tv = reader.ReadByte(); vertices[i] = new Vector3(x, y, z); uvs[i] = new Vector2(tu, tv); } using (var writer = File.CreateText("C:\\USERS\\RICKO\\DESKTOP\\TEST" + nameCrc + ".OBJ")) { foreach (var vertex in vertices) { writer.WriteLine("v " + vertex.X + " " + vertex.Y + " " + vertex.Z); } } reader.BaseStream.Seek(position, SeekOrigin.Begin); var numGT3s = ReadInt(reader); var primsTop = ReadInt(reader); position = reader.BaseStream.Position; reader.BaseStream.Seek(_offset + primsTop, SeekOrigin.Begin); if (id3 == BFF_FMA_MESH_ID) { for (var i = 0; i < numGT3s; i++) //FMA_GT3 { var r0 = reader.ReadByte(); var g0 = reader.ReadByte(); var b0 = reader.ReadByte(); var code = reader.ReadByte(); var u0 = reader.ReadByte(); var v0 = reader.ReadByte(); var clut = ReadPadData(reader); var r1 = reader.ReadByte(); var g1 = reader.ReadByte(); var b1 = reader.ReadByte(); var pad1 = reader.ReadByte(); var u1 = reader.ReadByte(); var v1 = reader.ReadByte(); var tPage = ReadPadData(reader); var r2 = reader.ReadByte(); var g2 = reader.ReadByte(); var b2 = reader.ReadByte(); var pad2 = reader.ReadByte(); var u2 = reader.ReadByte(); var v2 = reader.ReadByte(); var pad3 = ReadPadData(reader); var vert0 = ReadIndex(reader); var vert1 = ReadIndex(reader); var vert2 = ReadIndex(reader); var triangle = TriangleFromPrimitive(vertices, vert0, vert1, vert2, r0, g0, b0, r1, g1, b1, r2, g2, b2, u0, v0, u1, v1, u2, v2); AddTriangle(triangle, tPage); } } else { var vert0 = ReadIndex(reader); var vert1 = ReadIndex(reader); var vert2 = ReadIndex(reader); var vert3 = ReadIndex(reader); var triangle1 = ReadPolyGT3(reader, vertices, vert0, vert1, vert2, out var tPage1); //var triangle2 = ReadPolyGT3(reader, vertices, vert1, vert3, vert2, out var tPage2); AddTriangle(triangle1, tPage1); //AddTriangle(triangle2, 0); } reader.BaseStream.Seek(position, SeekOrigin.Begin); var numGT4s = ReadInt(reader); primsTop = ReadInt(reader); position = reader.BaseStream.Position; reader.BaseStream.Seek(_offset + primsTop, SeekOrigin.Begin); if (id3 == BFF_FMA_MESH_ID) { for (var i = 0; i < numGT4s; i++) //FMA_GT4 { var r0 = reader.ReadByte(); var g0 = reader.ReadByte(); var b0 = reader.ReadByte(); var code = reader.ReadByte(); var u0 = reader.ReadByte(); var v0 = reader.ReadByte(); var clut = ReadPadData(reader); var r1 = reader.ReadByte(); var g1 = reader.ReadByte(); var b1 = reader.ReadByte(); var pad1 = reader.ReadByte(); var u1 = reader.ReadByte(); var v1 = reader.ReadByte(); var tPage = ReadPadData(reader); var r2 = reader.ReadByte(); var g2 = reader.ReadByte(); var b2 = reader.ReadByte(); var pad2 = reader.ReadByte(); var u2 = reader.ReadByte(); var v2 = reader.ReadByte(); var pad3 = ReadPadData(reader); var r3 = reader.ReadByte(); var g3 = reader.ReadByte(); var b3 = reader.ReadByte(); var pad4 = reader.ReadByte(); var u3 = reader.ReadByte(); var v3 = reader.ReadByte(); var pad5 = ReadPadData(reader); var vert0 = ReadIndex(reader); var vert1 = ReadIndex(reader); var vert2 = ReadIndex(reader); var vert3 = ReadIndex(reader); var triangle1 = TriangleFromPrimitive(vertices, vert0, vert1, vert2, r0, g0, b0, r1, g1, b1, r2, g2, b2, u0, v0, u1, v1, u2, v2); var triangle2 = TriangleFromPrimitive(vertices, vert1, vert3, vert2, r1, g1, b1, r3, g3, b3, r2, g2, b2, u1, v1, u3, v3, u2, v2); AddTriangle(triangle1, tPage); AddTriangle(triangle2, tPage); } } else { var vert0 = ReadIndex(reader); var vert1 = ReadIndex(reader); var vert2 = ReadIndex(reader); var vert3 = ReadIndex(reader); //two POLY_GT3 var triangle1 = ReadPolyGT3(reader, vertices, vert0, vert1, vert2, out var tPage1); var triangle2 = ReadPolyGT3(reader, vertices, vert1, vert3, vert2, out var tPage2); AddTriangle(triangle1, tPage1); AddTriangle(triangle2, tPage2); } reader.BaseStream.Seek(position, SeekOrigin.Begin); var numTMaps = ReadInt(reader); var tMapsTop = ReadLong(reader); var numG3s = ReadInt(reader); primsTop = ReadInt(reader); position = reader.BaseStream.Position; reader.BaseStream.Seek(_offset + primsTop, SeekOrigin.Begin); for (var i = 0; i < numG3s; i++) //FMA_G3 { var r0 = reader.ReadByte(); var g0 = reader.ReadByte(); var b0 = reader.ReadByte(); var code = reader.ReadByte(); var r1 = reader.ReadByte(); var g1 = reader.ReadByte(); var b1 = reader.ReadByte(); var pad1 = reader.ReadByte(); var r2 = reader.ReadByte(); var g2 = reader.ReadByte(); var b2 = reader.ReadByte(); var pad2 = reader.ReadByte(); var vert0 = ReadIndex(reader); var vert1 = ReadIndex(reader); var vert2 = ReadIndex(reader); var triangle = TriangleFromPrimitive(vertices, vert0, vert1, vert2, r0, g0, b0, r1, g1, b1, r2, g2, b2, 0, 0, 0, 0, 0, 0); AddTriangle(triangle, 0); } reader.BaseStream.Seek(position, SeekOrigin.Begin); var numG4s = ReadInt(reader); primsTop = ReadInt(reader); position = reader.BaseStream.Position; reader.BaseStream.Seek(_offset + primsTop, SeekOrigin.Begin); for (var i = 0; i < numG4s; i++) //FMA_G4 { var r0 = reader.ReadByte(); var g0 = reader.ReadByte(); var b0 = reader.ReadByte(); var code = reader.ReadByte(); var r1 = reader.ReadByte(); var g1 = reader.ReadByte(); var b1 = reader.ReadByte(); var pad1 = reader.ReadByte(); var r2 = reader.ReadByte(); var g2 = reader.ReadByte(); var b2 = reader.ReadByte(); var pad2 = reader.ReadByte(); var r3 = reader.ReadByte(); var g3 = reader.ReadByte(); var b3 = reader.ReadByte(); var pad3 = reader.ReadByte(); var vert0 = ReadIndex(reader); var vert1 = ReadIndex(reader); var vert2 = ReadIndex(reader); var vert3 = ReadIndex(reader); var triangle1 = TriangleFromPrimitive(vertices, vert0, vert1, vert2, r0, g0, b0, r1, g1, b1, r2, g2, b2, 0, 0, 0, 0, 0, 0); var triangle2 = TriangleFromPrimitive(vertices, vert1, vert3, vert2, r1, g1, b1, r3, g3, b3, r2, g2, b2, 0, 0, 0, 0, 0, 0); AddTriangle(triangle1, 0); AddTriangle(triangle2, 0); } reader.BaseStream.Seek(position, SeekOrigin.Begin); foreach (var kvp in groupedTriangles) { var triangles = kvp.Value; if (triangles.Count > 0) { var model = new ModelEntity { Triangles = triangles.ToArray(), TexturePage = kvp.Key, TMDID = 0 }; models.Add(model); } } if (models.Count > 0) { var entity = new RootEntity(); foreach (var model in models) { model.ParentEntity = entity; } entity.ChildEntities = models.ToArray(); entity.ComputeBounds(); return(entity); } return(null); }
private static RootEntity ReadModels(BinaryReader reader) { void AddTriangle(Dictionary <Tuple <uint, uint>, List <Triangle> > groupedTriangles, Triangle triangle, uint modelIndex, uint tPage) { var tuple = new Tuple <uint, uint>(modelIndex, tPage); List <Triangle> triangles; if (groupedTriangles.ContainsKey(tuple)) { triangles = groupedTriangles[tuple]; } else { triangles = new List <Triangle>(); groupedTriangles.Add(tuple, triangles); } triangles.Add(triangle); } var version = reader.ReadByte(); var magic2 = reader.ReadByte(); var magic3 = reader.ReadByte(); var magic4 = reader.ReadByte(); if (version != 0x04 && version != 0x03 && version != 0x06) { return(null); } if (magic2 != 0x00 || magic3 != 0x02 || magic4 != 0x00) { return(null); } var metaPtr = reader.ReadUInt32(); //todo: read meta var objectCount = reader.ReadUInt32(); if (objectCount == 0 || objectCount > Program.MaxPSXObjectCount) { return(null); } var childEntities = new ModelEntity(); var objectModels = new PSXModel[objectCount]; for (var i = 0; i < objectCount; i++) { var flags = reader.ReadUInt32(); var x = (reader.ReadInt32() / 4096f) / 2.25f; // 4096f; var y = (reader.ReadInt32() / 4096f) / 2.25f; // 4096f; var z = (reader.ReadInt32() / 4096f) / 2.25f; // 4096f; var unk1 = reader.ReadUInt32(); var unk2 = reader.ReadUInt16(); var modelIndex = reader.ReadUInt16(); var tx = reader.ReadUInt16(); var ty = reader.ReadUInt16(); var unk3 = reader.ReadUInt32(); var palTop = reader.ReadUInt32(); objectModels[i] = new PSXModel(x, y, z, modelIndex); } var modelCount = reader.ReadUInt32(); if (modelCount == 0 || modelCount > Program.MaxPSXObjectCount) { return(null); } var triangleGroups = new Dictionary <Tuple <uint, uint>, List <Triangle> >(); var modelEntities = new List <ModelEntity>(); var attachmentIndex = 0; for (uint i = 0; i < modelCount; i++) { var modelTop = reader.ReadUInt32(); var modelPosition = reader.BaseStream.Position; reader.BaseStream.Seek(modelTop, SeekOrigin.Begin); var flags = version == 0x04 ? reader.ReadUInt16() : reader.ReadUInt32(); var vertexCount = version == 0x04 ? reader.ReadUInt16() : reader.ReadUInt32(); var planeCount = version == 0x04 ? reader.ReadUInt16() : reader.ReadUInt32(); var faceCount = version == 0x04 ? reader.ReadUInt16() : reader.ReadUInt32(); var radius = reader.ReadUInt32(); var xMax = reader.ReadUInt16(); var xMin = reader.ReadUInt16(); var yMax = reader.ReadUInt16(); var yMin = reader.ReadUInt16(); var zMax = reader.ReadUInt16(); var zMin = reader.ReadUInt16(); if (version == 0x04) { var unk2 = reader.ReadUInt32(); } var attachedIndices = new Dictionary <uint, uint>(); var attachableIndices = new Dictionary <uint, uint>(); var vertices = new Vector3[vertexCount]; for (uint j = 0; j < vertexCount; j++) { var x = reader.ReadInt16(); //reader.ReadInt16() / 1f) / 2.25f; var y = reader.ReadInt16(); //reader.ReadInt16() / 1f) / 2.25f; var z = reader.ReadInt16(); //(reader.ReadInt16() / 1f) / 2.25f; var pad = reader.ReadInt16(); var vertex = new Vector3( x / 1f / 2.25f, y / 1f / 2.25f, z / 1f / 2.25f ); if (pad == 1) { attachableIndices.Add(j, (uint)attachmentIndex++); } else if (pad == 2) { attachedIndices.Add(j, (uint)y); } vertices[j] = vertex; } var normals = new Vector3[planeCount]; for (uint j = 0; j < planeCount; j++) { var x = reader.ReadInt16() / 4096f; var y = reader.ReadInt16() / 4096f; var z = reader.ReadInt16() / 4096f; reader.ReadInt16(); normals[j] = new Vector3( x, y, z ); } //uint faceFlags; //uint faceLength; //if (version == 0x03) //{ // faceFlags = reader.ReadUInt16(); // faceLength = reader.ReadUInt16(); //} //else //{ // faceFlags = 0; // faceLength = 0; //} for (uint j = 0; j < faceCount; j++) { if (version == 0x04) { var faceBegin = reader.BaseStream.Position; var faceFlags = reader.ReadUInt16(); var faceLength = reader.ReadUInt16(); var triangle = (faceFlags & 0x0010) != 0; var gouraud = (faceFlags & 0x0800) != 0; var textured = (faceFlags & 0x0003) != 0; var invisible = (faceFlags & 0x0080) != 0; var i0 = reader.ReadByte(); var i1 = reader.ReadByte(); var i2 = reader.ReadByte(); var i3 = reader.ReadByte(); var vertex0 = vertices[i0]; var vertex1 = vertices[i1]; var vertex2 = vertices[i2]; var vertex3 = vertices[i3]; Color color0; Color color1; Color color2; Color color3; var r0 = reader.ReadByte() / 255f; var g0 = reader.ReadByte() / 255f; var b0 = reader.ReadByte() / 255f; var command = reader.ReadByte(); var attachedIndex0 = attachedIndices.TryGetValue(i0, out var index0) ? index0 : uint.MaxValue; var attachedIndex1 = attachedIndices.TryGetValue(i1, out var index1) ? index1 : uint.MaxValue; var attachedIndex2 = attachedIndices.TryGetValue(i2, out var index2) ? index2 : uint.MaxValue; var attachedIndex3 = attachedIndices.TryGetValue(i3, out var index3) ? index3 : uint.MaxValue; var attachableIndex0 = attachableIndices.TryGetValue(i0, out var attIndex0) ? attIndex0 : uint.MaxValue; var attachableIndex1 = attachableIndices.TryGetValue(i1, out var attIndex1) ? attIndex1 : uint.MaxValue; var attachableIndex2 = attachableIndices.TryGetValue(i2, out var attIndex2) ? attIndex2 : uint.MaxValue; var attachableIndex3 = attachableIndices.TryGetValue(i3, out var attIndex3) ? attIndex3 : uint.MaxValue; if (gouraud) { color0 = color1 = color2 = color3 = Color.Grey; //todo } else { color0 = color1 = color2 = color3 = new Color(r0, g0, b0); } //todo var planeIndex = reader.ReadUInt16(); var surfFlags = reader.ReadInt16(); var normal0 = normals[planeIndex]; var normal1 = normals[planeIndex]; var normal2 = normals[planeIndex]; var normal3 = normals[planeIndex]; var uv0 = Vector3.Zero; var uv1 = Vector3.Zero; var uv2 = Vector3.Zero; var uv3 = Vector3.Zero; uint tPage = 0; if (textured) { tPage = reader.ReadUInt32(); //todo var u0 = reader.ReadByte() / 255f; var v0 = reader.ReadByte() / 255f; var u1 = reader.ReadByte() / 255f; var v1 = reader.ReadByte() / 255f; var u2 = reader.ReadByte() / 255f; var v2 = reader.ReadByte() / 255f; var u3 = reader.ReadByte() / 255f; var v3 = reader.ReadByte() / 255f; uv0 = new Vector3(u0, v0, 0f); uv1 = new Vector3(u1, v1, 0f); uv2 = new Vector3(u2, v2, 0f); uv3 = new Vector3(u3, v3, 0f); } if (!invisible) { AddTriangle(triangleGroups, new Triangle { Vertices = new[] { vertex2, vertex1, vertex0 }, Normals = new[] { normal2, normal1, normal0 }, Uv = new[] { uv2, uv1, uv0 }, Colors = new[] { color2, color1, color0 }, OriginalVertexIndices = new uint[] { i2, i1, i0 }, AttachedIndices = new[] { attachedIndex2, attachedIndex1, attachedIndex0 }, AttachableIndices = new[] { attachableIndex2, attachableIndex1, attachableIndex0 } }, i, tPage); if (!triangle) { AddTriangle(triangleGroups, new Triangle { Vertices = new[] { vertex1, vertex2, vertex3 }, Normals = new[] { normal1, normal2, normal3 }, Uv = new[] { uv1, uv2, uv3 }, Colors = new[] { color1, color2, color3 }, OriginalVertexIndices = new uint[] { i1, i2, i3 }, AttachedIndices = new[] { attachedIndex1, attachedIndex2, attachedIndex3 }, AttachableIndices = new[] { attachableIndex1, attachableIndex2, attachableIndex3 } }, i, tPage); } } reader.BaseStream.Seek(faceBegin + faceLength, SeekOrigin.Begin); } else { var faceBegin = reader.BaseStream.Position; var faceFlags = reader.ReadUInt16(); var faceLength = reader.ReadUInt16(); var triangle = (faceFlags & 0x0010) != 0; var gouraud = (faceFlags & 0x0800) != 0; var textured = (faceFlags & 0x0003) != 0; var invisible = (faceFlags & 0x0080) != 0; var i0 = reader.ReadUInt16(); var i1 = reader.ReadUInt16(); var i2 = reader.ReadUInt16(); var i3 = reader.ReadUInt16(); var vertex0 = vertices[i0]; var vertex1 = vertices[i1]; var vertex2 = vertices[i2]; var vertex3 = vertices[i3]; Color color0; Color color1; Color color2; Color color3; var r0 = reader.ReadByte() / 255f; var g0 = reader.ReadByte() / 255f; var b0 = reader.ReadByte() / 255f; var command = reader.ReadByte(); var attachedIndex0 = attachedIndices.TryGetValue(i0, out var index0) ? index0 : uint.MaxValue; var attachedIndex1 = attachedIndices.TryGetValue(i1, out var index1) ? index1 : uint.MaxValue; var attachedIndex2 = attachedIndices.TryGetValue(i2, out var index2) ? index2 : uint.MaxValue; var attachedIndex3 = attachedIndices.TryGetValue(i3, out var index3) ? index3 : uint.MaxValue; var attachableIndex0 = attachableIndices.TryGetValue(i0, out var attIndex0) ? attIndex0 : uint.MaxValue; var attachableIndex1 = attachableIndices.TryGetValue(i1, out var attIndex1) ? attIndex1 : uint.MaxValue; var attachableIndex2 = attachableIndices.TryGetValue(i2, out var attIndex2) ? attIndex2 : uint.MaxValue; var attachableIndex3 = attachableIndices.TryGetValue(i3, out var attIndex3) ? attIndex3 : uint.MaxValue; if (gouraud) { color0 = color1 = color2 = color3 = Color.Grey; //todo } else { color0 = color1 = color2 = color3 = new Color(r0, g0, b0); } //todo var planeIndex = reader.ReadUInt16(); var surfFlags = reader.ReadInt16(); var normal0 = normals[planeIndex]; var normal1 = normals[planeIndex]; var normal2 = normals[planeIndex]; var normal3 = normals[planeIndex]; var uv0 = Vector3.Zero; var uv1 = Vector3.Zero; var uv2 = Vector3.Zero; var uv3 = Vector3.Zero; uint tPage = 0; if (textured) { tPage = reader.ReadUInt32(); //todo var u0 = reader.ReadByte() / 255f; var v0 = reader.ReadByte() / 255f; var u1 = reader.ReadByte() / 255f; var v1 = reader.ReadByte() / 255f; var u2 = reader.ReadByte() / 255f; var v2 = reader.ReadByte() / 255f; var u3 = reader.ReadByte() / 255f; var v3 = reader.ReadByte() / 255f; uv0 = new Vector3(u0, v0, 0f); uv1 = new Vector3(u1, v1, 0f); uv2 = new Vector3(u2, v2, 0f); uv3 = new Vector3(u3, v3, 0f); } if (!invisible) { AddTriangle(triangleGroups, new Triangle { Vertices = new[] { vertex2, vertex1, vertex0 }, Normals = new[] { normal2, normal1, normal0 }, Uv = new[] { uv2, uv1, uv0 }, Colors = new[] { color2, color1, color0 }, OriginalVertexIndices = new uint[] { i2, i1, i0 }, AttachedIndices = new[] { attachedIndex2, attachedIndex1, attachedIndex0 }, AttachableIndices = new[] { attachableIndex2, attachableIndex1, attachableIndex0 } }, i, tPage); if (!triangle) { AddTriangle(triangleGroups, new Triangle { Vertices = new[] { vertex1, vertex2, vertex3 }, Normals = new[] { normal1, normal2, normal3 }, Uv = new[] { uv1, uv2, uv3 }, Colors = new[] { color1, color2, color3 }, OriginalVertexIndices = new uint[] { i1, i2, i3 }, AttachedIndices = new[] { attachedIndex1, attachedIndex2, attachedIndex3 }, AttachableIndices = new[] { attachableIndex1, attachableIndex2, attachableIndex3 } }, i, tPage); } } reader.BaseStream.Seek(faceBegin + faceLength, SeekOrigin.Begin); } } reader.BaseStream.Seek(modelPosition, SeekOrigin.Begin); } //var position = reader.BaseStream.Position; //reader.BaseStream.Seek(metaPtr, SeekOrigin.Begin); //for (; ; ) //{ // var chunkId = reader.ReadBytes(4); // if (chunkId[0] == 0xFF && chunkId[1] == 0xFF && chunkId[2] == 0xFF && chunkId[3] == 0xFF) // { // break; // } // var chunkString = Encoding.ASCII.GetString(chunkId); // var chunkLength = reader.ReadUInt32(); // var chunkData = reader.ReadBytes((int)chunkLength); //}; //reader.BaseStream.Seek(position, SeekOrigin.Begin); foreach (var psxModel in objectModels) { foreach (var kvp in triangleGroups) { if (kvp.Key.Item1 == psxModel.ModelIndex) { var triangles = kvp.Value; var model = new ModelEntity { Triangles = triangles.ToArray(), TexturePage = kvp.Key.Item2, TMDID = 1, //todo LocalMatrix = Matrix4.CreateTranslation(psxModel.X, psxModel.Y, psxModel.Z) }; modelEntities.Add(model); } } } RootEntity rootEntity; if (modelEntities.Count > 0) { rootEntity = new RootEntity(); foreach (var modelEntity in modelEntities) { modelEntity.ParentEntity = rootEntity; } rootEntity.ChildEntities = modelEntities.ToArray(); rootEntity.ComputeBounds(); } else { rootEntity = null; } return(rootEntity); }
public bool SetupAnimationFrame(float frameIndex, RootEntity[] checkedEntities, RootEntity selectedRootEntity, ModelEntity selectedModelEntity, bool updateMeshData = false) { _scene.SkeletonBatch.Reset(); RootEntity rootEntity = null; if (selectedRootEntity != null) { rootEntity = selectedRootEntity; } else if (selectedModelEntity != null) { rootEntity = selectedModelEntity.GetRootEntity(); } _scene.MeshBatch.SetupMultipleEntityBatch(checkedEntities, selectedModelEntity, selectedRootEntity, _scene.TextureBinder, updateMeshData || _scene.AutoAttach, false, true); return(ProcessAnimationObject(_animation.RootAnimationObject, frameIndex, rootEntity, Matrix4.Identity)); }