/* * @brief Loads in the BSP and all sub-models for collision detection. This * function can also be used to initialize or clean up the collision model by * invoking with NULL. */ cm_bsp_model_t *Cm_LoadBspModel(const char *name, int64_t *size) { void *buf; memset(&cm_bsp, 0, sizeof(cm_bsp)); cm_vis = (d_bsp_vis_t *) cm_bsp.visibility; // clean up and return if (!name) { if (size) { *size = 0; } return &cm_bsp.models[0]; } // load the file const int64_t s = Fs_Load(name, &buf); if (s == -1) { Com_Error(ERR_DROP, "Couldn't load %s\n", name); } if (size) { *size = s; } // byte-swap the entire header d_bsp_header_t header = *(d_bsp_header_t *) buf; for (size_t i = 0; i < sizeof(d_bsp_header_t) / sizeof(int32_t); i++) { ((int32_t *) &header)[i] = LittleLong(((int32_t *) &header)[i]); } if (header.version != BSP_VERSION && header.version != BSP_VERSION_QUETOO) { Com_Error(ERR_DROP, "%s has unsupported version: %d\n", name, header.version); } g_strlcpy(cm_bsp.name, name, sizeof(cm_bsp.name)); cm_bsp.base = (byte *) buf; // load into heap Cm_LoadEntityString(&header.lumps[BSP_LUMP_ENTITIES]); Cm_LoadBspPlanes(&header.lumps[BSP_LUMP_PLANES]); Cm_LoadBspNodes(&header.lumps[BSP_LUMP_NODES]); Cm_LoadBspSurfaces(&header.lumps[BSP_LUMP_TEXINFO]); Cm_LoadBspLeafs(&header.lumps[BSP_LUMP_LEAFS]); Cm_LoadBspLeafBrushes(&header.lumps[BSP_LUMP_LEAF_BRUSHES]); Cm_LoadBspInlineModels(&header.lumps[BSP_LUMP_MODELS]); Cm_LoadBspBrushes(&header.lumps[BSP_LUMP_BRUSHES]); Cm_LoadBspBrushSides(&header.lumps[BSP_LUMP_BRUSH_SIDES]); Cm_LoadBspVisibility(&header.lumps[BSP_LUMP_VISIBILITY]); Cm_LoadBspAreas(&header.lumps[BSP_LUMP_AREAS]); Cm_LoadBspAreaPortals(&header.lumps[BSP_LUMP_AREA_PORTALS]); Fs_Free(buf); Cm_SetupBspBrushes(); Cm_InitBoxHull(); Cm_FloodAreas(); return &cm_bsp.models[0]; }
/** * @brief Loads in the BSP and all sub-models for collision detection. This * function can also be used to initialize or clean up the collision model by * invoking with NULL. */ cm_bsp_model_t *Cm_LoadBspModel(const char *name, int64_t *size) { // don't re-load if we don't have to if (name && !g_strcmp0(name, cm_bsp.name)) { if (size) { *size = cm_bsp.size; } return &cm_bsp.models[0]; } Cm_UnloadBspMaterials(); Bsp_UnloadLumps(&cm_bsp.bsp, BSP_LUMPS_ALL); // free dynamic memory Mem_Free(cm_bsp.planes); Mem_Free(cm_bsp.nodes); Mem_Free(cm_bsp.texinfos); Mem_Free(cm_bsp.leafs); Mem_Free(cm_bsp.leaf_brushes); Mem_Free(cm_bsp.models); Mem_Free(cm_bsp.brushes); Mem_Free(cm_bsp.brush_sides); Mem_Free(cm_bsp.areas); Mem_Free(cm_bsp.portal_open); memset(&cm_bsp, 0, sizeof(cm_bsp)); // clean up and return if (!name) { if (size) { *size = 0; } return &cm_bsp.models[0]; } // load the common BSP structure and the lumps we need bsp_header_t *file; if (!Fs_Load(name, (void **) &file)) { Com_Error(ERROR_DROP, "Couldn't load %s\n", name); } int32_t version = Bsp_Verify(file); if (version != BSP_VERSION && version != BSP_VERSION_QUETOO) { Fs_Free(file); Com_Error(ERROR_DROP, "%s has unsupported version: %d\n", name, version); } if (!Bsp_LoadLumps(file, &cm_bsp.bsp, CM_BSP_LUMPS)) { Fs_Free(file); Com_Error(ERROR_DROP, "Lump error loading %s\n", name); } // in theory, by this point the BSP is valid - now we have to create the cm_ // structures out of the raw file data if (size) { cm_bsp.size = *size = Bsp_Size(file); } g_strlcpy(cm_bsp.name, name, sizeof(cm_bsp.name)); Fs_Free(file); cm_bsp.materials = Cm_LoadBspMaterials(name); Cm_LoadBspPlanes(); Cm_LoadBspNodes(); Cm_LoadBspSurfaces(); Cm_LoadBspLeafs(); Cm_LoadBspLeafBrushes(); Cm_LoadBspInlineModels(); Cm_LoadBspBrushes(); Cm_LoadBspBrushSides(); Cm_LoadBspVisibility(); Cm_LoadBspAreas(); Cm_LoadBspAreaPortals(); Cm_SetupBspBrushes(); Cm_InitBoxHull(); Cm_FloodAreas(); return &cm_bsp.models[0]; }