/** * @brief Loads and registers a sound file for later use * @param[in] soundFile The name of the soundfile, relative to the sounds dir * @return The index of the loaded sample or 0 * @sa S_LoadSound */ int S_LoadSampleIdx (const char *soundFile) { Mix_Chunk *chunk; s_sample_t *sample; char name[MAX_QPATH]; unsigned hash; if (!s_env.initialized) return 0; Com_StripExtension(soundFile, name, sizeof(name)); sample = S_FindByName(name); if (sample) return sample->index; /* make sure the sound is loaded */ chunk = S_LoadSampleChunk(name); if (!chunk) return 0; /* couldn't load the sound's data */ hash = Com_HashKey(name, SAMPLE_HASH_SIZE); sample = (s_sample_t *)Mem_PoolAlloc(sizeof(*sample), cl_soundSysPool, 0); sample->name = Mem_PoolStrDup(name, cl_soundSysPool, 0); sample->chunk = chunk; sample->hashNext = sampleHash[hash]; sampleHash[hash] = sample; sampleIndex[++sampleIndexLast] = sample; sample->index = sampleIndexLast; return sample->index; }
/** * @brief Loads in a model for the given name * @param[in] filename Filename relative to base dir and with extension (models/model.md2) * @param[inout] mod Structure to initialize * @return True if the loading was succeed. True or false structure mod was edited. */ static bool R_LoadModel (model_t *mod, const char *filename) { byte *buf; int modfilelen; char animname[MAX_QPATH]; if (filename[0] == '\0') Com_Error(ERR_FATAL, "R_ModForName: NULL name"); /* load the file */ modfilelen = FS_LoadFile(filename, &buf); if (!buf) return false; OBJZERO(*mod); Q_strncpyz(mod->name, filename, sizeof(mod->name)); /* call the appropriate loader */ switch (LittleLong(*(unsigned *) buf)) { case IDALIASHEADER: /* MD2 header */ R_ModLoadAliasMD2Model(mod, buf, modfilelen, true); break; case DPMHEADER: R_ModLoadAliasDPMModel(mod, buf, modfilelen); break; case IDMD3HEADER: /* MD3 header */ R_ModLoadAliasMD3Model(mod, buf, modfilelen); break; case IDBSPHEADER: Com_Error(ERR_FATAL, "R_ModForName: don't load BSPs with this function"); break; default: { const char* ext = Com_GetExtension(filename); if (ext != NULL && !Q_strcasecmp(ext, "obj")) R_LoadObjModel(mod, buf, modfilelen); else Com_Error(ERR_FATAL, "R_ModForName: unknown fileid for %s", mod->name); } } /* load the animations */ Com_StripExtension(mod->name, animname, sizeof(animname)); Com_DefaultExtension(animname, sizeof(animname), ".anm"); /* try to load the animation file */ if (FS_CheckFile("%s", animname) != -1) { R_ModLoadAnims(&mod->alias, animname); } FS_FreeFile(buf); return true; }
int main (int argc, char **argv) { char bspFilename[MAX_OSPATH]; if (argc < 2) { Usage(); } com_genericPool = Mem_CreatePool("slicer"); com_fileSysPool = Mem_CreatePool("slicer filesys"); Swap_Init(); Mem_Init(); SL_Parameter(argc, argv); Com_StripExtension(config.filename, bspFilename, sizeof(bspFilename)); Com_DefaultExtension(bspFilename, sizeof(bspFilename), ".bsp"); FS_InitFilesystem(false); SL_BSPSlice(LoadBSPFile(bspFilename), config.thickness, config.scale, config.singleContour, config.multipleContour); Mem_Shutdown(); return EXIT_SUCCESS; }
/** * @brief Generate a list of textures that should have footsteps when walking on them * @param[in] filename Add this texture to the list of * textures where we should have footstep sounds for * @param[in] mipTexIndex The index in the textures array * @sa SV_GetFootstepSound * @sa Com_GetTerrainType */ static void GenerateFootstepList (const char* filename, int mipTexIndex) { if (!config.generateFootstepFile) return; if (textureref[mipTexIndex].footstepMarked) return; assert(filename); char fileBase[MAX_OSPATH]; Com_StripExtension(filename, fileBase, sizeof(fileBase)); ScopedFile f; FS_OpenFile(va("%s.footsteps", fileBase), &f, FILE_APPEND); if (!f) { Com_Printf("Could not open footstep file '%s.footsteps' for writing\n", fileBase); config.generateFootstepFile = false; return; } #ifdef _WIN32 FS_Printf(&f, "terrain %s {\n}\n\n", textureref[mipTexIndex].name); #else FS_Printf(&f, "%s\n", textureref[mipTexIndex].name); #endif footstepsCnt++; textureref[mipTexIndex].footstepMarked = true; }
/** * @brief Generates material files in case the settings can be guessed from map file */ static void GenerateMaterialFile (const char* filename, int mipTexIndex, side_t* s) { bool terrainByTexture = false; char fileBase[MAX_OSPATH], materialPath[MAX_OSPATH]; if (!config.generateMaterialFile) return; /* we already have a material definition for this texture */ if (textureref[mipTexIndex].materialMarked) return; assert(filename); Com_StripExtension(filename, fileBase, sizeof(fileBase)); Com_sprintf(materialPath, sizeof(materialPath), "materials/%s.mat", Com_SkipPath(fileBase)); ScopedFile f; FS_OpenFile(materialPath, &f, FILE_APPEND); if (!f) { Com_Printf("Could not open material file '%s' for writing\n", materialPath); config.generateMaterialFile = false; return; } if (strstr(textureref[mipTexIndex].name, "dirt") || strstr(textureref[mipTexIndex].name, "rock") || strstr(textureref[mipTexIndex].name, "grass")) { terrainByTexture = true; } if ((s->contentFlags & CONTENTS_TERRAIN) || terrainByTexture) { FS_Printf(&f, "{\n\tmaterial %s\n\t{\n\t\ttexture <fillme>\n\t\tterrain 0 64\n\t\tlightmap\n\t}\n}\n", textureref[mipTexIndex].name); textureref[mipTexIndex].materialMarked = true; materialsCnt++; } /* envmap for water surfaces */ if ((s->contentFlags & CONTENTS_WATER) || strstr(textureref[mipTexIndex].name, "glass") || strstr(textureref[mipTexIndex].name, "window")) { FS_Printf(&f, "{\n\tmaterial %s\n\tspecular 2.0\n\t{\n\t\tenvmap 0\n\t}\n}\n", textureref[mipTexIndex].name); textureref[mipTexIndex].materialMarked = true; materialsCnt++; } if (strstr(textureref[mipTexIndex].name, "wood")) { FS_Printf(&f, "{\n\tmaterial %s\n\tspecular 0.2\n}\n", textureref[mipTexIndex].name); textureref[mipTexIndex].materialMarked = true; materialsCnt++; } if (strstr(textureref[mipTexIndex].name, "wall")) { FS_Printf(&f, "{\n\tmaterial %s\n\tspecular 0.6\n\tbump 2.0\n}\n", textureref[mipTexIndex].name); textureref[mipTexIndex].materialMarked = true; materialsCnt++; } }
/** * @brief Export the day and night lightmap and direction data for the given map. * @note The bsp file must already be loaded. * @param bspFileName The path of the loaded bsp file. */ void ExportLightmaps (const char* bspFileName) { char path[MAX_QPATH], lightmapName[MAX_QPATH]; const char* fileName = Com_SkipPath(bspFileName); Com_FilePath(bspFileName, path, sizeof(path)); Com_StripExtension(fileName, lightmapName, sizeof(lightmapName)); /* note it */ Com_Printf("--- ExportLightmaps ---\n"); BuildFaceExtents(); ExportLightmap(path, lightmapName, true); ExportLightmap(path, lightmapName, false); }
/** * @brief Open a cinematic file and store status to a structure * @sa CIN_CloseCinematic */ void CIN_OpenCinematic (cinematic_t* cin, const char* fileName) { char name[MAX_OSPATH]; int status = 1; Com_StripExtension(fileName, name, sizeof(name)); /* If already playing a cinematic, stop it */ CIN_CloseCinematic(cin); if (FS_CheckFile("%s.roq", name) >= 0) status = CIN_ROQ_OpenCinematic(cin, va("%s.roq", name)); else if (FS_CheckFile("%s.ogm", name) >= 0) status = CIN_OGM_OpenCinematic(cin, va("%s.ogm", name)); if (status != 0) { Com_Printf("Could not load cinematic '%s'\n", name); cin->status = CIN_STATUS_INVALID; } }
/** * @sa M_Stop */ static void M_Start (const char* file) { if (Q_strnull(file)) return; if (!s_env.initialized) { Com_Printf("M_Start: No sound started!\n"); return; } if (music.playingStream || !music.playing) return; char name[MAX_QPATH]; Com_StripExtension(file, name, sizeof(name)); const size_t len = strlen(name); if (len + 4 >= MAX_QPATH) { Com_Printf("M_Start: MAX_QPATH exceeded: " UFO_SIZE_T "\n", len + 4); return; } /* we are already playing that track */ if (Q_streq(name, music.currentTrack) && music.data && Mix_PlayingMusic()) return; /* we are still playing some background track - fade it out */ if (music.data && Mix_PlayingMusic()) { if (!Mix_FadeOutMusic(1500)) M_Stop(); Q_strncpyz(music.nextTrack, name, sizeof(music.nextTrack)); return; } /* make really sure the last track is closed and freed */ M_Stop(); /* load it in */ byte* musicBuf; const int size = FS_LoadFile(va("music/%s.ogg", name), &musicBuf); if (size == -1) { Com_Printf("M_Start: Could not load '%s' background track!\n", name); return; } SDL_RWops* rw = SDL_RWFromMem(musicBuf, size); if (!rw) { Com_Printf("M_Start: Could not load music: 'music/%s'!\n", name); FS_FreeFile(musicBuf); return; } #if SDL_VERSION_ATLEAST(2,0,0) music.data = Mix_LoadMUS_RW(rw, 1); #else music.data = Mix_LoadMUS_RW(rw); #endif if (!music.data) { Com_Printf("M_Start: Could not load music: 'music/%s' (%s)!\n", name, Mix_GetError()); SDL_FreeRW(rw); FS_FreeFile(musicBuf); return; } Q_strncpyz(music.currentTrack, name, sizeof(music.currentTrack)); music.buffer = musicBuf; if (Mix_FadeInMusic(music.data, 1, 1500) == -1) Com_Printf("M_Start: Could not play music: 'music/%s' (%s)!\n", name, Mix_GetError()); }
/** * @brief Tries to load a mdx file that contains the normals and the tangents for a model. * @sa R_ModCalcNormalsAndTangents * @sa R_ModCalcUniqueNormalsAndTangents * @param mod The model to load the mdx file for */ qboolean R_ModLoadMDX (model_t *mod) { int i; for (i = 0; i < mod->alias.num_meshes; i++) { mAliasMesh_t *mesh = &mod->alias.meshes[i]; char mdxFileName[MAX_QPATH]; byte *buffer = NULL, *buf; const int32_t *intbuf; uint32_t version; int sharedTris[MAX_ALIAS_VERTS]; Com_StripExtension(mod->name, mdxFileName, sizeof(mdxFileName)); Com_DefaultExtension(mdxFileName, sizeof(mdxFileName), ".mdx"); if (FS_LoadFile(mdxFileName, &buffer) == -1) return qfalse; buf = buffer; if (strncmp((const char *) buf, IDMDXHEADER, strlen(IDMDXHEADER))) Com_Error(ERR_DROP, "No mdx file buffer given"); buffer += strlen(IDMDXHEADER) * sizeof(char); version = LittleLong(*(uint32_t*) buffer); if (version != MDX_VERSION) Com_Error(ERR_DROP, "Invalid version of the mdx file, expected %i, found %i", MDX_VERSION, version); buffer += sizeof(uint32_t); intbuf = (const int32_t *) buffer; mesh->num_verts = LittleLong(*intbuf); if (mesh->num_verts <= 0 || mesh->num_verts > MAX_ALIAS_VERTS) Com_Error(ERR_DROP, "mdx file for %s has to many (or no) vertices: %i", mod->name, mesh->num_verts); intbuf++; mesh->num_indexes = LittleLong(*intbuf); intbuf++; mesh->indexes = (int32_t *)Mem_PoolAlloc(sizeof(int32_t) * mesh->num_indexes, vid_modelPool, 0); mesh->revIndexes = (mIndexList_t *)Mem_PoolAlloc(sizeof(mIndexList_t) * mesh->num_verts, vid_modelPool, 0); mesh->vertexes = (mAliasVertex_t *)Mem_PoolAlloc(sizeof(mAliasVertex_t) * mod->alias.num_frames * mesh->num_verts, vid_modelPool, 0); /* load index that maps triangle verts to Vertex objects */ for (i = 0; i < mesh->num_indexes; i++) { mesh->indexes[i] = LittleLong(*intbuf); intbuf++; } for (i = 0; i < mesh->num_verts; i++) sharedTris[i] = 0; /* set up reverse-index that maps Vertex objects to a list of triangle verts */ for (i = 0; i < mesh->num_indexes; i++) sharedTris[mesh->indexes[i]]++; for (i = 0; i < mesh->num_verts; i++) { mesh->revIndexes[i].length = 0; mesh->revIndexes[i].list = (int32_t *)Mem_PoolAlloc(sizeof(int32_t) * sharedTris[i], vid_modelPool, 0); } for (i = 0; i < mesh->num_indexes; i++) mesh->revIndexes[mesh->indexes[i]].list[mesh->revIndexes[mesh->indexes[i]].length++] = i; FS_FreeFile(buf); } return qtrue; }