Beispiel #1
0
/**
 * @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;
}
Beispiel #2
0
/**
 * @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;
}
Beispiel #3
0
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;
}
Beispiel #4
0
/**
 * @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;
}
Beispiel #5
0
/**
 * @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++;
	}
}
Beispiel #6
0
/**
 * @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);
}
Beispiel #7
0
/**
 * @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;
	}
}
Beispiel #8
0
/**
 * @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());
}
Beispiel #9
0
/**
 * @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;
}