// Methods public override void Load(Stream fileStream) { // Header var reader = new GensReader(fileStream, true); Header = new GensHeader(reader); // Root Node uint lightType = reader.ReadUInt32(); if (lightType < 0 || lightType > 1) { throw new InvalidDataException( $"Cannot read light - unknown light type! ({lightType})"); } // Data LightType = (LightTypes)lightType; Position = reader.ReadVector3(); Color = reader.ReadVector3(); if (LightType == LightTypes.Omni) { UnknownTotal1 = reader.ReadUInt32(); UnknownTotal2 = reader.ReadUInt32(); UnknownTotal3 = reader.ReadUInt32(); OmniInnerRange = reader.ReadSingle(); OmniOuterRange = reader.ReadSingle(); } }
// Methods public override void Load(Stream fileStream) { // Header var reader = new GensReader(fileStream); Header = new GensHeader(reader); // Root Node uint modelFileNameOffset = reader.ReadUInt32(); uint matrixOffset = reader.ReadUInt32(); uint fileNameOffset = reader.ReadUInt32(); uint instanceTotal = reader.ReadUInt32(); uint fileNameOffsetEnd = reader.ReadUInt32(); // File Name reader.JumpTo(fileNameOffset, false); FileName = reader.ReadNullTerminatedString(); // Matrix reader.JumpTo(matrixOffset, false); for (int x = 0; x < 4; ++x) { for (int y = 0; y < 4; ++y) { matrix[x, y] = reader.ReadSingle(); } } // Model File Name reader.JumpTo(modelFileNameOffset, false); ModelFileName = reader.ReadNullTerminatedString(); // Mesh "Loaders" (what?) // TODO }
public override void Load(Stream fileStream) { var reader = new GensReader(fileStream); Header = new GensHeader(reader); uint textureCount = reader.ReadUInt32(); uint texturesOffset = reader.ReadUInt32(); reader.JumpTo(texturesOffset, false); Read(reader, textureCount); }
// Methods public unsafe void Read(GensReader reader, float *data, float scale = 1) { switch ((DataTypes)Type) { case DataTypes.Vector2: *data = reader.ReadSingle() * scale; *++data = reader.ReadSingle() * scale; break; case DataTypes.Vector2_Half: *data = reader.ReadHalf(); *++data = reader.ReadHalf(); break; case DataTypes.Vector3: *data = reader.ReadSingle() * scale; *++data = reader.ReadSingle() * scale; *++data = reader.ReadSingle() * scale; break; case DataTypes.Vector3_360: // TODO: Read this properly reader.ReadUInt32(); break; case DataTypes.Vector3_Forces: // TODO: Read this properly reader.ReadUInt32(); break; case DataTypes.Vector4: *data = reader.ReadSingle() * scale; *++data = reader.ReadSingle() * scale; *++data = reader.ReadSingle() * scale; *++data = reader.ReadSingle() * scale; break; case DataTypes.Vector4_Byte: case DataTypes.Indices: // TODO: Read this properly reader.ReadUInt32(); break; case DataTypes.Indices_Byte: // TODO: Read this properly reader.ReadUInt32(); break; } }
// Methods public override void Load(Stream fileStream) { // Header var reader = new GensReader(fileStream, true); Header = new GensHeader(reader); // Root Node uint instanceInfoCount = reader.ReadUInt32(); uint instanceInfoOffsetsOffset = reader.ReadUInt32(); uint terrainModelCount = reader.ReadUInt32(); uint terrainModelOffsetsOffset = reader.ReadUInt32(); // Instance Infos InstanceInfos = new InstanceInfoEntry[instanceInfoCount]; reader.JumpTo(instanceInfoOffsetsOffset, false); for (uint i = 0; i < instanceInfoCount; ++i) { var instanceInfo = new InstanceInfoEntry(); uint instanceInfoOffset = reader.ReadUInt32(); long curPos = reader.BaseStream.Position; reader.JumpTo(instanceInfoOffset, false); uint fileNameCount = reader.ReadUInt32(); uint fileNameOffsetsOffset = reader.ReadUInt32(); uint boundingSphereOffset = reader.ReadUInt32(); reader.JumpTo(fileNameOffsetsOffset, false); // File Names instanceInfo.FileNames = new string[fileNameCount]; for (uint i2 = 0; i2 < fileNameCount; ++i2) { instanceInfo.FileNames[i2] = reader.GetString(); } // Bounding Sphere reader.JumpTo(boundingSphereOffset, false); instanceInfo.BoundingSphereCenter = reader.ReadVector3(); instanceInfo.BoundingSphereRadius = reader.ReadSingle(); InstanceInfos[i] = instanceInfo; reader.BaseStream.Position = curPos; } // Terrain Models TerrainModels = new string[terrainModelCount]; reader.JumpTo(terrainModelOffsetsOffset, false); for (uint i = 0; i < terrainModelCount; ++i) { TerrainModels[i] = reader.GetString(); } }
// Methods public override void Load(Stream fileStream) { // Header var reader = new GensReader(fileStream, true); Header = new GensHeader(reader); // Root Node uint lightTotal = reader.ReadUInt32(); uint lightTableOffset = reader.ReadUInt32(); // Data reader.JumpTo(lightTableOffset, false); for (uint i = 0; i < lightTotal; ++i) { LightNames.Add(reader.GetString()); } }
public virtual void Load(Stream fileStream, bool isTerrain, float scale = 1) { // Header var reader = new GensReader(fileStream); Header = reader.ReadHeader(); // Data uint meshCount = reader.ReadUInt32(); uint meshOffsetsOffset = reader.ReadUInt32(); if (isTerrain) { uint modelNameOffset = reader.ReadUInt32(); // TODO: Use this uint modelFlag = reader.ReadUInt32(); // TODO: Use this } else { // TODO: Read the skeleton } // Mesh Offsets var meshOffsets = new uint[meshCount]; reader.JumpTo(meshOffsetsOffset, false); for (uint i = 0; i < meshCount; ++i) { meshOffsets[i] = reader.ReadUInt32(); } // Meshes for (uint i = 0; i < meshCount; ++i) { reader.JumpTo(meshOffsets[i], false); ReadMesh(reader, scale); } }
protected void ReadMesh(GensReader reader, float scale = 1) { // SubMesh Slots uint curPos = (uint)reader.BaseStream.Position; for (int i = 0; i < SubMeshSlotCount;) { uint subMeshCount = reader.ReadUInt32(); uint subMeshOffsetsOffset = reader.ReadUInt32(); // TODO: Add support for water SubMesh if (i == SubMeshSlotCount - 1) { break; } // SubMesh Offsets var subMeshOffsets = new uint[subMeshCount]; reader.JumpTo(subMeshOffsetsOffset, false); for (uint i2 = 0; i2 < subMeshCount; ++i2) { subMeshOffsets[i2] = reader.ReadUInt32(); } // SubMeshes for (uint i2 = 0; i2 < subMeshCount; ++i2) { reader.JumpTo(subMeshOffsets[i2], false); var m = ReadSubMesh(reader, scale); m.Slot = (Mesh.Slots)i; } reader.JumpTo(curPos + (++i * 8)); } }
public override void Load(Stream fileStream) { var reader = new GensReader(fileStream); Header = new GensHeader(reader); // Root Node uint entryCount = reader.ReadUInt32(); uint entriesOffset = reader.ReadUInt32(); // AR Entry Offsets var entryOffsets = new uint[entryCount]; reader.JumpTo(entriesOffset, false); for (uint i = 0; i < entryCount; ++i) { entryOffsets[i] = reader.ReadUInt32(); } // AR Entries for (uint i = 0; i < entryCount; ++i) { reader.JumpTo(entryOffsets[i], false); uint nameOffset = reader.ReadUInt32(); uint offset = reader.ReadUInt32(); uint size = reader.ReadUInt32(); reader.JumpTo(nameOffset, false); Entries.Add(new AREntry() { PFDOffset = offset, Size = size, Name = reader.ReadNullTerminatedString() }); } }
// Methods public override void Load(Stream fileStream) { // Header var reader = new GensReader(fileStream); Header = new GensHeader(reader); // Root Node uint groupCount = reader.ReadUInt32(); uint groupOffsetsOffset = reader.ReadUInt32(); GroupEntries = new TerrainGroupEntry[groupCount]; // Group Offsets var groupOffsets = new uint[groupCount]; reader.JumpTo(groupOffsetsOffset, false); for (uint i = 0; i < groupCount; ++i) { groupOffsets[i] = reader.ReadUInt32(); } // Groups for (uint i = 0; i < groupCount; ++i) { var group = new TerrainGroupEntry(); reader.JumpTo(groupOffsets[i], false); // Entry uint centerPosOffset = reader.ReadUInt32(); uint fileNameOffset = reader.ReadUInt32(); group.UncompressedGroupSize = reader.ReadUInt32(); uint sphereCount = reader.ReadUInt32(); uint sphereOffsetsOffset = reader.ReadUInt32(); group.SubsetID = reader.ReadUInt32(); // Center position reader.JumpTo(centerPosOffset, false); group.CenterPosition = reader.ReadVector3(); group.CenterRadius = reader.ReadSingle(); // FileName reader.JumpTo(fileNameOffset, false); group.FileName = reader.ReadNullTerminatedString(); // Sphere Offsets var sphereOffsets = new uint[sphereCount]; reader.JumpTo(sphereOffsetsOffset, false); for (uint i2 = 0; i2 < sphereCount; ++i2) { sphereOffsets[i2] = reader.ReadUInt32(); } // Spheres var spheres = new TerrainSphere[sphereCount]; for (uint i2 = 0; i2 < sphereCount; ++i2) { reader.JumpTo(sphereOffsets[i2], false); spheres[i2] = new TerrainSphere() { Center = reader.ReadVector3(), CenterRadius = reader.ReadSingle() }; } group.Spheres = spheres; GroupEntries[i] = group; } }
protected virtual string Read(Stream fileStream, bool readAdditionalString = false) { // Header var reader = new GensReader(fileStream); Header.Read(reader); uint metaDataOffset = reader.ReadUInt32(); uint metaAnimsSize = reader.ReadUInt32(); uint keyframesOffset = reader.ReadUInt32(); uint keyframesSize = reader.ReadUInt32(); uint stringTableOffset = reader.ReadUInt32(); uint stringTableSize = reader.ReadUInt32(); // MetaData reader.JumpTo(metaDataOffset, false); uint materialNameOffset = reader.ReadUInt32(); uint additionalStringOffset = (readAdditionalString) ? reader.ReadUInt32() : 0; uint animCount = reader.ReadUInt32(); var animOffsets = new uint[animCount]; for (uint i = 0; i < animCount; ++i) { animOffsets[i] = reader.ReadUInt32(); } // Animations for (uint i = 0; i < animCount; ++i) { reader.JumpTo(animOffsets[i], false); Animations.Add(new Animation(reader)); } // Keyframes foreach (var anim in Animations) { foreach (var set in anim.KeyframeSets) { set.ReadKeyframes(reader, keyframesOffset); } } // String Table name = ReadString(materialNameOffset); string additionalString = (readAdditionalString) ? ReadString(additionalStringOffset) : null; foreach (var anim in Animations) { anim.BlendType = ReadString(anim.BlendTypeOffset); } return(additionalString); // Sub-Methods string ReadString(uint off) { reader.JumpTo(stringTableOffset + off, false); return(reader.ReadNullTerminatedString()); } }
protected unsafe Mesh ReadSubMesh(GensReader reader, float scale = 1) { uint offset; // Generic uint reused for different data // Offsets uint materialNameOffset, faceCount, faceOffset, vertexCount, vertexSize, vertexOffset, vertexFormatOffset, boneCount, boneOffset, textureUnitCount, textureUnitOffsetsOffset; if (Header.RootNodeType == PS3RootType) { uint unknownOffset1 = reader.ReadUInt32(); // VertexFormat? materialNameOffset = reader.ReadUInt32(); boneCount = reader.ReadUInt32(); boneOffset = reader.ReadUInt32(); // ? textureUnitCount = reader.ReadUInt32(); textureUnitOffsetsOffset = reader.ReadUInt32(); // Possibly vertex format? reader.JumpTo(unknownOffset1, false); int unknown1 = reader.ReadInt32(); int unknown2 = reader.ReadInt32(); int unknown3 = reader.ReadInt32(); int unknown4 = reader.ReadInt32(); uint unknownOffset2 = reader.ReadUInt32(); uint unknownCount1 = reader.ReadUInt32(); vertexOffset = reader.ReadUInt32(); // TODO throw new NotImplementedException( "ERROR: Cannot yet read PS3 terrain-models"); } else { materialNameOffset = reader.ReadUInt32(); faceCount = reader.ReadUInt32(); faceOffset = reader.ReadUInt32(); vertexCount = reader.ReadUInt32(); vertexSize = reader.ReadUInt32(); vertexOffset = reader.ReadUInt32(); vertexFormatOffset = reader.ReadUInt32(); boneCount = reader.ReadUInt32(); boneOffset = reader.ReadUInt32(); textureUnitCount = reader.ReadUInt32(); textureUnitOffsetsOffset = reader.ReadUInt32(); } // Faces var faces = new ushort[faceCount]; reader.JumpTo(faceOffset, false); // Convert faces from triangle strips // Basically taken from LibGens because I honestly // don't think there's another way to do it lol int newStrip = 3, newIndex = 0; ushort face1 = 0, face2 = 0, face3 = 0, t; uint count = 0, faceIndex = 0; // HACK: We go through the whole loop twice, the first time just // to get the new faceCount, second time to actually get the faces. // This way we don't have to do any copying (yes, lists do it too) // which is a huge performance improvement. for (uint i = 0; i < faceCount; ++i) { t = reader.ReadUInt16(); faces[i] = t; if (t == 0xFFFF) { newStrip = 3; newIndex = 0; } else { newStrip -= 1; face3 = face2; face2 = face1; face1 = t; if (newStrip == 0) { if ((face1 != face2) && (face2 != face3) && (face1 != face3)) { count += 3; } newStrip = 1; ++newIndex; } } } // Alright, we've got the new count! // Time to actually get the faces. var newFaces = new uint[count]; newStrip = 3; newIndex = 0; face1 = face2 = face3 = 0; for (uint i = 0; i < faceCount; ++i) { t = faces[i]; if (t == 0xFFFF) { newStrip = 3; newIndex = 0; } else { newStrip -= 1; face3 = face2; face2 = face1; face1 = t; if (newStrip == 0) { if ((face1 != face2) && (face2 != face3) && (face1 != face3)) { if ((newIndex % 2) == 0) { newFaces[faceIndex] = face1; newFaces[++faceIndex] = face2; newFaces[++faceIndex] = face3; } else { newFaces[faceIndex] = face3; newFaces[++faceIndex] = face2; newFaces[++faceIndex] = face1; } ++faceIndex; } newStrip = 1; ++newIndex; } } } // Vertex Format var vertexFormat = new List <VertexFormatElement>(); var fs = reader.BaseStream; reader.JumpTo(vertexFormatOffset, false); for (byte i = 0; i < 0xFF; ++i) { offset = reader.ReadUInt32(); if (offset > 1000) { break; } var element = new VertexFormatElement() { Offset = offset, Type = reader.ReadUInt32(), ID = reader.ReadUInt16(), Index = reader.ReadByte() }; vertexFormat.Add(element); fs.ReadByte(); } // Vertices var data = new float[vertexCount * Mesh.StructureLength]; var idc = new float[vertexCount * 4]; // TODO: Care // HACK: Read this stuff using pointers to avoid boundry checks. fixed(float *dataStart = data) fixed(float *idcp = idc) { float *dp; // Pointer to data uint structStart; for (uint i = 0; i < vertexCount; ++i) { // Set default vertex coloring structStart = (i * Mesh.StructureLength); dp = dataStart + structStart + Mesh.ColorPos; // RGBA = 1, 1, 1, 1 *dp = 1; *++dp = 1; *++dp = 1; *++dp = 1; // Just to be accurate offset = (vertexOffset + (i * vertexSize)); foreach (var element in vertexFormat) { reader.JumpTo(offset + element.Offset, false); switch (element.ID) { // Vertex Positions case 0: element.Read(reader, dataStart + structStart + Mesh.VertPos, scale); break; // Bone Weights case 1: // TODO element.Read(reader, idcp); break; // Bone Indices case 2: // TODO element.Read(reader, idcp); break; // Normals case 3: // TODO: Do I need to scale normals? element.Read(reader, dataStart + structStart + Mesh.NormPos); break; // UV Coordinates case 5: if (element.Index < 1) { element.Read(reader, dataStart + structStart + Mesh.UVPos); } else { // TODO: Read multi-UV Channels element.Read(reader, idcp); } break; // Tangents case 6: // TODO element.Read(reader, idcp); break; // Binormals case 7: // TODO element.Read(reader, idcp); break; // Vertex Colors case 10: element.Read(reader, dataStart + structStart + Mesh.ColorPos); break; } } ++dp; } } // Bones reader.JumpTo(boneOffset, false); var bones = reader.ReadBytes((int)boneCount); // Texture Unit Offsets var textureUnitOffsets = new uint[textureUnitCount]; reader.JumpTo(textureUnitOffsetsOffset, false); for (uint i = 0; i < textureUnitCount; ++i) { textureUnitOffsets[i] = reader.ReadUInt32(); } // Texture Units for (uint i = 0; i < textureUnitCount; ++i) { // TODO: Actually use this data reader.JumpTo(textureUnitOffsets[i], false); uint textureUnitNameOffset = reader.ReadUInt32(); uint textureUnitID = reader.ReadUInt32(); // Texture Unit Name reader.JumpTo(textureUnitNameOffset, false); string textureUnitName = reader.ReadNullTerminatedString(); } // Material Name reader.JumpTo(materialNameOffset, false); string materialName = reader.ReadNullTerminatedString(); // Generate a HedgeLib mesh and add it to the array var mesh = new Mesh() { VertexData = data, Triangles = newFaces, MaterialName = materialName }; Meshes.Add(mesh); return(mesh); }
public override void Load(Stream fileStream) { // Header var reader = new GensReader(fileStream); Header = reader.ReadHeader(); // Root Node uint shaderOffset = reader.ReadUInt32(); uint subShaderOffset = reader.ReadUInt32(); uint texsetOffset = reader.ReadUInt32(); uint texturesOffset = reader.ReadUInt32(); MaterialFlag = reader.ReadByte(); // ? NoBackFaceCulling = reader.ReadBoolean(); AdditiveBlending = reader.ReadBoolean(); UnknownFlag1 = reader.ReadByte(); byte paramCount = reader.ReadByte(); byte padding1 = reader.ReadByte(); byte unknownFlag2 = reader.ReadByte(); // Might be an enum, might just be a boolean? byte textureCount = reader.ReadByte(); uint paramsOffset = reader.ReadUInt32(); uint padding2 = reader.ReadUInt32(); uint unknown1 = reader.ReadUInt32(); // Padding/Unknown Value Checks if (padding1 != 0) { Console.WriteLine($"WARNING: Material Padding1 != 0 ({padding1})"); } if (unknownFlag2 > 1) { Console.WriteLine($"WARNING: Material UnknownFlag2 > 1 ({unknownFlag2})"); } if (padding2 != 0) { Console.WriteLine($"WARNING: Material Padding2 != 0 ({padding2})"); } // Shader Name reader.JumpTo(shaderOffset, false); ShaderName = reader.ReadNullTerminatedString(); // Sub-Shader Name reader.JumpTo(subShaderOffset, false); SubShaderName = reader.ReadNullTerminatedString(); // Parameter Offsets var paramOffsets = new uint[paramCount]; reader.JumpTo(paramsOffset, false); for (uint i = 0; i < paramCount; ++i) { paramOffsets[i] = reader.ReadUInt32(); } // Parameters parameters.Clear(); for (uint i = 0; i < paramCount; ++i) { reader.JumpTo(paramOffsets[i], false); var param = new Parameter() { ParamFlag1 = reader.ReadUInt16(), ParamFlag2 = reader.ReadUInt16() }; uint paramNameOffset = reader.ReadUInt32(); uint paramValueOffset = reader.ReadUInt32(); // Parameter Name reader.JumpTo(paramNameOffset, false); param.Name = reader.ReadNullTerminatedString(); // Parameter Value reader.JumpTo(paramValueOffset, false); param.Value = reader.ReadVector4(); parameters.Add(param); } // Texset reader.JumpTo(texsetOffset, false); if (Header.RootNodeType == 1) // TODO: Maybe check for textureCount < 1 instead? { TexsetName = reader.ReadNullTerminatedString(); } else { Texset.Read(reader, textureCount); // Texture Offsets var texOffsets = new uint[textureCount]; reader.JumpTo(texturesOffset, false); for (uint i = 0; i < textureCount; ++i) { texOffsets[i] = reader.ReadUInt32(); } // Textures for (int i = 0; i < textureCount; ++i) { reader.JumpTo(texOffsets[i], false); Texset.Textures[i].Read(reader); } } }