public void WriteToObj(LeagueMap map, Stream outputStream, VertexType type) { using (StreamWriter writer = new StreamWriter(outputStream)) { // Write out some meta data as comments writer.WriteLine(@"// This file was auto generated from a League of Legends .nvr file by liblolmap, which is part of The Dargon Project"); writer.WriteLine(); var vertexOffsets = 0; foreach (var mesh in map.meshes) { var meshData = type == VertexType.COMPLEX ? mesh.complexMesh : mesh.simpleMesh; var vertexBuffer = map.vertexBuffers[meshData.vertexBufferIndex]; for (var i = meshData.vertexBufferOffset; i < meshData.vertexBufferOffset + meshData.vertexCount; ++i) { if (type == VertexType.COMPLEX) { writer.WriteComplexVertex((ComplexVertex)vertexBuffer[i]); } else { writer.WriteSimpleVertex((SimpleVertex)vertexBuffer[i]); } } var indexBuffer = map.indexBuffers[meshData.indexBufferIndex]; var vertexOffset = meshData.vertexBufferOffset; for (var i = meshData.indexBufferOffset; i < meshData.indexBufferOffset + meshData.indexCount; i += 3) { var index1 = indexBuffer[i] - vertexOffset + vertexOffsets + 1; var index2 = indexBuffer[i + 1] - vertexOffset + vertexOffsets + 1; var index3 = indexBuffer[i + 2] - vertexOffset + vertexOffsets + 1; writer.WriteLine("f " + index1 + "/" + index1 + "/" + index1 + " " + index2 + "/" + index2 + "/" + index2 + " " + index3 + "/" + index3 + "/" + index3); } vertexOffsets += meshData.vertexCount; } } }
public LeagueMap LoadFromNVR(IFileSystem system, IFileSystemHandle mapFolderHandle) { // Find the .nvr file IFileSystemHandle nvrFileHandle; if (system.AllocateRelativeHandleFromPath(mapFolderHandle, @"Scene/room.nvr", out nvrFileHandle) != IoResult.Success) { throw new FileNotFoundException(); } // Read the file and put it into a stream for easy processing byte[] nvrFileRawData; if (system.ReadAllBytes(nvrFileHandle, out nvrFileRawData) != IoResult.Success) { throw new FileLoadException(); } using (var ms = new MemoryStream(nvrFileRawData)) { using (var reader = new BinaryReader(ms)) { var leagueMap = new LeagueMap(); // Check magic var magic = reader.ReadBytes(4); if (!magic.SequenceEqual(fileMagic)) { throw new Exception("NVR file magic number is not correct"); } // Read meta data leagueMap.majorVersion = reader.ReadUInt16(); leagueMap.minorVersion = reader.ReadUInt16(); var materialCount = reader.ReadInt32(); var vertexBufferCount = reader.ReadInt32(); var indexBufferCount = reader.ReadInt32(); var meshCount = reader.ReadInt32(); var aabbCount = reader.ReadInt32(); // Read materials leagueMap.materials = Util.Generate(materialCount, i => reader.ReadMaterial()); // Read vertex buffers raw data var vertexBuffers = Util.Generate(vertexBufferCount, i => reader.ReadVertexBufferRawData()); // Read index buffers leagueMap.indexBuffers = Util.Generate(indexBufferCount, i => reader.ReadIndexBuffer()); // Read meshes leagueMap.meshes = Util.Generate(meshCount, i => reader.ReadMesh()); // Classify the vertex buffers var vertexBufferTypes = new VertexType[vertexBufferCount]; foreach (var mesh in leagueMap.meshes) { vertexBufferTypes[mesh.simpleMesh.vertexBufferIndex] = VertexType.SIMPLE; vertexBufferTypes[mesh.complexMesh.vertexBufferIndex] = VertexType.COMPLEX; } // Parse the vertexBuffers leagueMap.vertexBuffers = Util.Generate(vertexBufferCount, i => ReadVertexBuffer(vertexBuffers[i], vertexBufferTypes[i])); // Read AABB data leagueMap.AABBs = new AABB[aabbCount]; for (var i = 0; i < aabbCount; ++i) { leagueMap.AABBs[i] = reader.ReadAABB(); var unknown1 = reader.ReadSingle(); var unknown2 = reader.ReadSingle(); var unknown3 = reader.ReadSingle(); } return(leagueMap); } } }