/* OpenMW - The completely unofficial reimplementation of Morrowind Copyright (C) 2009 Nicolay Korslund WWW: http://openmw.sourceforge.net/ This file (cpp_cachewriter.cpp) is part of the OpenMW package. OpenMW is distributed as free software: you can redistribute it and/or modify it under the terms of the GNU General Public License version 3, as published by the Free Software Foundation. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License version 3 along with this program. If not, see http://www.gnu.org/licenses/ . */ // Helper structs struct AlphaHolder { AlphaInfo info; // Actual pixel buffer unsigned char *buffer; // Texture name and alpha material name to use //std::string texName, alphaName; }; struct MeshHolder { MeshInfo info; // Actual buffers char *vertexBuffer; // Texture name std::string texName; // Alpha maps (if any) std::vector alphas; }; // A struct that gathers all the relevant quad data in one place. struct QuadHolder { QuadInfo info; std::vector meshes; }; class CacheWriter { public: // Opens the main archive file for output void openFile(const std::string &fname) { mainFile.open(fname.c_str(), std::ios::binary); iname = fname + ".index"; fileOffset = 0; totalStringLength = 0; } void setParams(int mxLev, int alphSize) { maxLevel = mxLev; alphaSize = alphSize; vertBufData.resize(maxLevel); indexBufData.resize(maxLevel); vertBufSize.resize(maxLevel); indexBufSize.resize(maxLevel); } // Closes the main archive file and writes the index. void finish() { mainFile.close(); // Write the index file std::ofstream ofile(iname.c_str(), std::ios::binary); // Header first ArchiveHeader head; head.magic = CACHE_MAGIC; head.quads = quadList.size(); head.rootLevel = maxLevel; head.alphaSize = alphaSize; head.stringNum = stringList.size(); head.stringSize = totalStringLength; ofile.write((char*)&head, sizeof(head)); // Write the quads for(QuadList::iterator it = quadList.begin(); it != quadList.end(); it++) { QuadInfo qi = *it; ofile.write((char*)&qi, sizeof(QuadInfo)); } // String table next. We need to sort it in order of the indices // first. std::vector strVector; strVector.resize(head.stringNum); for(StringList::iterator it = stringList.begin(); it != stringList.end(); it++) { strVector[it->second] = it->first; } // Next, write the strings to file while we fill inn the offset // list std::vector offsets; offsets.resize(head.stringNum); size_t curOffs = 0; for(int i=0; i level); vertBufData[level] = ptr; vertBufSize[level] = size; } // Add a common vertex buffer for a given level void addIndexBuffer(int level, void *ptr, int size) { assert(indexBufData.size() > level); indexBufData[level] = ptr; indexBufSize[level] = size; } // Write a finished quad to the archive file. All the offsets and // numbers in the *Info structs are filled in automatically based on // the additional data in the Holder structs. void writeQuad(const QuadHolder &qh) { TRACE("writeQuad"); // See util/outbuffer.h OutBuffer buf; // Write the MeshInfo's first int meshNum = qh.meshes.size(); MeshInfo *meshes = buf.write(meshNum); // Then write the mesh data in approximately the order it's read for(int i=0; i(alphaNum); // Loop through the alpha maps for(int k=0; ksecond; // Nope, insert it int index = stringList.size(); stringList[str] = index; stringLookup[index] = str; // Sum up the string lengths + 1 byte for the zero totalStringLength += str.length() + 1; return index; } const std::string &getString(int index) { const std::string &res = stringLookup[index]; assert(stringList[res] == index); return res; } private: // Write the given block of memory to 'buf', possibly compressing // the data. void writeBuf(OutBuffer &buf, const void *ptr, size_t size) { // Reserve the maximum bytes needed. void *toPtr = buf.reserve(size); // Store the data memcpy(toPtr, ptr, size); // Add the actual number of bytes stored buf.add(size); } std::vector vertBufData; std::vector indexBufData; std::vector vertBufSize; std::vector indexBufSize; // Variables that must be set during the gen phase int maxLevel; int alphaSize; // Contains a unique index for each string typedef std::map StringList; StringList stringList; std::map stringLookup; size_t totalStringLength; // List of all quads typedef std::list QuadList; QuadList quadList; // Output file std::ofstream mainFile; size_t fileOffset; // Index file name std::string iname; };