diff options
Diffstat (limited to 'libs/assimp/code/AssetLib/Q3BSP')
-rw-r--r-- | libs/assimp/code/AssetLib/Q3BSP/Q3BSPFileData.h | 214 | ||||
-rw-r--r-- | libs/assimp/code/AssetLib/Q3BSP/Q3BSPFileImporter.cpp | 680 | ||||
-rw-r--r-- | libs/assimp/code/AssetLib/Q3BSP/Q3BSPFileImporter.h | 118 | ||||
-rw-r--r-- | libs/assimp/code/AssetLib/Q3BSP/Q3BSPFileParser.cpp | 272 | ||||
-rw-r--r-- | libs/assimp/code/AssetLib/Q3BSP/Q3BSPFileParser.h | 89 |
5 files changed, 1373 insertions, 0 deletions
diff --git a/libs/assimp/code/AssetLib/Q3BSP/Q3BSPFileData.h b/libs/assimp/code/AssetLib/Q3BSP/Q3BSPFileData.h new file mode 100644 index 0000000..8ccee0b --- /dev/null +++ b/libs/assimp/code/AssetLib/Q3BSP/Q3BSPFileData.h @@ -0,0 +1,214 @@ +/* +Open Asset Import Library (assimp) +---------------------------------------------------------------------- + +Copyright (c) 2006-2022, assimp team + + +All rights reserved. + +Redistribution and use of this software in source and binary forms, +with or without modification, are permitted provided that the +following conditions are met: + +* Redistributions of source code must retain the above + copyright notice, this list of conditions and the + following disclaimer. + +* Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the + following disclaimer in the documentation and/or other + materials provided with the distribution. + +* Neither the name of the assimp team, nor the names of its + contributors may be used to endorse or promote products + derived from this software without specific prior + written permission of the assimp team. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +---------------------------------------------------------------------- +*/ +#ifndef ASSIMP_Q3BSPFILEDATA_H_INC +#define ASSIMP_Q3BSPFILEDATA_H_INC + +#include <vector> +#include <string.h> +#include <string> + +namespace Assimp { +namespace Q3BSP { + +static const unsigned int CE_BSP_LIGHTMAPWIDTH = 128; +static const unsigned int CE_BSP_LIGHTMAPHEIGHT = 128; + +static const unsigned int CE_BSP_LIGHTMAPSIZE = 128*128*3; ///< = 128( width ) * 128 ( height ) * 3 ( channels / RGB ). +static const int VERION_Q3LEVEL = 46; ///< Supported version. + +/// Geometric type enumeration +enum Q3BSPGeoType { + Polygon = 1, + Patch, + TriangleMesh, + Billboard +}; + +/// Integer vector. +struct ceVec3i { + int x, y, z; + ceVec3i(): x( 0 ), y( 0 ), z( 0 ) { /* empty */ } + ceVec3i( int iX, int iY=0, int iZ=0) : x( iX ), y( iY ), z( iZ ) { /* empty */ } +}; + +/// the file header +struct sQ3BSPHeader { + char strID[ 4 ]; ///< Should be "IBSP" + int iVersion; ///< 46 for standard levels +}; + +/// Describes an entry. +struct sQ3BSPLump { + int iOffset; ///< Offset from start pointer of file + int iSize; ///< Size of part +}; + +struct vec2f { + float x,y; +}; + +struct vec3f { + float x, y, z; +}; + +/// Vertex of a Q3 level +struct sQ3BSPVertex { + vec3f vPosition; ///< Position of vertex + vec2f vTexCoord; ///< (u,v) Texturecoordinate of detailtexture + vec2f vLightmap; ///< (u,v) Texturecoordinate of lightmap + vec3f vNormal; ///< vertex normal + unsigned char bColor[ 4 ]; ///< Color in RGBA +}; + +/// A face in bsp format info +struct sQ3BSPFace { + int iTextureID; ///< Index in texture array + int iEffect; ///< Index in effect array (-1 = no effect) + int iType; ///< 1=Polygon, 2=Patch, 3=Mesh, 4=Billboard + int iVertexIndex; ///< Start index of polygon + int iNumOfVerts; ///< Number of vertices + int iFaceVertexIndex; ///< Index of first mesh vertex + int iNumOfFaceVerts; ///< number of mesh vertices + int iLightmapID; ///< Index to the light-map array + int iLMapCorner[ 2 ]; ///< edge of the light-map in texture + int iLMapSize[ 2 ]; ///< Size of the light-map stored on the texture + vec3f vLMapPos; ///< 3D origin of the light-map + vec3f vLMapVecs[ 2 ]; ///< 3D-s-t-vectors + vec3f vNormal; ///< Polygon normals + int patchWidth, patchHeight; ///< bezier patch +}; + +/// A quake3 texture name. +struct sQ3BSPTexture { + char strName[ 64 ]; ///< Name of the texture without extension + int iFlags; ///< Not used + int iContents; ///< Not used +}; + +/// A light-map of the level, size 128 x 128, RGB components. +struct sQ3BSPLightmap { + unsigned char bLMapData[ CE_BSP_LIGHTMAPSIZE ]; + sQ3BSPLightmap() { + ::memset(bLMapData, 0, CE_BSP_LIGHTMAPSIZE ); + } +}; + +struct SubPatch { + std::vector<size_t> indices; + int lightmapID; +}; + +enum eLumps { + kEntities = 0, + kTextures, + kPlanes, + kNodes, + kLeafs, + kLeafFaces, + kLeafBrushes, + kModels, + kBrushes, + kBrushSides, + kVertices, + kMeshVerts, + kShaders, + kFaces, + kLightmaps, + kLightVolumes, + kVisData, + kMaxLumps +}; + +struct Q3BSPModel { + std::vector<unsigned char> m_Data; + std::vector<sQ3BSPLump*> m_Lumps; + std::vector<sQ3BSPVertex*> m_Vertices; + std::vector<sQ3BSPFace*> m_Faces; + std::vector<int> m_Indices; + std::vector<sQ3BSPTexture*> m_Textures; + std::vector<sQ3BSPLightmap*> m_Lightmaps; + std::vector<char> m_EntityData; + std::string m_ModelName; + + Q3BSPModel() : + m_Data(), + m_Lumps(), + m_Vertices(), + m_Faces(), + m_Indices(), + m_Textures(), + m_Lightmaps(), + m_EntityData(), + m_ModelName() + { + // empty + } + + ~Q3BSPModel() { + for ( unsigned int i=0; i<m_Lumps.size(); i++ ) { + delete m_Lumps[ i ]; + } + for ( unsigned int i=0; i<m_Vertices.size(); i++ ) { + delete m_Vertices[ i ]; + } + for ( unsigned int i=0; i<m_Faces.size(); i++ ) { + delete m_Faces[ i ]; + } + for ( unsigned int i=0; i<m_Textures.size(); i++ ) { + delete m_Textures[ i ]; + } + for ( unsigned int i=0; i<m_Lightmaps.size(); i++ ) { + delete m_Lightmaps[ i ]; + } + + m_Lumps.clear(); + m_Vertices.clear(); + m_Faces.clear(); + m_Textures.clear(); + m_Lightmaps.clear(); + } +}; + +} // Namespace Q3BSP +} // Namespace Assimp + +#endif // ASSIMP_Q3BSPFILEDATA_H_INC diff --git a/libs/assimp/code/AssetLib/Q3BSP/Q3BSPFileImporter.cpp b/libs/assimp/code/AssetLib/Q3BSP/Q3BSPFileImporter.cpp new file mode 100644 index 0000000..db9a4a0 --- /dev/null +++ b/libs/assimp/code/AssetLib/Q3BSP/Q3BSPFileImporter.cpp @@ -0,0 +1,680 @@ +/* +Open Asset Import Library (assimp) +--------------------------------------------------------------------------------------------------- + +Copyright (c) 2006-2022, assimp team + + +All rights reserved. + +Redistribution and use of this software in source and binary forms, +with or without modification, are permitted provided that the +following conditions are met: + +* Redistributions of source code must retain the above + copyright notice, this list of conditions and the + following disclaimer. + +* Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the + following disclaimer in the documentation and/or other + materials provided with the distribution. + +* Neither the name of the assimp team, nor the names of its + contributors may be used to endorse or promote products + derived from this software without specific prior + written permission of the assimp team. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +--------------------------------------------------------------------------------------------------- +*/ + +#ifndef ASSIMP_BUILD_NO_Q3BSP_IMPORTER + +#include "Q3BSPFileImporter.h" +#include "Q3BSPFileData.h" +#include "Q3BSPFileParser.h" + +#include <assimp/DefaultLogger.hpp> + +#ifdef ASSIMP_BUILD_NO_OWN_ZLIB +#include <zlib.h> +#else +#include "../contrib/zlib/zlib.h" +#endif + +#include <assimp/DefaultIOSystem.h> +#include <assimp/StringComparison.h> +#include <assimp/ZipArchiveIOSystem.h> +#include <assimp/ai_assert.h> +#include <assimp/importerdesc.h> +#include <assimp/mesh.h> +#include <assimp/scene.h> +#include <assimp/types.h> +#include <sstream> +#include <vector> + +static const aiImporterDesc desc = { + "Quake III BSP Importer", + "", + "", + "", + aiImporterFlags_SupportBinaryFlavour, + 0, + 0, + 0, + 0, + "bsp pk3" +}; + +namespace Assimp { + +using namespace Q3BSP; + +// ------------------------------------------------------------------------------------------------ +// Local function to create a material key name. +static void createKey(int id1, int id2, std::string &key) { + std::ostringstream str; + str << id1 << "." << id2; + key = str.str(); +} + +// ------------------------------------------------------------------------------------------------ +// Local function to extract the texture ids from a material key-name. +static void extractIds(const std::string &key, int &id1, int &id2) { + id1 = -1; + id2 = -1; + if (key.empty()) { + return; + } + + const std::string::size_type pos = key.find('.'); + if (std::string::npos == pos) { + return; + } + + std::string tmp1 = key.substr(0, pos); + std::string tmp2 = key.substr(pos + 1, key.size() - pos - 1); + id1 = atoi(tmp1.c_str()); + id2 = atoi(tmp2.c_str()); +} + +// ------------------------------------------------------------------------------------------------ +// Local helper function to normalize filenames. +static void normalizePathName(const std::string &rPath, std::string &normalizedPath) { + normalizedPath = std::string(); + if (rPath.empty()) { + return; + } + +#ifdef _WIN32 + std::string sep = "\\"; +#else + std::string sep = "/"; +#endif + + static const unsigned int numDelimiters = 2; + const char delimiters[numDelimiters] = { '/', '\\' }; + normalizedPath = rPath; + for (const char delimiter : delimiters) { + for (size_t j = 0; j < normalizedPath.size(); ++j) { + if (normalizedPath[j] == delimiter) { + normalizedPath[j] = sep[0]; + } + } + } +} + +// ------------------------------------------------------------------------------------------------ +// Constructor. +Q3BSPFileImporter::Q3BSPFileImporter() : + m_pCurrentMesh(nullptr), m_pCurrentFace(nullptr), m_MaterialLookupMap(), mTextures() { + // empty +} + +// ------------------------------------------------------------------------------------------------ +// Destructor. +Q3BSPFileImporter::~Q3BSPFileImporter() { + // Clear face-to-material map + for (FaceMap::iterator it = m_MaterialLookupMap.begin(); it != m_MaterialLookupMap.end(); ++it) { + const std::string &matName = it->first; + if (!matName.empty()) { + delete it->second; + } + } +} + +// ------------------------------------------------------------------------------------------------ +// Returns true if the loader can read this. +bool Q3BSPFileImporter::CanRead(const std::string &filename, IOSystem * /*pIOHandler*/, bool checkSig) const { + if (!checkSig) { + return SimpleExtensionCheck(filename, "pk3", "bsp"); + } + return false; +} + +// ------------------------------------------------------------------------------------------------ +// Adds extensions. +const aiImporterDesc *Q3BSPFileImporter::GetInfo() const { + return &desc; +} + +// ------------------------------------------------------------------------------------------------ +// Import method. +void Q3BSPFileImporter::InternReadFile(const std::string &rFile, aiScene *scene, IOSystem *ioHandler) { + ZipArchiveIOSystem Archive(ioHandler, rFile); + if (!Archive.isOpen()) { + throw DeadlyImportError("Failed to open file ", rFile, "."); + } + + std::string archiveName, mapName; + separateMapName(rFile, archiveName, mapName); + + if (mapName.empty()) { + if (!findFirstMapInArchive(Archive, mapName)) { + return; + } + } + + Q3BSPFileParser fileParser(mapName, &Archive); + Q3BSPModel *pBSPModel = fileParser.getModel(); + if (nullptr != pBSPModel) { + CreateDataFromImport(pBSPModel, scene, &Archive); + } +} + +// ------------------------------------------------------------------------------------------------ +// Separates the map name from the import name. +void Q3BSPFileImporter::separateMapName(const std::string &importName, std::string &archiveName, std::string &mapName) { + archiveName = std::string(); + mapName = std::string(); + if (importName.empty()) { + return; + } + + const std::string::size_type pos = importName.rfind(','); + if (std::string::npos == pos) { + archiveName = importName; + return; + } + + archiveName = importName.substr(0, pos); + mapName = importName.substr(pos, importName.size() - pos - 1); +} + +// ------------------------------------------------------------------------------------------------ +// Returns the first map in the map archive. +bool Q3BSPFileImporter::findFirstMapInArchive(ZipArchiveIOSystem &bspArchive, std::string &mapName) { + mapName = std::string(); + std::vector<std::string> fileList; + bspArchive.getFileListExtension(fileList, "bsp"); + if (fileList.empty()) { + return false; + } + + std::vector<std::string>::iterator it(fileList.begin()); + for (; it != fileList.end(); ++it) { + const std::string::size_type pos = (*it).find("maps/"); + if (std::string::npos != pos) { + std::string::size_type extPos = (*it).find(".bsp"); + if (std::string::npos != extPos) { + mapName = *it; + return true; + } + } + } + + return false; +} + +// ------------------------------------------------------------------------------------------------ +// Creates the assimp specific data. +void Q3BSPFileImporter::CreateDataFromImport(const Q3BSP::Q3BSPModel *pModel, aiScene *pScene, + ZipArchiveIOSystem *pArchive) { + if (nullptr == pModel || nullptr == pScene) { + return; + } + + pScene->mRootNode = new aiNode; + if (!pModel->m_ModelName.empty()) { + pScene->mRootNode->mName.Set(pModel->m_ModelName); + } + + // Create the face to material relation map + createMaterialMap(pModel); + + // Create all nodes + CreateNodes(pModel, pScene, pScene->mRootNode); + + // Create the assigned materials + createMaterials(pModel, pScene, pArchive); +} + +// ------------------------------------------------------------------------------------------------ +// Creates all assimp nodes. +void Q3BSPFileImporter::CreateNodes(const Q3BSP::Q3BSPModel *pModel, aiScene *pScene, + aiNode *pParent) { + if (nullptr == pModel) { + return; + } + + unsigned int matIdx(0); + std::vector<aiMesh *> MeshArray; + std::vector<aiNode *> NodeArray; + for (FaceMapIt it = m_MaterialLookupMap.begin(); it != m_MaterialLookupMap.end(); ++it) { + std::vector<Q3BSP::sQ3BSPFace *> *pArray = (*it).second; + size_t numVerts = countData(*pArray); + if (0 != numVerts) { + aiMesh *pMesh(nullptr); + aiNode *pNode = CreateTopology(pModel, matIdx, *pArray, &pMesh); + if (nullptr != pNode) { + NodeArray.push_back(pNode); + MeshArray.push_back(pMesh); + } + } + matIdx++; + } + + pScene->mNumMeshes = static_cast<unsigned int>(MeshArray.size()); + if (pScene->mNumMeshes > 0) { + pScene->mMeshes = new aiMesh *[pScene->mNumMeshes]; + for (size_t i = 0; i < MeshArray.size(); i++) { + aiMesh *pMesh = MeshArray[i]; + if (nullptr != pMesh) { + pScene->mMeshes[i] = pMesh; + } + } + } + + pParent->mNumChildren = static_cast<unsigned int>(MeshArray.size()); + pParent->mChildren = new aiNode *[pScene->mRootNode->mNumChildren]; + for (size_t i = 0; i < NodeArray.size(); i++) { + aiNode *pNode = NodeArray[i]; + pNode->mParent = pParent; + pParent->mChildren[i] = pNode; + pParent->mChildren[i]->mMeshes[0] = static_cast<unsigned int>(i); + } +} + +// ------------------------------------------------------------------------------------------------ +// Creates the topology. +aiNode *Q3BSPFileImporter::CreateTopology(const Q3BSP::Q3BSPModel *pModel, unsigned int materialIdx, + std::vector<sQ3BSPFace *> &rArray, aiMesh **pMesh) { + size_t numVerts = countData(rArray); + if (0 == numVerts) { + return nullptr; + } + + size_t numFaces = countFaces(rArray); + if (0 == numFaces) { + return nullptr; + } + + aiMesh *mesh = new aiMesh; + size_t numTriangles = countTriangles(rArray); + mesh->mPrimitiveTypes = aiPrimitiveType_TRIANGLE; + + mesh->mFaces = new aiFace[numTriangles]; + mesh->mNumFaces = static_cast<unsigned int>(numTriangles); + + mesh->mNumVertices = static_cast<unsigned int>(numVerts); + mesh->mVertices = new aiVector3D[numVerts]; + mesh->mNormals = new aiVector3D[numVerts]; + mesh->mTextureCoords[0] = new aiVector3D[numVerts]; + mesh->mTextureCoords[1] = new aiVector3D[numVerts]; + mesh->mMaterialIndex = materialIdx; + + unsigned int faceIdx = 0; + unsigned int vertIdx = 0; + mesh->mNumUVComponents[0] = 2; + mesh->mNumUVComponents[1] = 2; + for (std::vector<sQ3BSPFace *>::const_iterator it = rArray.begin(); it != rArray.end(); ++it) { + Q3BSP::sQ3BSPFace *pQ3BSPFace = *it; + ai_assert(nullptr != pQ3BSPFace); + if (nullptr == pQ3BSPFace) { + continue; + } + + if (pQ3BSPFace->iNumOfFaceVerts > 0) { + if (pQ3BSPFace->iType == Polygon || pQ3BSPFace->iType == TriangleMesh) { + createTriangleTopology(pModel, pQ3BSPFace, mesh, faceIdx, vertIdx); + } + } + } + + aiNode *pNode = new aiNode; + pNode->mNumMeshes = 1; + pNode->mMeshes = new unsigned int[1]; + *pMesh = mesh; + + return pNode; +} + +// ------------------------------------------------------------------------------------------------ +// Creates the triangle topology from a face array. +void Q3BSPFileImporter::createTriangleTopology(const Q3BSP::Q3BSPModel *pModel, sQ3BSPFace *pQ3BSPFace, + aiMesh *pMesh, unsigned int &faceIdx, unsigned int &vertIdx) { + ai_assert(faceIdx < pMesh->mNumFaces); + + m_pCurrentFace = getNextFace(pMesh, faceIdx); + if (nullptr == m_pCurrentFace) { + return; + } + + m_pCurrentFace->mNumIndices = 3; + m_pCurrentFace->mIndices = new unsigned int[m_pCurrentFace->mNumIndices]; + + size_t idx(0); + for (size_t i = 0; i < (size_t)pQ3BSPFace->iNumOfFaceVerts; ++i) { + const size_t index = pQ3BSPFace->iVertexIndex + pModel->m_Indices[pQ3BSPFace->iFaceVertexIndex + i]; + if (index >= pModel->m_Vertices.size()) { + continue; + } + + sQ3BSPVertex *pVertex = pModel->m_Vertices[index]; + if (nullptr == pVertex) { + continue; + } + if (idx > 2) { + idx = 0; + m_pCurrentFace = getNextFace(pMesh, faceIdx); + if (nullptr != m_pCurrentFace) { + m_pCurrentFace->mNumIndices = 3; + m_pCurrentFace->mIndices = new unsigned int[3]; + m_pCurrentFace->mIndices[idx] = vertIdx; + } + } + + pMesh->mVertices[vertIdx].Set(pVertex->vPosition.x, pVertex->vPosition.y, pVertex->vPosition.z); + pMesh->mNormals[vertIdx].Set(pVertex->vNormal.x, pVertex->vNormal.y, pVertex->vNormal.z); + + pMesh->mTextureCoords[0][vertIdx].Set(pVertex->vTexCoord.x, pVertex->vTexCoord.y, 0.0f); + pMesh->mTextureCoords[1][vertIdx].Set(pVertex->vLightmap.x, pVertex->vLightmap.y, 0.0f); + + vertIdx++; + idx++; + } +} + +// ------------------------------------------------------------------------------------------------ +// Creates all referenced materials. +void Q3BSPFileImporter::createMaterials(const Q3BSP::Q3BSPModel *pModel, aiScene *pScene, + ZipArchiveIOSystem *pArchive) { + if (m_MaterialLookupMap.empty()) { + return; + } + + pScene->mMaterials = new aiMaterial *[m_MaterialLookupMap.size()]; + aiString aiMatName; + int textureId(-1), lightmapId(-1); + for (FaceMapIt it = m_MaterialLookupMap.begin(); it != m_MaterialLookupMap.end(); + ++it) { + const std::string matName(it->first); + if (matName.empty()) { + continue; + } + + aiMatName.Set(matName); + aiMaterial *pMatHelper = new aiMaterial; + pMatHelper->AddProperty(&aiMatName, AI_MATKEY_NAME); + + extractIds(matName, textureId, lightmapId); + + // Adding the texture + if (-1 != textureId) { + sQ3BSPTexture *pTexture = pModel->m_Textures[textureId]; + if (nullptr != pTexture) { + std::string tmp("*"), texName; + tmp += pTexture->strName; + tmp += ".jpg"; + normalizePathName(tmp, texName); + + if (!importTextureFromArchive(pModel, pArchive, pScene, pMatHelper, textureId)) { + ASSIMP_LOG_ERROR("Cannot import texture from archive ", texName); + } + } + } + if (-1 != lightmapId) { + importLightmap(pModel, pScene, pMatHelper, lightmapId); + } + pScene->mMaterials[pScene->mNumMaterials] = pMatHelper; + pScene->mNumMaterials++; + } + pScene->mNumTextures = static_cast<unsigned int>(mTextures.size()); + pScene->mTextures = new aiTexture *[pScene->mNumTextures]; + std::copy(mTextures.begin(), mTextures.end(), pScene->mTextures); +} + +// ------------------------------------------------------------------------------------------------ +// Counts the number of referenced vertices. +size_t Q3BSPFileImporter::countData(const std::vector<sQ3BSPFace *> &faceArray) const { + size_t numVerts(0); + for (std::vector<sQ3BSPFace *>::const_iterator it = faceArray.begin(); it != faceArray.end(); + ++it) { + sQ3BSPFace *pQ3BSPFace = *it; + if (pQ3BSPFace->iType == Polygon || pQ3BSPFace->iType == TriangleMesh) { + Q3BSP::sQ3BSPFace *face = *it; + if (nullptr != face) { + numVerts += face->iNumOfFaceVerts; + } + } + } + + return numVerts; +} + +// ------------------------------------------------------------------------------------------------ +// Counts the faces with vertices. +size_t Q3BSPFileImporter::countFaces(const std::vector<Q3BSP::sQ3BSPFace *> &rArray) const { + size_t numFaces = 0; + for (std::vector<sQ3BSPFace *>::const_iterator it = rArray.begin(); it != rArray.end(); + ++it) { + Q3BSP::sQ3BSPFace *pQ3BSPFace = *it; + if (pQ3BSPFace->iNumOfFaceVerts > 0) { + numFaces++; + } + } + + return numFaces; +} + +// ------------------------------------------------------------------------------------------------ +// Counts the number of triangles in a Q3-face-array. +size_t Q3BSPFileImporter::countTriangles(const std::vector<Q3BSP::sQ3BSPFace *> &rArray) const { + size_t numTriangles = 0; + for (std::vector<Q3BSP::sQ3BSPFace *>::const_iterator it = rArray.begin(); it != rArray.end(); + ++it) { + const Q3BSP::sQ3BSPFace *pQ3BSPFace = *it; + if (nullptr != pQ3BSPFace) { + numTriangles += pQ3BSPFace->iNumOfFaceVerts / 3; + } + } + + return numTriangles; +} + +// ------------------------------------------------------------------------------------------------ +// Creates the faces-to-material map. +void Q3BSPFileImporter::createMaterialMap(const Q3BSP::Q3BSPModel *pModel) { + std::string key; + std::vector<sQ3BSPFace *> *pCurFaceArray = nullptr; + for (size_t idx = 0; idx < pModel->m_Faces.size(); idx++) { + Q3BSP::sQ3BSPFace *pQ3BSPFace = pModel->m_Faces[idx]; + const int texId = pQ3BSPFace->iTextureID; + const int lightMapId = pQ3BSPFace->iLightmapID; + createKey(texId, lightMapId, key); + FaceMapIt it = m_MaterialLookupMap.find(key); + if (m_MaterialLookupMap.end() == it) { + pCurFaceArray = new std::vector<Q3BSP::sQ3BSPFace *>; + m_MaterialLookupMap[key] = pCurFaceArray; + } else { + pCurFaceArray = (*it).second; + } + ai_assert(nullptr != pCurFaceArray); + if (nullptr != pCurFaceArray) { + pCurFaceArray->push_back(pQ3BSPFace); + } + } +} + +// ------------------------------------------------------------------------------------------------ +// Returns the next face. +aiFace *Q3BSPFileImporter::getNextFace(aiMesh *mesh, unsigned int &faceIdx) { + aiFace *face(nullptr); + if (faceIdx < mesh->mNumFaces) { + face = &mesh->mFaces[faceIdx]; + ++faceIdx; + } + + return face; +} + +// ------------------------------------------------------------------------------------------------ +// Imports a texture file. +bool Q3BSPFileImporter::importTextureFromArchive(const Q3BSP::Q3BSPModel *model, + ZipArchiveIOSystem *archive, aiScene *, + aiMaterial *pMatHelper, int textureId) { + if (nullptr == archive || nullptr == pMatHelper) { + return false; + } + + if (textureId < 0 || textureId >= static_cast<int>(model->m_Textures.size())) { + return false; + } + + bool res = true; + sQ3BSPTexture *pTexture = model->m_Textures[textureId]; + if (!pTexture) { + return false; + } + + std::vector<std::string> supportedExtensions; + supportedExtensions.push_back(".jpg"); + supportedExtensions.push_back(".png"); + supportedExtensions.push_back(".tga"); + std::string textureName, ext; + if (expandFile(archive, pTexture->strName, supportedExtensions, textureName, ext)) { + IOStream *pTextureStream = archive->Open(textureName.c_str()); + if (pTextureStream) { + size_t texSize = pTextureStream->FileSize(); + aiTexture *curTexture = new aiTexture; + curTexture->mHeight = 0; + curTexture->mWidth = static_cast<unsigned int>(texSize); + unsigned char *pData = new unsigned char[curTexture->mWidth]; + size_t readSize = pTextureStream->Read(pData, sizeof(unsigned char), curTexture->mWidth); + (void)readSize; + ai_assert(readSize == curTexture->mWidth); + curTexture->pcData = reinterpret_cast<aiTexel *>(pData); + curTexture->achFormatHint[0] = ext[1]; + curTexture->achFormatHint[1] = ext[2]; + curTexture->achFormatHint[2] = ext[3]; + curTexture->achFormatHint[3] = '\0'; + res = true; + + aiString name; + name.data[0] = '*'; + name.length = 1 + ASSIMP_itoa10(name.data + 1, static_cast<unsigned int>(MAXLEN - 1), static_cast<int32_t>(mTextures.size())); + + archive->Close(pTextureStream); + + pMatHelper->AddProperty(&name, AI_MATKEY_TEXTURE_DIFFUSE(0)); + mTextures.push_back(curTexture); + } else { + // If it doesn't exist in the archive, it is probably just a reference to an external file. + // We'll leave it up to the user to figure out which extension the file has. + aiString name; + strncpy(name.data, pTexture->strName, sizeof name.data); + name.length = static_cast<ai_uint32>(strlen(name.data)); + pMatHelper->AddProperty(&name, AI_MATKEY_TEXTURE_DIFFUSE(0)); + } + } + + return res; +} + +// ------------------------------------------------------------------------------------------------ +// Imports a light map file. +bool Q3BSPFileImporter::importLightmap(const Q3BSP::Q3BSPModel *pModel, aiScene *pScene, + aiMaterial *pMatHelper, int lightmapId) { + if (nullptr == pModel || nullptr == pScene || nullptr == pMatHelper) { + return false; + } + + if (lightmapId < 0 || lightmapId >= static_cast<int>(pModel->m_Lightmaps.size())) { + return false; + } + + sQ3BSPLightmap *pLightMap = pModel->m_Lightmaps[lightmapId]; + if (nullptr == pLightMap) { + return false; + } + + aiTexture *pTexture = new aiTexture; + + pTexture->mWidth = CE_BSP_LIGHTMAPWIDTH; + pTexture->mHeight = CE_BSP_LIGHTMAPHEIGHT; + pTexture->pcData = new aiTexel[CE_BSP_LIGHTMAPWIDTH * CE_BSP_LIGHTMAPHEIGHT]; + + ::memcpy(pTexture->pcData, pLightMap->bLMapData, pTexture->mWidth); + size_t p = 0; + for (size_t i = 0; i < CE_BSP_LIGHTMAPWIDTH * CE_BSP_LIGHTMAPHEIGHT; ++i) { + pTexture->pcData[i].r = pLightMap->bLMapData[p++]; + pTexture->pcData[i].g = pLightMap->bLMapData[p++]; + pTexture->pcData[i].b = pLightMap->bLMapData[p++]; + pTexture->pcData[i].a = 0xFF; + } + + aiString name; + name.data[0] = '*'; + name.length = 1 + ASSIMP_itoa10(name.data + 1, static_cast<unsigned int>(MAXLEN - 1), static_cast<int32_t>(mTextures.size())); + + pMatHelper->AddProperty(&name, AI_MATKEY_TEXTURE_LIGHTMAP(1)); + mTextures.push_back(pTexture); + + return true; +} + +// ------------------------------------------------------------------------------------------------ +// Will search for a supported extension. +bool Q3BSPFileImporter::expandFile(ZipArchiveIOSystem *pArchive, const std::string &rFilename, + const std::vector<std::string> &rExtList, std::string &rFile, + std::string &rExt) { + ai_assert(nullptr != pArchive); + ai_assert(!rFilename.empty()); + + if (rExtList.empty()) { + rFile = rFilename; + rExt = std::string(); + return true; + } + + bool found = false; + for (std::vector<std::string>::const_iterator it = rExtList.begin(); it != rExtList.end(); ++it) { + const std::string textureName = rFilename + *it; + if (pArchive->Exists(textureName.c_str())) { + rExt = *it; + rFile = textureName; + found = true; + break; + } + } + + return found; +} + +// ------------------------------------------------------------------------------------------------ + +} // Namespace Assimp + +#endif // ASSIMP_BUILD_NO_Q3BSP_IMPORTER diff --git a/libs/assimp/code/AssetLib/Q3BSP/Q3BSPFileImporter.h b/libs/assimp/code/AssetLib/Q3BSP/Q3BSPFileImporter.h new file mode 100644 index 0000000..fdcfff8 --- /dev/null +++ b/libs/assimp/code/AssetLib/Q3BSP/Q3BSPFileImporter.h @@ -0,0 +1,118 @@ +/* +Open Asset Import Library (assimp) +---------------------------------------------------------------------- + +Copyright (c) 2006-2022, assimp team + +All rights reserved. + +Redistribution and use of this software in source and binary forms, +with or without modification, are permitted provided that the +following conditions are met: + +* Redistributions of source code must retain the above + copyright notice, this list of conditions and the + following disclaimer. + +* Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the + following disclaimer in the documentation and/or other + materials provided with the distribution. + +* Neither the name of the assimp team, nor the names of its + contributors may be used to endorse or promote products + derived from this software without specific prior + written permission of the assimp team. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +---------------------------------------------------------------------- +*/ +#ifndef ASSIMP_Q3BSPFILEIMPORTER_H_INC +#define ASSIMP_Q3BSPFILEIMPORTER_H_INC + +#include <assimp/BaseImporter.h> + +#include <map> +#include <string> + +struct aiMesh; +struct aiNode; +struct aiFace; +struct aiMaterial; +struct aiTexture; + +namespace Assimp { + class ZipArchiveIOSystem; + +namespace Q3BSP { + struct Q3BSPModel; + struct sQ3BSPFace; +} + +// ------------------------------------------------------------------------------------------------ +/** Loader to import BSP-levels from a PK3 archive or from a unpacked BSP-level. + */ +// ------------------------------------------------------------------------------------------------ +class Q3BSPFileImporter : public BaseImporter { +public: + /// @brief Default constructor. + Q3BSPFileImporter(); + + /// @brief Destructor. + ~Q3BSPFileImporter() override; + + /// @brief Returns whether the class can handle the format of the given file. + /// @remark See BaseImporter::CanRead() for details. + bool CanRead( const std::string& pFile, IOSystem* pIOHandler, bool checkSig ) const override; + +protected: + using FaceMap = std::map<std::string, std::vector<Q3BSP::sQ3BSPFace*>*>; + using FaceMapIt = std::map<std::string, std::vector<Q3BSP::sQ3BSPFace*>* >::iterator; + using FaceMapConstIt = std::map<std::string, std::vector<Q3BSP::sQ3BSPFace*>*>::const_iterator; + + const aiImporterDesc* GetInfo () const override; + void InternReadFile(const std::string& pFile, aiScene* pScene, IOSystem* pIOHandler) override; + void separateMapName( const std::string &rImportName, std::string &rArchiveName, std::string &rMapName ); + bool findFirstMapInArchive(ZipArchiveIOSystem &rArchive, std::string &rMapName ); + void CreateDataFromImport( const Q3BSP::Q3BSPModel *pModel, aiScene* pScene, ZipArchiveIOSystem *pArchive ); + void CreateNodes( const Q3BSP::Q3BSPModel *pModel, aiScene* pScene, aiNode *pParent ); + aiNode *CreateTopology( const Q3BSP::Q3BSPModel *pModel, unsigned int materialIdx, + std::vector<Q3BSP::sQ3BSPFace*> &rArray, aiMesh **pMesh ); + void createTriangleTopology( const Q3BSP::Q3BSPModel *pModel, Q3BSP::sQ3BSPFace *pQ3BSPFace, aiMesh* pMesh, unsigned int &rFaceIdx, + unsigned int &rVertIdx ); + void createMaterials( const Q3BSP::Q3BSPModel *pModel, aiScene* pScene, ZipArchiveIOSystem *pArchive ); + size_t countData( const std::vector<Q3BSP::sQ3BSPFace*> &rArray ) const; + size_t countFaces( const std::vector<Q3BSP::sQ3BSPFace*> &rArray ) const; + size_t countTriangles( const std::vector<Q3BSP::sQ3BSPFace*> &rArray ) const; + void createMaterialMap( const Q3BSP::Q3BSPModel *pModel); + aiFace *getNextFace( aiMesh *pMesh, unsigned int &rFaceIdx ); + bool importTextureFromArchive( const Q3BSP::Q3BSPModel *pModel, ZipArchiveIOSystem *pArchive, aiScene* pScene, + aiMaterial *pMatHelper, int textureId ); + bool importLightmap( const Q3BSP::Q3BSPModel *pModel, aiScene* pScene, aiMaterial *pMatHelper, int lightmapId ); + bool importEntities( const Q3BSP::Q3BSPModel *pModel, aiScene* pScene ); + bool expandFile(ZipArchiveIOSystem *pArchive, const std::string &rFilename, const std::vector<std::string> &rExtList, + std::string &rFile, std::string &rExt ); + +private: + aiMesh *m_pCurrentMesh; + aiFace *m_pCurrentFace; + FaceMap m_MaterialLookupMap; + std::vector<aiTexture*> mTextures; +}; + +// ------------------------------------------------------------------------------------------------ + +} // Namespace Assimp + +#endif // ASSIMP_Q3BSPFILEIMPORTER_H_INC diff --git a/libs/assimp/code/AssetLib/Q3BSP/Q3BSPFileParser.cpp b/libs/assimp/code/AssetLib/Q3BSP/Q3BSPFileParser.cpp new file mode 100644 index 0000000..910da5b --- /dev/null +++ b/libs/assimp/code/AssetLib/Q3BSP/Q3BSPFileParser.cpp @@ -0,0 +1,272 @@ +/* +Open Asset Import Library (assimp) +---------------------------------------------------------------------- + +Copyright (c) 2006-2022, assimp team + +All rights reserved. + +Redistribution and use of this software in source and binary forms, +with or without modification, are permitted provided that the +following conditions are met: + +* Redistributions of source code must retain the above + copyright notice, this list of conditions and the + following disclaimer. + +* Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the + following disclaimer in the documentation and/or other + materials provided with the distribution. + +* Neither the name of the assimp team, nor the names of its + contributors may be used to endorse or promote products + derived from this software without specific prior + written permission of the assimp team. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +---------------------------------------------------------------------- +*/ + + +#ifndef ASSIMP_BUILD_NO_Q3BSP_IMPORTER + +#include "Q3BSPFileParser.h" +#include "Q3BSPFileData.h" +#include <vector> +#include <assimp/DefaultIOSystem.h> +#include <assimp/ZipArchiveIOSystem.h> +#include <assimp/ai_assert.h> + +namespace Assimp { + +using namespace Q3BSP; + +// ------------------------------------------------------------------------------------------------ +Q3BSPFileParser::Q3BSPFileParser( const std::string &mapName, ZipArchiveIOSystem *pZipArchive ) : + m_sOffset( 0 ), + m_Data(), + m_pModel(nullptr), + m_pZipArchive( pZipArchive ) +{ + ai_assert(nullptr != m_pZipArchive ); + ai_assert( !mapName.empty() ); + + if ( !readData( mapName ) ) + return; + + m_pModel = new Q3BSPModel; + m_pModel->m_ModelName = mapName; + if ( !parseFile() ) { + delete m_pModel; + m_pModel = nullptr; + } +} + +// ------------------------------------------------------------------------------------------------ +Q3BSPFileParser::~Q3BSPFileParser() { + delete m_pModel; +} + +// ------------------------------------------------------------------------------------------------ +Q3BSP::Q3BSPModel *Q3BSPFileParser::getModel() const { + return m_pModel; +} + +// ------------------------------------------------------------------------------------------------ +bool Q3BSPFileParser::readData( const std::string &rMapName ) { + if ( !m_pZipArchive->Exists( rMapName.c_str() ) ) + return false; + + IOStream *pMapFile = m_pZipArchive->Open( rMapName.c_str() ); + if ( nullptr == pMapFile ) + return false; + + const size_t size = pMapFile->FileSize(); + m_Data.resize( size ); + + const size_t readSize = pMapFile->Read( &m_Data[0], sizeof( char ), size ); + if ( readSize != size ) { + m_Data.clear(); + m_pZipArchive->Close(pMapFile); + return false; + } + m_pZipArchive->Close( pMapFile ); + + return true; +} + +// ------------------------------------------------------------------------------------------------ +bool Q3BSPFileParser::parseFile() { + if ( m_Data.empty() ) { + return false; + } + + if ( !validateFormat() ) + { + return false; + } + + // Imports the dictionary of the level + getLumps(); + + // Count data and prepare model data + countLumps(); + + // Read in Vertices + getVertices(); + + // Read in Indices + getIndices(); + + // Read Faces + getFaces(); + + // Read Textures + getTextures(); + + // Read Lightmaps + getLightMaps(); + + // Load the entities + getEntities(); + + return true; +} + +// ------------------------------------------------------------------------------------------------ +bool Q3BSPFileParser::validateFormat() +{ + sQ3BSPHeader *pHeader = (sQ3BSPHeader*) &m_Data[ 0 ]; + m_sOffset += sizeof( sQ3BSPHeader ); + + // Version and identify string validation + if (pHeader->strID[ 0 ] != 'I' || pHeader->strID[ 1 ] != 'B' || pHeader->strID[ 2 ] != 'S' + || pHeader->strID[ 3 ] != 'P') + { + return false; + } + + return true; +} + +// ------------------------------------------------------------------------------------------------ +void Q3BSPFileParser::getLumps() +{ + size_t Offset = m_sOffset; + m_pModel->m_Lumps.resize( kMaxLumps ); + for ( size_t idx=0; idx < kMaxLumps; idx++ ) + { + sQ3BSPLump *pLump = new sQ3BSPLump; + memcpy( pLump, &m_Data[ Offset ], sizeof( sQ3BSPLump ) ); + Offset += sizeof( sQ3BSPLump ); + m_pModel->m_Lumps[ idx ] = pLump; + } +} + +// ------------------------------------------------------------------------------------------------ +void Q3BSPFileParser::countLumps() +{ + m_pModel->m_Vertices.resize( m_pModel->m_Lumps[ kVertices ]->iSize / sizeof( sQ3BSPVertex ) ); + m_pModel->m_Indices.resize( m_pModel->m_Lumps[ kMeshVerts ]->iSize / sizeof( int ) ); + m_pModel->m_Faces.resize( m_pModel->m_Lumps[ kFaces ]->iSize / sizeof( sQ3BSPFace ) ); + m_pModel->m_Textures.resize( m_pModel->m_Lumps[ kTextures ]->iSize / sizeof( sQ3BSPTexture ) ); + m_pModel->m_Lightmaps.resize( m_pModel->m_Lumps[ kLightmaps ]->iSize / sizeof( sQ3BSPLightmap ) ); +} + +// ------------------------------------------------------------------------------------------------ +void Q3BSPFileParser::getVertices() +{ + size_t Offset = m_pModel->m_Lumps[ kVertices ]->iOffset; + for ( size_t idx = 0; idx < m_pModel->m_Vertices.size(); idx++ ) + { + sQ3BSPVertex *pVertex = new sQ3BSPVertex; + memcpy( pVertex, &m_Data[ Offset ], sizeof( sQ3BSPVertex ) ); + Offset += sizeof( sQ3BSPVertex ); + m_pModel->m_Vertices[ idx ] = pVertex; + } +} + +// ------------------------------------------------------------------------------------------------ +void Q3BSPFileParser::getIndices() +{ + ai_assert(nullptr != m_pModel ); + + sQ3BSPLump *lump = m_pModel->m_Lumps[ kMeshVerts ]; + size_t Offset = (size_t) lump->iOffset; + const size_t nIndices = lump->iSize / sizeof( int ); + m_pModel->m_Indices.resize( nIndices ); + memcpy( &m_pModel->m_Indices[ 0 ], &m_Data[ Offset ], lump->iSize ); +} + +// ------------------------------------------------------------------------------------------------ +void Q3BSPFileParser::getFaces() +{ + ai_assert(nullptr != m_pModel ); + + size_t Offset = m_pModel->m_Lumps[ kFaces ]->iOffset; + for ( size_t idx = 0; idx < m_pModel->m_Faces.size(); idx++ ) + { + sQ3BSPFace *pFace = new sQ3BSPFace; + memcpy( pFace, &m_Data[ Offset ], sizeof( sQ3BSPFace ) ); + m_pModel->m_Faces[ idx ] = pFace; + Offset += sizeof( sQ3BSPFace ); + } +} + +// ------------------------------------------------------------------------------------------------ +void Q3BSPFileParser::getTextures() +{ + ai_assert(nullptr != m_pModel ); + + size_t Offset = m_pModel->m_Lumps[ kTextures ]->iOffset; + for ( size_t idx=0; idx < m_pModel->m_Textures.size(); idx++ ) + { + sQ3BSPTexture *pTexture = new sQ3BSPTexture; + memcpy( pTexture, &m_Data[ Offset ], sizeof(sQ3BSPTexture) ); + m_pModel->m_Textures[ idx ] = pTexture; + Offset += sizeof(sQ3BSPTexture); + } +} + +// ------------------------------------------------------------------------------------------------ +void Q3BSPFileParser::getLightMaps() +{ + ai_assert(nullptr != m_pModel ); + + size_t Offset = m_pModel->m_Lumps[kLightmaps]->iOffset; + for ( size_t idx=0; idx < m_pModel->m_Lightmaps.size(); idx++ ) + { + sQ3BSPLightmap *pLightmap = new sQ3BSPLightmap; + memcpy( pLightmap, &m_Data[ Offset ], sizeof( sQ3BSPLightmap ) ); + Offset += sizeof( sQ3BSPLightmap ); + m_pModel->m_Lightmaps[ idx ] = pLightmap; + } +} + +// ------------------------------------------------------------------------------------------------ +void Q3BSPFileParser::getEntities() { + const int size = m_pModel->m_Lumps[ kEntities ]->iSize; + m_pModel->m_EntityData.resize( size ); + if ( size > 0 ) { + size_t Offset = m_pModel->m_Lumps[ kEntities ]->iOffset; + memcpy( &m_pModel->m_EntityData[ 0 ], &m_Data[ Offset ], sizeof( char ) * size ); + } +} + +// ------------------------------------------------------------------------------------------------ + +} // Namespace Assimp + +#endif // ASSIMP_BUILD_NO_Q3BSP_IMPORTER diff --git a/libs/assimp/code/AssetLib/Q3BSP/Q3BSPFileParser.h b/libs/assimp/code/AssetLib/Q3BSP/Q3BSPFileParser.h new file mode 100644 index 0000000..15cc751 --- /dev/null +++ b/libs/assimp/code/AssetLib/Q3BSP/Q3BSPFileParser.h @@ -0,0 +1,89 @@ +/* +Open Asset Import Library (assimp) +---------------------------------------------------------------------- + +Copyright (c) 2006-2022, assimp team + +All rights reserved. + +Redistribution and use of this software in source and binary forms, +with or without modification, are permitted provided that the +following conditions are met: + +* Redistributions of source code must retain the above + copyright notice, this list of conditions and the + following disclaimer. + +* Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the + following disclaimer in the documentation and/or other + materials provided with the distribution. + +* Neither the name of the assimp team, nor the names of its + contributors may be used to endorse or promote products + derived from this software without specific prior + written permission of the assimp team. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +---------------------------------------------------------------------- +*/ + +#ifndef ASSIMP_Q3BSPFILEPARSER_H_INC +#define ASSIMP_Q3BSPFILEPARSER_H_INC + +#include <assimp/BaseImporter.h> +#include <string> + +namespace Assimp +{ + class ZipArchiveIOSystem; + +namespace Q3BSP +{ + struct Q3BSPModel; + class ZipFile; +} + +// ------------------------------------------------------------------- +/// @brief This class implements th Q3DSP file parsing. +// ------------------------------------------------------------------- +class Q3BSPFileParser { +public: + Q3BSPFileParser( const std::string &rMapName, ZipArchiveIOSystem *pZipArchive ); + ~Q3BSPFileParser(); + Q3BSP::Q3BSPModel *getModel() const; + +protected: + bool readData(const std::string &rMapName); + bool parseFile(); + bool validateFormat(); + void getLumps(); + void countLumps(); + void getVertices(); + void getIndices(); + void getFaces(); + void getTextures(); + void getLightMaps(); + void getEntities(); + +private: + size_t m_sOffset; + std::vector<char> m_Data; + Q3BSP::Q3BSPModel *m_pModel; + ZipArchiveIOSystem *m_pZipArchive; +}; + +} // Namespace Assimp + +#endif // ASSIMP_Q3BSPFILEPARSER_H_INC |