Exemple #1
0
/**
 * @brief Renders text and images
 * @sa SEQ_InitStartup
 * @param[in] context Sequence context
 * @param[in] backgroundObjects if true, draw background objects, else display foreground objects
 */
static void SEQ_Render2D (sequenceContext_t *context, bool backgroundObjects)
{
	seq2D_t *s2d;
	int i, j;
	int height = 0;

	/* add texts */
	for (i = 0, s2d = context->obj2Ds; i < context->numObj2Ds; i++, s2d++) {
		if (!s2d->inuse)
			continue;
		if (backgroundObjects != s2d->inBackground)
			continue;

		if (s2d->relativePos && height > 0) {
			s2d->pos[1] += height;
			s2d->relativePos = false;
		}
		/* advance in time */
		for (j = 0; j < 4; j++) {
			s2d->color[j] += cls.frametime * s2d->fade[j];
			if (s2d->color[j] < 0.0)
				s2d->color[j] = 0.0;
			else if (s2d->color[j] > 1.0)
				s2d->color[j] = 1.0;
		}
		for (j = 0; j < 2; j++) {
			s2d->pos[j] += cls.frametime * s2d->speed[j];
			s2d->size[j] += cls.frametime * s2d->enlarge[j];
		}

		/* outside the screen? */
		/** @todo We need this check - but this does not work */
		/*if (s2d->pos[1] >= VID_NORM_HEIGHT || s2d->pos[0] >= VID_NORM_WIDTH)
			continue;*/

		/* render */
		R_Color(s2d->color);

		/* image can be background */
		if (s2d->image[0] != '\0') {
			const image_t *image = R_FindImage(s2d->image, it_pic);
			R_DrawImage(s2d->pos[0], s2d->pos[1], image);
		}

		/* bgcolor can be overlay */
		if (s2d->bgcolor[3] > 0.0)
			R_DrawFill(s2d->pos[0], s2d->pos[1], s2d->size[0], s2d->size[1], s2d->bgcolor);

		/* render */
		R_Color(s2d->color);

		/* gettext placeholder */
		if (s2d->text) {
			int maxWidth = (int) s2d->size[0];
			if (maxWidth <= 0)
				maxWidth = VID_NORM_WIDTH;
			height += UI_DrawString(s2d->font, s2d->align, s2d->pos[0], s2d->pos[1], s2d->pos[0], maxWidth, -1 /** @todo use this for some nice line spacing */, _(s2d->text));
		}
	}
	R_Color(NULL);
}
Exemple #2
0
/**
 * @brief Draw the day and night images of a flat geoscape
 * multitexture feature is used to blend the images
 * @sa R_Draw3DGlobe
 * @param[in] p The horizontal shift of the night map
 * @param[in] cx The x texture coordinate
 * @param[in] cy The y texture coordinate
 * @param[in] iz The zoomlevel of the geoscape - see ccs.zoom
 * @param[in] map The geoscape map to draw (can be changed in the campaign definition)
 * @param[in] overlayNation,overlayXVI,overlayRadar Whether these overlays should be drawn or not
 */
void R_DrawFlatGeoscape (const vec2_t nodePos, const vec2_t nodeSize, float p, float cx, float cy, float iz, const char *map, bool overlayNation, bool overlayXVI, bool overlayRadar, image_t *r_dayandnightTexture, image_t *r_xviTexture, image_t *r_radarTexture)
{
	image_t *gl;
	float geoscape_texcoords[4 * 2];
	short geoscape_verts[4 * 2];

	/* normalize */
	const float nx = nodePos[0] * viddef.rx;
	const float ny = nodePos[1] * viddef.ry;
	const float nw = nodeSize[0] * viddef.rx;
	const float nh = nodeSize[1] * viddef.ry;

	/* load day image */
	gl = R_FindImage(va("pics/geoscape/%s_day", map), it_wrappic);
	if (gl == r_noTexture)
		Com_Error(ERR_FATAL, "Could not load geoscape day image");

	/* alter the array pointers */
	glVertexPointer(2, GL_SHORT, 0, geoscape_verts);
	R_BindArray(GL_TEXTURE_COORD_ARRAY, GL_FLOAT, geoscape_texcoords);

	geoscape_texcoords[0] = cx - iz;
	geoscape_texcoords[1] = cy - iz;
	geoscape_texcoords[2] = cx + iz;
	geoscape_texcoords[3] = cy - iz;
	geoscape_texcoords[4] = cx + iz;
	geoscape_texcoords[5] = cy + iz;
	geoscape_texcoords[6] = cx - iz;
	geoscape_texcoords[7] = cy + iz;

	geoscape_verts[0] = nx;
	geoscape_verts[1] = ny;
	geoscape_verts[2] = nx + nw;
	geoscape_verts[3] = ny;
	geoscape_verts[4] = nx + nw;
	geoscape_verts[5] = ny + nh;
	geoscape_verts[6] = nx;
	geoscape_verts[7] = ny + nh;

	/* draw day image */
	R_BindTexture(gl->texnum);
	glDrawArrays(GL_TRIANGLE_FAN, 0, 4);

	refdef.batchCount++;

	/* draw night map */
	gl = R_FindImage(va("pics/geoscape/%s_night", map), it_wrappic);
	/* maybe the campaign map doesn't have a night image */
	if (gl != r_noTexture) {
		float geoscape_nighttexcoords[4 * 2];

		R_BindTexture(gl->texnum);
		R_EnableTexture(&texunit_lightmap, true);
		R_SelectTexture(&texunit_lightmap);

		geoscape_nighttexcoords[0] = geoscape_texcoords[0] + p;
		geoscape_nighttexcoords[1] = geoscape_texcoords[1];
		geoscape_nighttexcoords[2] = geoscape_texcoords[2] + p;
		geoscape_nighttexcoords[3] = geoscape_texcoords[3];
		geoscape_nighttexcoords[4] = geoscape_texcoords[4] + p;
		geoscape_nighttexcoords[5] = geoscape_texcoords[5];
		geoscape_nighttexcoords[6] = geoscape_texcoords[6] + p;
		geoscape_nighttexcoords[7] = geoscape_texcoords[7];

		R_BindArray(GL_TEXTURE_COORD_ARRAY, GL_FLOAT, geoscape_nighttexcoords);

		R_BindTexture(r_dayandnightTexture->texnum);

		R_SelectTexture(&texunit_diffuse);
		glDrawArrays(GL_TRIANGLE_FAN, 0, 4);

		refdef.batchCount++;

		R_SelectTexture(&texunit_lightmap);
		R_BindArray(GL_TEXTURE_COORD_ARRAY, GL_FLOAT, geoscape_texcoords);

		R_EnableTexture(&texunit_lightmap, false);
	}

	/* draw nation overlay */
	if (overlayNation) {
		gl = R_FindImage(va("pics/geoscape/%s_nations_overlay", map), it_wrappic);
		if (gl == r_noTexture)
			Com_Error(ERR_FATAL, "Could not load geoscape nation overlay image");

		/* draw day image */
		R_BindTexture(gl->texnum);
		glDrawArrays(GL_TRIANGLE_FAN, 0, 4);

		refdef.batchCount++;
	}

	/* draw XVI image */
	if (overlayXVI) {
		gl = R_FindImage(va("pics/geoscape/%s_xvi_overlay", map), it_wrappic);
		if (gl == r_noTexture)
			Com_Error(ERR_FATAL, "Could not load xvi overlay image");

		R_BindTexture(gl->texnum);

		R_EnableTexture(&texunit_lightmap, true);
		R_BindLightmapTexture(r_xviTexture->texnum);

		glDrawArrays(GL_TRIANGLE_FAN, 0, 4);

		refdef.batchCount++;

		R_EnableTexture(&texunit_lightmap, false);
	}

	/* draw radar image */
	if (overlayRadar) {
		R_BindTexture(r_radarTexture->texnum);
		glDrawArrays(GL_TRIANGLE_FAN, 0, 4);

		refdef.batchCount++;
	}

	/* and restore them */
	R_BindDefaultArray(GL_TEXTURE_COORD_ARRAY);
	R_BindDefaultArray(GL_VERTEX_ARRAY);
}
Exemple #3
0
/**
 * @brief Draws shadow and highlight effects for the entities (actors)
 * @note The origins are already transformed
 */
void R_DrawEntityEffects (void)
{
	const int mask = r_stencilshadows->integer ? RF_BLOOD : (RF_SHADOW | RF_BLOOD);
	GLint oldDepthFunc;
	glGetIntegerv(GL_DEPTH_FUNC, &oldDepthFunc);

	R_EnableBlend(true);

	if (actorIndicator == nullptr) {
		selectedActorIndicator = R_FindImage("pics/sfx/actor_selected", it_effect);
		actorIndicator = R_FindImage("pics/sfx/actor", it_effect);
	}

	for (int i = 0; i < refdef.numEntities; i++) {
		const entity_t* e = &r_entities[i];

		if (e->flags <= RF_BOX)
			continue;

		glPushMatrix();
		glMultMatrixf(e->transform.matrix);

		if (e->flags & mask) {
			const vec3_t points[] = { { -18.0, 14.0, -28.5 }, { 10.0, 14.0, -28.5 }, { 10.0, -14.0, -28.5 }, { -18.0,
					-14.0, -28.5 } };
			/** @todo use default_texcoords */
			const vec2_t texcoords[] = { { 0.0, 1.0 }, { 1.0, 1.0 }, { 1.0, 0.0 }, { 0.0, 0.0 } };

			if (e->flags & RF_SHADOW) {
				R_BindTexture(shadow->texnum);
			} else {
				assert(e->texture);
				R_BindTexture(e->texture->texnum);
			}

			R_BindArray(GL_TEXTURE_COORD_ARRAY, GL_FLOAT, texcoords);
			R_BindArray(GL_VERTEX_ARRAY, GL_FLOAT, points);
			glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
			R_BindDefaultArray(GL_TEXTURE_COORD_ARRAY);
			R_BindDefaultArray(GL_VERTEX_ARRAY);

			refdef.batchCount++;
		}

		if (e->flags & RF_ACTOR) {
			const float size = 15.0;
			int texnum;
			/* draw the circles for team-members and allied troops */
			vec4_t color = {1, 1, 1, 1};
			const vec3_t points[] = { { -size, size, -SELECTION_DELTA }, { size, size, -SELECTION_DELTA }, { size, -size,
					-SELECTION_DELTA }, { -size, -size, -SELECTION_DELTA } };
			/** @todo use default_texcoords */
			const vec2_t texcoords[] = { { 0.0, 1.0 }, { 1.0, 1.0 }, { 1.0, 0.0 }, { 0.0, 0.0 } };

			if (e->flags & RF_SELECTED)
				Vector4Set(color, 0, 1, 0, 0.5);
			else if (e->flags & RF_MEMBER)
				Vector4Set(color, 0, 0.8, 0, 0.5);
			else if (e->flags & RF_ALLIED)
				Vector4Set(color, 0, 1, 0.5, 0.5);
			else if (e->flags & RF_NEUTRAL)
				Vector4Set(color, 1, 1, 0, 0.5);
			else if (e->flags & RF_OPPONENT)
				Vector4Set(color, 1, 0, 0, 0.5);
			else
				Vector4Set(color, 0.3, 0.3, 0.3, 0.5);

			if (e->flags & RF_SELECTED)
				texnum = selectedActorIndicator->texnum;
			else
				texnum = actorIndicator->texnum;

			R_BindTexture(texnum);
			R_Color(color);
			R_EnableDrawAsGlow(true);

			/* circle points */
			R_BindArray(GL_TEXTURE_COORD_ARRAY, GL_FLOAT, texcoords);
			R_BindArray(GL_VERTEX_ARRAY, GL_FLOAT, points);

			glDrawArrays(GL_TRIANGLE_FAN, 0, 4);

			refdef.batchCount++;

			/* add transparency when something is in front of the circle */
			color[3] *= 0.25;
			R_Color(color);
			glDepthFunc(GL_GREATER);
			glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
			glDepthFunc(oldDepthFunc);

			refdef.batchCount++;

			R_BindDefaultArray(GL_TEXTURE_COORD_ARRAY);
			R_BindDefaultArray(GL_VERTEX_ARRAY);

			R_Color(nullptr);
			R_EnableDrawAsGlow(false);
		}
		glPopMatrix();
	}
}
Exemple #4
0
/**
 * @brief Calculate some radar values that won't change during a mission
 * @note Called for every new map (client_state_t is wiped with every
 * level change)
 */
static void UI_InitRadar (const uiNode_t *node)
{
    int i, j;
    const vec3_t offset = {MAP_SIZE_OFFSET, MAP_SIZE_OFFSET, MAP_SIZE_OFFSET};
    float distAB, distBC;
    vec2_t gridSize;		/**< Size of the whole grid (in tiles units) */
    vec2_t nodepos;
    vec2_t min;
    vec2_t max;

    UI_FreeRadarImages();
    UI_BuildRadarImageList(CL_GetConfigString(CS_TILES), CL_GetConfigString(CS_POSITIONS));

    UI_GetNodeAbsPos(node, nodepos);
    radar.x = nodepos[0] + node->box.size[0] / 2;
    radar.y = nodepos[1] + node->box.size[1] / 2;

    /* only check once per map whether all the needed images exist */
    for (j = 0; j < radar.numImages; j++) {
        hudRadarImage_t *tile = &radar.images[j];
        /* map_mins, map_maxs */
        for (i = 0; i < PATHFINDING_HEIGHT; i++) {
            char imagePath[MAX_QPATH];
            const image_t *image;
            if (!UI_CheckRadarImage(tile->name, i + 1)) {
                if (i == 0) {
                    /* there should be at least one level */
                    Com_Printf("No radar images for map: '%s'\n", tile->name);
                    radar.numImages = 0;
                    return;
                }
                continue;
            }

            Com_sprintf(imagePath, sizeof(imagePath), "radars/%s_%i", tile->name, i + 1);
            tile->path[i] = Mem_StrDup(imagePath);
            tile->maxlevel++;

            image = R_FindImage(va("pics/%s", tile->path[i]), it_pic);
            tile->width = image->width;
            tile->height = image->height;
            if (tile->isTile) {
                tile->gridWidth = round(image->width / 94.0f);
                tile->gridHeight = round(image->height / 94.0f);
                tile->mapWidth = tile->gridWidth * 8 * UNIT_SIZE;
                tile->mapHeight = tile->gridHeight * 8 * UNIT_SIZE;
            } else {
                tile->mapX = cl.mapData->mapMin[0];
                tile->mapY = cl.mapData->mapMin[1];
                tile->mapWidth = cl.mapData->getWidthX();
                tile->mapHeight = cl.mapData->getWidthY();
            }
        }
        if (tile->isTile) {
            tile->mapY = cl.mapData->mapMax[1] - tile->mapY - tile->mapHeight;
        }
    }

    /* center tiles into the minMap/maxMap */
    Vector2Copy(cl.mapData->mapMax, min);
    Vector2Copy(cl.mapData->mapMin, max);
    for (j = 0; j < radar.numImages; j++) {
        hudRadarImage_t *tile = &radar.images[j];
        if (tile->mapX < min[0])
            min[0] = tile->mapX;
        if (tile->mapY < min[1])
            min[1] = tile->mapY;
        if (tile->mapX + tile->mapWidth > max[0])
            max[0] = tile->mapX + tile->mapWidth;
        if (tile->mapY + tile->mapHeight > max[1])
            max[1] = tile->mapY + tile->mapHeight;
    }
    /* compute translation */
    min[0] = cl.mapData->mapMin[0] + (cl.mapData->getWidthX() - (max[0] - min[0])) * 0.5 - min[0];
    min[1] = cl.mapData->mapMin[1] + (cl.mapData->getWidthY() - (max[1] - min[1])) * 0.5 - min[1];
    for (j = 0; j < radar.numImages; j++) {
        hudRadarImage_t *tile = &radar.images[j];
        tile->mapX += min[0];
        tile->mapY += min[1];
    }

    /* get the three points of the triangle */
    VectorSubtract(cl.mapData->mapMin, offset, radar.a);
    VectorAdd(cl.mapData->mapMax, offset, radar.c);
    VectorSet(radar.b, radar.c[0], radar.a[1], 0);

    distAB = (Vector2Dist(radar.a, radar.b) / UNIT_SIZE);
    distBC = (Vector2Dist(radar.b, radar.c) / UNIT_SIZE);

    UI_GetRadarWidth(node, gridSize);

    /* get the dimensions for one grid field on the radar map */
    radar.gridWidth = radar.w / distAB;
    radar.gridHeight = radar.h / distBC;

    /* shift the x and y values according to their grid width/height and
     * their gridX and gridY position */
    {
        const float radarLength = std::max(1.0, fabs(gridSize[0]));
        const float radarHeight = std::max(1.0, fabs(gridSize[1]));
        /* image grid relations */
        const float gridFactorX = radar.w / radarLength;
        const float gridFactorY = radar.h / radarHeight;
        for (j = 0; j < radar.numImages; j++) {
            hudRadarImage_t *image = &radar.images[j];

            image->x = (image->gridX - radar.gridMin[0]) * gridFactorX;
            image->y = radar.h - (image->gridY - radar.gridMin[1]) * gridFactorY - image->height;
        }
    }

    /* now align the screen coordinates like it's given by the node */
    radar.x -= (radar.w / 2);
    radar.y -= (radar.h / 2);
}
Exemple #5
0
/**
 * @brief responsible for drawing the 3d globe on geoscape
 * param[in] rotate the rotate angle of the globe
 * param[in] zoom the current globe zoon
 * param[in] map the prefix of the map to use (image must be at base/pics/menu/\<map\>_[day|night])
 * @sa R_DrawFlatGeoscape
 * @sa R_SphereGenerate
 */
void R_Draw3DGlobe (const vec2_t pos, const vec2_t size, int day, int second, const vec3_t rotate, float zoom, const char *map,
					bool disableSolarRender, float ambient, bool overlayNation, bool overlayXVI, bool overlayRadar, image_t *r_xviTexture,
					image_t *r_radarTexture, bool renderNationGlow)
{
	/* globe scaling */
	const float fullscale = zoom / STANDARD_3D_ZOOM;

	/* lighting colors */
	static const vec4_t diffuseLightColor = { 1.75f, 1.75f, 1.75f, 1.0f };
	static const vec4_t specularLightColor = { 2.0f, 1.9f, 1.7f, 1.0f };
	static const vec4_t darknessLightColor = { 0.0f, 0.0f, 0.0f, 1.0f };
	static const vec4_t brightDiffuseLightColor = { 5.0f, 5.0f, 5.0f, 1.0f };
	const vec4_t ambientLightColor = { ambient + 0.2f, ambient + 0.2f, ambient + 0.2f, ambient + 0.2f };
	/* billboard textures */
	image_t *starfield;
	image_t *halo;
	image_t *sun;
	image_t *sunOverlay;

	/* set distance of the sun and moon to make them static on starfield when
	 * time is stoped.  this distance should be used for any celestial body
	 * considered at infinite location (sun, moon) */
	static const float celestialDist = 1.37f * SKYBOX_HALFSIZE;
	static const float moonSize = 0.025f;
	vec4_t sunPos;
	vec4_t antiSunPos;
	vec4_t moonLoc;
	vec4_t sunLoc;

	/* normalize */
	const float nx = pos[0] * viddef.rx;
	const float ny = pos[1] * viddef.ry;
	const float nw = size[0] * viddef.rx;
	const float nh = size[1] * viddef.ry;

	/* Earth center is in the middle of node.
	 * Due to Orthographic view, this is also camera position */
	const vec3_t earthPos = { nx + nw / 2.0f, ny + nh / 2.0f, 0.0f };

	/* estimate the progress through the current season so we can do
	 * smooth transitions between textures.  Currently there are 12
	 * "seasons", because we have one image per Earth-month. */
	const float season = (float) (day % DAYS_PER_YEAR) / ((float) (DAYS_PER_YEAR) / (float) (SEASONS_PER_YEAR));
	const int currSeason = (int) floorf(season) % SEASONS_PER_YEAR;
	const int nextSeason = (int) ceilf(season) % SEASONS_PER_YEAR;
	const float seasonProgress = season - (float) currSeason;

	/* Compute sun position in absolute frame */
	const float q = (day % DAYS_PER_YEAR * SECONDS_PER_DAY + second) * (2.0f * M_PI / (SECONDS_PER_DAY * DAYS_PER_YEAR));	/* sun rotation (year) */
	const float a = cos(q) * SIN_ALPHA;	/* due to earth obliquity */
	const float sqrta = sqrt(0.5f * (1 - a * a));

	/* earth rotation (day) */
	const float p = (second - SECONDS_PER_DAY / 4) * (2.0f * M_PI / SECONDS_PER_DAY);
	/* lunar orbit */
	const float m = p + (((double)((10 * day % 249) / 10.0f) + ((double)second / (double)SECONDS_PER_DAY)) / 24.9f) * (2.0f * M_PI);

	glPushMatrix();
	glMatrixMode(GL_TEXTURE);
	glLoadIdentity();
	glMatrixMode(GL_MODELVIEW);
	glDisable(GL_LIGHTING);
	/* draw the starfield, rotating with the planet */
	starfield = R_FindImage(va("pics/geoscape/%s_stars", map), it_wrappic);
	if (starfield != r_noTexture)
		R_DrawStarfield(starfield->texnum, earthPos, rotate, p);

	glPopMatrix();

	/* set up position vectors for celestial bodies */
	Vector4Set(sunPos, cos(p) * sqrta, -sin(p) * sqrta, a, 0);
	Vector4Set(antiSunPos, -cos(p) * sqrta, sin(p) * sqrta, -a, 0);

	/* Rotate the sun in the relative frame of player view, to get sun location */
	R_RotateCelestialBody(sunPos, sunLoc, rotate, earthPos, 1.0f);
	/* load sun texture image */
	sun = R_FindImage(va("pics/geoscape/%s_sun", map), it_wrappic);
	sunOverlay = R_FindImage(va("pics/geoscape/%s_sun_overlay", map), it_pic);
	if (sun != r_noTexture && sunOverlay != r_noTexture && sunLoc[2] > 0 && !disableSolarRender) {
		const int sunx = earthPos[0] + viddef.rx * (-128.0f + celestialDist * (sunLoc[0] - earthPos[0]));
		const int suny = earthPos[1] + viddef.ry * (-128.0f + celestialDist * (sunLoc[1] - earthPos[1]));

		R_DrawTexture(sunOverlay->texnum, sunx, suny, 256.0f * viddef.rx, 256.0f * viddef.ry);
		R_DrawBuffers(2);
		R_DrawTexture(sun->texnum, sunx, suny, 256.0 * viddef.rx, 256.0 * viddef.ry);
		R_DrawBuffers(1);
	}

	/* calculate position of the moon (it rotates around earth with a period of
	 * about 24.9 h, and we must take day into account to avoid moon to "jump"
	 * every time the day is changing) */
	VectorSet(moonLoc, cos(m) * sqrta, -sin(m) * sqrta, a);
	R_RotateCelestialBody(moonLoc, moonLoc, rotate, earthPos, celestialDist);

	/* free last month's texture image */
	if (r_globeEarth.season != currSeason) {
		r_globeEarth.season = currSeason;
		R_FreeImage(r_globeEarth.texture);
	}

	/* load diffuse texture map (with embedded night-glow map as alpha channel) */
	r_globeEarth.texture = R_FindImage(va("pics/geoscape/%s/%s_season_%02d", r_config.lodDir, map, currSeason), it_wrappic);
	if (r_globeEarth.texture == r_noTexture)
		Com_Error(ERR_FATAL, "Could not find pics/geoscape/%s/%s_season_%02d\n", r_config.lodDir, map, currSeason);

	/* set up for advanced GLSL rendering if we have the capability */
	if (r_programs->integer) {
		r_globeEarth.glslProgram = r_state.geoscape_program;
		/* load earth image for the next month so we can blend them */
		r_globeEarth.blendTexture = R_FindImage(va("pics/geoscape/%s/%s_season_%02d", r_config.lodDir, map, nextSeason), it_wrappic);
		if (r_globeEarth.blendTexture == r_noTexture)
			Com_Error(ERR_FATAL, "Could not find pics/geoscape/%s/%s_season_%02d\n", r_config.lodDir, map, nextSeason);

		/* load normal map (with embedded gloss map as alpha channel) */
		r_globeEarth.normalMap = R_FindImage(va("pics/geoscape/%s/%s_bump", r_config.lodDir, map), it_wrappic);
		if (r_globeEarth.normalMap == r_noTexture)
			r_globeEarth.normalMap = nullptr;

		/* weight the blending based on how much of the month has elapsed */
		r_globeEarth.blendScale = seasonProgress;
		/* set up lights for nighttime city glow */
		VectorCopy(antiSunPos, r_globeEarth.nightLightPos);
		glLightfv(GL_LIGHT1, GL_AMBIENT, darknessLightColor);
		glLightfv(GL_LIGHT1, GL_DIFFUSE, brightDiffuseLightColor);
		glLightfv(GL_LIGHT1, GL_SPECULAR, darknessLightColor);

		r_globeEarth.glowScale = 0.7f;
	}

	/* load moon texture image */
	r_globeMoon.texture = R_FindImage(va("pics/geoscape/%s_moon", map), it_wrappic);

	/* globe texture scaling */
	glMatrixMode(GL_TEXTURE);
	glLoadIdentity();
	glScalef(2.0f, 1.0f, 1.0f);
	glMatrixMode(GL_MODELVIEW);

	/* enable the lighting */
	glEnable(GL_LIGHTING);
	glEnable(GL_LIGHT0);
	glLightfv(GL_LIGHT0, GL_DIFFUSE, diffuseLightColor);
	glLightfv(GL_LIGHT0, GL_AMBIENT, ambientLightColor);
	glLightfv(GL_LIGHT0, GL_SPECULAR, specularLightColor);

	/* draw the moon */
	if (r_globeMoon.texture != r_noTexture && moonLoc[2] > 0 && !disableSolarRender)
		R_SphereRender(&r_globeMoon, moonLoc, rotate, moonSize, sunPos);

	/* activate depth to hide 3D models behind earth */
	glEnable(GL_DEPTH_TEST);

	/* draw the earth */
	R_DrawBuffers(2);
#if 0 /* old rendering code which doesn't render city lights in FFP */
	if (r_programs->integer == 0) /* ignore alpha channel, since the city-light map is stored there */
		glBlendFunc(GL_ONE, GL_ZERO);

	R_SphereRender(&r_globeEarth, earthPos, rotate, fullscale, sunPos);

	if (r_programs->integer == 0) /* restore default blend function */
		glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
#else /* new which does render city lights in FFP */
	if (r_programs->integer == 0) {
		/* set up rendering of city lights map, which is stored in alpha channel; OpenGL 1.3 required */
		R_SelectTexture(&texunit_diffuse); /* select texture to edit texture environment for */
		glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE); /* enable color combiner */
		/* setup texture combiner to blend between daylight diffuse map stored in the RGB channels of the diffuse texture
		 * and the monochomatic emission map (which simulates city lights) stored in the alpha channel;
		 * incoming color value is the blend factor.
		 */
		glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB, GL_TEXTURE); /* set day color as blending target*/
		glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_RGB, GL_SRC_COLOR);
		glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_RGB, GL_TEXTURE); /* set night color as blending source */
		glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND1_RGB, GL_SRC_ALPHA);
		glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE2_RGB, GL_PREVIOUS); /* set incoming color as blending factor */
		glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND2_RGB, GL_SRC_COLOR);
		glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB, GL_INTERPOLATE); /* set blending mode to interpolation from src1 to src0 */
		/* copy alpha from incoming color, bypassing the value read from texture, which is not a "real" alpha anyway */
		glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_ALPHA, GL_REPLACE);
		glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA, GL_PREVIOUS);
		glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_ALPHA, GL_SRC_ALPHA);
	}

	R_SphereRender(&r_globeEarth, earthPos, rotate, fullscale, sunPos);

	if (r_programs->integer == 0) { /* disable combiner */
		R_SelectTexture(&texunit_diffuse);
		glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
	}
#endif

	r_globeEarthAtmosphere.texture = R_FindImage(va("pics/geoscape/%s_atmosphere", map), it_wrappic);

	/* Draw earth atmosphere */
	/** @todo render atmosphere glow even when postprocessing is disabled */
	if (r_programs->integer && r_postprocess->integer) {
		r_globeEarthAtmosphere.normalMap = r_globeEarth.normalMap;
		r_globeEarthAtmosphere.glowScale = 1.0;
		r_globeEarthAtmosphere.blendScale = -1.0;
		r_globeEarthAtmosphere.glslProgram = r_state.atmosphere_program;
		R_SphereRender(&r_globeEarthAtmosphere, earthPos, rotate, fullscale, sunPos);
	} else {
		halo = R_FindImage("pics/geoscape/map_earth_halo", it_pic);
		if (halo != r_noTexture) {
			/** @todo Replace this magic number with some speaking constant */
			const float earthSizeX = fullscale * 20500.0f * viddef.rx;
			const float earthSizeY = fullscale * 20500.0f * viddef.ry;
			glMatrixMode(GL_TEXTURE);
			glPushMatrix();
			glLoadIdentity();
			glDisable(GL_LIGHTING);

			R_DrawTexture(halo->texnum, earthPos[0] - earthSizeX * 0.5f, earthPos[1] - earthSizeY * 0.5f, earthSizeX, earthSizeY);
			glEnable(GL_LIGHTING);
			glPopMatrix();
			glMatrixMode(GL_MODELVIEW);
		}
	}

	R_DrawBuffers(1);
	glDisable(GL_DEPTH_TEST);

	/* draw nation overlay */
	if (overlayNation) {
		r_globeEarth.overlay = R_FindImage(va("pics/geoscape/%s_nations_overlay", map), it_wrappic);
		if (r_globeEarth.overlay == r_noTexture)
			Com_Error(ERR_FATAL, "Could not load geoscape nation overlay image");

		R_SphereRender(&r_globeEarth, earthPos, rotate, fullscale, sunPos);

		if (renderNationGlow) {
			/* draw glowing borders */
			r_globeEarth.overlay = R_FindImage(va("pics/geoscape/%s_nations_overlay_glow", map), it_wrappic);
			if (r_globeEarth.overlay == r_noTexture)
				Com_Error(ERR_FATAL, "Could not load geoscape nation overlay glow image");

			R_DrawBuffers(2);
			glDisable(GL_LIGHTING);
			R_SphereRender(&r_globeEarth, earthPos, rotate, fullscale, sunPos);
			glEnable(GL_LIGHTING);
			R_DrawBuffers(1);
		}

		r_globeEarth.overlay = nullptr;
	}
	/* draw XVI overlay */
	if (overlayXVI) {
		r_globeEarth.overlay = R_FindImage(va("pics/geoscape/%s_xvi_overlay", map), it_wrappic);
		r_globeEarth.overlayAlphaMask = r_xviTexture;
		assert(r_globeEarth.overlayAlphaMask);
		R_SphereRender(&r_globeEarth, earthPos, rotate, fullscale, sunPos);
		r_globeEarth.overlayAlphaMask = nullptr;
		r_globeEarth.overlay = nullptr;
	}
	/* draw radar overlay */
	if (overlayRadar) {
		r_globeEarth.overlay = r_radarTexture;
		assert(r_globeEarth.overlay);
		R_SphereRender(&r_globeEarth, earthPos, rotate, fullscale, sunPos);
		r_globeEarth.overlay = nullptr;
	}

	/* disable 3d geoscape lighting */
	glDisable(GL_LIGHTING);

	/* restore the previous matrix */
	glMatrixMode(GL_TEXTURE);
	glLoadIdentity();
	glMatrixMode(GL_MODELVIEW);
}
Exemple #6
0
/**
 * @brief Load material definitions for each map that has one
 * @param[in] map the base name of the map to load the material for
 */
void R_LoadMaterials (const char *map)
{
	char path[MAX_QPATH];
	byte *fileBuffer;
	const char *buffer;
	bool inmaterial;
	image_t *image;
	material_t *m;
	materialStage_t *ss;

	/* clear previously loaded materials */
	R_ImageClearMaterials();

	if (map[0] == '+' || map[0] == '-')
		map++;
	else if (map[0] == '-')
		return;

	/* load the materials file for parsing */
	Com_sprintf(path, sizeof(path), "materials/%s.mat", Com_SkipPath(map));

	if (FS_LoadFile(path, &fileBuffer) < 1) {
		Com_DPrintf(DEBUG_RENDERER, "Couldn't load %s\n", path);
		return;
	} else {
		Com_Printf("load material file: '%s'\n", path);
		if (!r_materials->integer)
			Com_Printf("...ignore materials (r_materials is deactivated)\n");
	}

	buffer = (const char *)fileBuffer;

	inmaterial = false;
	image = nullptr;
	m = nullptr;

	while (true) {
		const char *c = Com_Parse(&buffer);

		if (c[0] == '\0')
			break;

		if (*c == '{' && !inmaterial) {
			inmaterial = true;
			continue;
		}

		if (Q_streq(c, "material")) {
			c = Com_Parse(&buffer);
			image = R_GetImage(va("textures/%s", c));
			if (image == nullptr)
				Com_DPrintf(DEBUG_RENDERER, "R_LoadMaterials: skip texture: %s - not used in the map\n", c);

			continue;
		}

		if (!image)
			continue;

		m = &image->material;

		if (Q_streq(c, "normalmap")){
			c = Com_Parse(&buffer);
			image->normalmap = R_FindImage(va("textures/%s", c), it_normalmap);

			if (image->normalmap == r_noTexture){
				Com_Printf("R_LoadMaterials: Failed to resolve normalmap: %s\n", c);
				image->normalmap = nullptr;
			}
		}

		if (Q_streq(c, "glowmap")){
			c = Com_Parse(&buffer);
			image->glowmap = R_FindImage(va("textures/%s", c), it_glowmap);

			if (image->glowmap == r_noTexture){
				Com_Printf("R_LoadMaterials: Failed to resolve glowmap: %s\n", c);
				image->glowmap = nullptr;
			}
		}

		if (Q_streq(c, "bump")) {
			m->bump = atof(Com_Parse(&buffer));
			if (m->bump < 0.0) {
				Com_Printf("R_LoadMaterials: Invalid bump value for %s\n", image->name);
				m->bump = defaultMaterial.bump;
			}
		}

		if (Q_streq(c, "parallax")) {
			m->parallax = atof(Com_Parse(&buffer));
			if (m->parallax < 0.0) {
				Com_Printf("R_LoadMaterials: Invalid parallax value for %s\n", image->name);
				m->parallax = defaultMaterial.parallax;
			}
		}

		if (Q_streq(c, "hardness")) {
			m->hardness = atof(Com_Parse(&buffer));
			if (m->hardness < 0.0) {
				Com_Printf("R_LoadMaterials: Invalid hardness value for %s\n", image->name);
				m->hardness = defaultMaterial.hardness;
			}
		}

		if (Q_streq(c, "specular")) {
			m->specular = atof(Com_Parse(&buffer));
			if (m->specular < 0.0) {
				Com_Printf("R_LoadMaterials: Invalid specular value for %s\n", image->name);
				m->specular = defaultMaterial.specular;
			}
		}

		if (Q_streq(c, "glowscale")) {
			m->glowscale = atof(Com_Parse(&buffer));
			if (m->glowscale < 0.0) {
				Com_Printf("R_LoadMaterials: Invalid glowscale value for %s\n", image->name);
				m->glowscale = defaultMaterial.glowscale;
			}
		}

		if (*c == '{' && inmaterial) {
			materialStage_t* const s = Mem_PoolAllocType(materialStage_t, vid_imagePool);
			s->glowscale = defaultMaterial.glowscale;

			if (R_ParseStage(s, &buffer) == -1) {
				Mem_Free(s);
				continue;
			}

			/* load animation frame images */
			if (s->flags & STAGE_ANIM) {
				if (R_LoadAnimImages(s) == -1) {
					Mem_Free(s);
					continue;
				}
			}

			/* append the stage to the chain */
			if (!m->stages)
				m->stages = s;
			else {
				ss = m->stages;
				while (ss->next)
					ss = ss->next;
				ss->next = s;
			}

			m->flags |= s->flags;
			m->num_stages++;
			continue;
		}

		if (*c == '}' && inmaterial) {
			Com_DPrintf(DEBUG_RENDERER, "Parsed material %s with %d stages\n", image->name, m->num_stages);
			inmaterial = false;
			image = nullptr;
			/* multiply stage glowscale values by material glowscale */
			ss = m->stages;
			while (ss) {
				ss->glowscale *= m->glowscale;
				ss = ss->next;
			}
		}
	}

	FS_FreeFile(fileBuffer);

	R_CreateMaterialData();
}
Exemple #7
0
void
LoadMD2(model_t *mod, void *buffer, int modfilelen)
{
	int i, j;
	dmdl_t *pinmodel, *pheader;
	dstvert_t *pinst, *poutst;
	dtriangle_t *pintri, *pouttri;
	daliasframe_t *pinframe, *poutframe;
	int *pincmd, *poutcmd;
	int version;
	int ofs_end;

	pinmodel = (dmdl_t *)buffer;

	version = LittleLong(pinmodel->version);

	if (version != ALIAS_VERSION)
	{
		ri.Sys_Error(ERR_DROP, "%s has wrong version number (%i should be %i)",
				mod->name, version, ALIAS_VERSION);
	}

	ofs_end = LittleLong(pinmodel->ofs_end);
	if (ofs_end < 0 || ofs_end > modfilelen)
		ri.Sys_Error (ERR_DROP, "model %s file size(%d) too small, should be %d", mod->name,
				   modfilelen, ofs_end);

	mod->extradata = Hunk_Begin(modfilelen);
	pheader = Hunk_Alloc(ofs_end);

	/* byte swap the header fields and sanity check */
	for (i = 0; i < sizeof(dmdl_t) / 4; i++)
	{
		((int *)pheader)[i] = LittleLong(((int *)buffer)[i]);
	}

	if (pheader->skinheight > MAX_LBM_HEIGHT)
	{
		ri.Sys_Error(ERR_DROP, "model %s has a skin taller than %d", mod->name,
				MAX_LBM_HEIGHT);
	}

	if (pheader->num_xyz <= 0)
	{
		ri.Sys_Error(ERR_DROP, "model %s has no vertices", mod->name);
	}

	if (pheader->num_xyz > MAX_VERTS)
	{
		ri.Sys_Error(ERR_DROP, "model %s has too many vertices", mod->name);
	}

	if (pheader->num_st <= 0)
	{
		ri.Sys_Error(ERR_DROP, "model %s has no st vertices", mod->name);
	}

	if (pheader->num_tris <= 0)
	{
		ri.Sys_Error(ERR_DROP, "model %s has no triangles", mod->name);
	}

	if (pheader->num_frames <= 0)
	{
		ri.Sys_Error(ERR_DROP, "model %s has no frames", mod->name);
	}

	/* load base s and t vertices (not used in gl version) */
	pinst = (dstvert_t *)((byte *)pinmodel + pheader->ofs_st);
	poutst = (dstvert_t *)((byte *)pheader + pheader->ofs_st);

	for (i = 0; i < pheader->num_st; i++)
	{
		poutst[i].s = LittleShort(pinst[i].s);
		poutst[i].t = LittleShort(pinst[i].t);
	}

	/* load triangle lists */
	pintri = (dtriangle_t *)((byte *)pinmodel + pheader->ofs_tris);
	pouttri = (dtriangle_t *)((byte *)pheader + pheader->ofs_tris);

	for (i = 0; i < pheader->num_tris; i++)
	{
		for (j = 0; j < 3; j++)
		{
			pouttri[i].index_xyz[j] = LittleShort(pintri[i].index_xyz[j]);
			pouttri[i].index_st[j] = LittleShort(pintri[i].index_st[j]);
		}
	}

	/* load the frames */
	for (i = 0; i < pheader->num_frames; i++)
	{
		pinframe = (daliasframe_t *)((byte *)pinmodel
				+ pheader->ofs_frames + i * pheader->framesize);
		poutframe = (daliasframe_t *)((byte *)pheader
				+ pheader->ofs_frames + i * pheader->framesize);

		memcpy(poutframe->name, pinframe->name, sizeof(poutframe->name));

		for (j = 0; j < 3; j++)
		{
			poutframe->scale[j] = LittleFloat(pinframe->scale[j]);
			poutframe->translate[j] = LittleFloat(pinframe->translate[j]);
		}

		/* verts are all 8 bit, so no swapping needed */
		memcpy(poutframe->verts, pinframe->verts,
				pheader->num_xyz * sizeof(dtrivertx_t));
	}

	mod->type = mod_alias;

	/* load the glcmds */
	pincmd = (int *)((byte *)pinmodel + pheader->ofs_glcmds);
	poutcmd = (int *)((byte *)pheader + pheader->ofs_glcmds);

	for (i = 0; i < pheader->num_glcmds; i++)
	{
		poutcmd[i] = LittleLong(pincmd[i]);
	}

	/* register all skins */
	memcpy((char *)pheader + pheader->ofs_skins,
			(char *)pinmodel + pheader->ofs_skins,
			pheader->num_skins * MAX_SKINNAME);

	for (i = 0; i < pheader->num_skins; i++)
	{
		mod->skins[i] = R_FindImage(
				(char *)pheader + pheader->ofs_skins + i * MAX_SKINNAME,
				it_skin);
	}

	mod->mins[0] = -32;
	mod->mins[1] = -32;
	mod->mins[2] = -32;
	mod->maxs[0] = 32;
	mod->maxs[1] = 32;
	mod->maxs[2] = 32;
}
Exemple #8
0
/**
 * @brief Material stage parser
 * @sa R_LoadMaterials
 */
static int R_ParseStage (materialStage_t *s, const char **buffer)
{
	int i;

	while (true) {
		const char *c = Com_Parse(buffer);

		if (c[0] == '\0')
			break;

		if (Q_streq(c, "glowscale")) {
			s->glowscale = atof(Com_Parse(buffer));
			if (s->glowscale < 0.0) {
				Com_Printf("R_LoadMaterials: Invalid glowscale value for %s\n", c);
				s->glowscale = defaultMaterial.glowscale;
			}
			continue;
		}

		if (Q_streq(c, "texture")) {
			c = Com_Parse(buffer);
			s->image = R_FindImage(va("textures/%s", c), it_material);

			if (s->image == r_noTexture) {
				Com_Printf("R_ParseStage: Failed to resolve texture: %s\n", c);
				return -1;
			}

			s->flags |= STAGE_TEXTURE;
			continue;
		}

		if (Q_streq(c, "envmap")) {
			c = Com_Parse(buffer);
			i = atoi(c);

			if (i > -1 && i < MAX_ENVMAPTEXTURES)
				s->image = r_envmaptextures[i];
			else
				s->image = R_FindImage(va("pics/envmaps/%s", c), it_material);

			if (s->image == r_noTexture) {
				Com_Printf("R_ParseStage: Failed to resolve envmap: %s\n", c);
				return -1;
			}

			s->flags |= STAGE_ENVMAP;
			continue;
		}

		if (Q_streq(c, "blend")) {
			c = Com_Parse(buffer);
			s->blend.src = R_ConstByName(c);

			if (s->blend.src == -1) {
				Com_Printf("R_ParseStage: Failed to resolve blend src: %s\n", c);
				return -1;
			}

			c = Com_Parse(buffer);
			s->blend.dest = R_ConstByName(c);

			if (s->blend.dest == -1) {
				Com_Printf("R_ParseStage: Failed to resolve blend dest: %s\n", c);
				return -1;
			}

			s->flags |= STAGE_BLEND;
			continue;
		}

		if (Q_streq(c, "color")) {
			for (i = 0; i < 3; i++) {
				c = Com_Parse(buffer);
				s->color[i] = atof(c);

				if (s->color[i] < 0.0 || s->color[i] > 1.0) {
					Com_Printf("R_ParseStage: Failed to resolve color: %s\n", c);
					return -1;
				}
			}

			s->flags |= STAGE_COLOR;
			continue;
		}

		if (Q_streq(c, "pulse")) {
			c = Com_Parse(buffer);
			s->pulse.hz = atof(c);
			s->pulse.dutycycle = 1.0;

			if (s->pulse.hz < 0.0) {
				Com_Printf("R_ParseStage: Failed to resolve frequency: %s\n", c);
				return -1;
			}

			s->flags |= STAGE_PULSE;
			continue;
		}

		if (Q_streq(c, "dutycycle")) {
			c = Com_Parse(buffer);
			s->pulse.dutycycle = atof(c);

			if (s->pulse.dutycycle < 0.0 || s->pulse.dutycycle > 1.0) {
				Com_Printf("R_ParseStage: Failed to resolve pulse duty cycle: %s\n", c);
				return -1;
			}

			continue;
		}

		if (Q_streq(c, "stretch")) {
			c = Com_Parse(buffer);
			s->stretch.amp = atof(c);

			if (s->stretch.amp < 0.0) {
				Com_Printf("R_ParseStage: Failed to resolve amplitude: %s\n", c);
				return -1;
			}

			c = Com_Parse(buffer);
			s->stretch.hz = atof(c);

			if (s->stretch.hz < 0.0) {
				Com_Printf("R_ParseStage: Failed to resolve frequency: %s\n", c);
				return -1;
			}

			s->flags |= STAGE_STRETCH;
			continue;
		}

		if (Q_streq(c, "rotate")) {
			c = Com_Parse(buffer);
			s->rotate.hz = atof(c);

			if (s->rotate.hz < 0.0) {
				Com_Printf("R_ParseStage: Failed to resolve rotate: %s\n", c);
				return -1;
			}

			s->flags |= STAGE_ROTATE;
			continue;
		}

		if (Q_streq(c, "scroll.s")) {
			c = Com_Parse(buffer);
			s->scroll.s = atof(c);

			s->flags |= STAGE_SCROLL_S;
			continue;
		}

		if (Q_streq(c, "scroll.t")) {
			c = Com_Parse(buffer);
			s->scroll.t = atof(c);

			s->flags |= STAGE_SCROLL_T;
			continue;
		}

		if (Q_streq(c, "scale.s")) {
			c = Com_Parse(buffer);
			s->scale.s = atof(c);

			s->flags |= STAGE_SCALE_S;
			continue;
		}

		if (Q_streq(c, "scale.t")) {
			c = Com_Parse(buffer);
			s->scale.t = atof(c);

			s->flags |= STAGE_SCALE_T;
			continue;
		}

		if (Q_streq(c, "terrain")) {
			c = Com_Parse(buffer);
			s->terrain.floor = atof(c);

			c = Com_Parse(buffer);
			s->terrain.ceil = atof(c);
			if (s->terrain.ceil < s->terrain.floor) {
				Com_Printf("R_ParseStage: Inverted terrain ceiling and floor "
					"values for %s\n", (s->image ? s->image->name : "nullptr"));
				return -1;
			}

			s->terrain.height = s->terrain.ceil - s->terrain.floor;

			if (s->terrain.height == 0.0) {
				Com_Printf("R_ParseStage: Zero height terrain specified for %s\n",
					(s->image ? s->image->name : "nullptr"));
				return -1;
			}

			s->flags |= STAGE_TERRAIN;
			continue;
		}

		if (Q_streq(c, "tape")) {
			c = Com_Parse(buffer);
			s->tape.center = atof(c);

			/* how much downwards? */
			c = Com_Parse(buffer);
			s->tape.floor = atof(c);

			/* how much upwards? */
			c = Com_Parse(buffer);
			s->tape.ceil = atof(c);

			s->tape.min = s->tape.center - s->tape.floor;
			s->tape.max = s->tape.center + s->tape.ceil;
			s->tape.height = s->tape.floor + s->tape.ceil;

			if (s->tape.height == 0.0) {
				Com_Printf("R_ParseStage: Zero height tape specified for %s\n",
					(s->image ? s->image->name : "nullptr"));
				return -1;
			}

			s->flags |= STAGE_TAPE;
			continue;
		}

		if (Q_streq(c, "dirtmap")) {
			c = Com_Parse(buffer);
			s->dirt.intensity = atof(c);
			if (s->dirt.intensity <= 0.0 || s->dirt.intensity > 1.0) {
				Com_Printf("R_ParseStage: Invalid dirtmap intensity for %s\n",
					(s->image ? s->image->name : "nullptr"));
				return -1;
			}
			s->flags |= STAGE_DIRTMAP;
			continue;
		}

		if (char const* const rest = Q_strstart(c, "anim")) {
			switch (rest[0]) {
			case 'a':
				s->anim.type = ANIM_ALTERNATE;
				break;
			case 'b':
				s->anim.type = ANIM_BACKWARDS;
				break;
			case 'r':
				s->anim.type = ANIM_RANDOM;
				break;
			case 'f':
				s->anim.type = ANIM_RANDOMFORCE;
				break;
			default:
				s->anim.type = ANIM_NORMAL;
				break;
			}
			c = Com_Parse(buffer);
			s->anim.num_frames = atoi(c);

			if (s->anim.num_frames < 1 || s->anim.num_frames > MAX_ANIM_FRAMES) {
				Com_Printf("R_ParseStage: Invalid number of anim frames for %s (max is %i)\n",
						(s->image ? s->image->name : "nullptr"), MAX_ANIM_FRAMES);
				return -1;
			}

			c = Com_Parse(buffer);
			s->anim.fps = atof(c);

			if (s->anim.fps <= 0) {
				Com_Printf("R_ParseStage: Invalid anim fps for %s\n",
						(s->image ? s->image->name : "nullptr"));
				return -1;
			}

			/* the frame images are loaded once the stage is parsed completely */

			s->flags |= STAGE_ANIM;
			continue;
		}

		if (Q_streq(c, "glowmaplink")) {
			s->flags |= STAGE_GLOWMAPLINK;
			continue;
		}

		if (Q_streq(c, "lightmap")) {
			s->flags |= STAGE_LIGHTMAP;
			continue;
		}

		if (Q_streq(c, "flare")) {
			c = Com_Parse(buffer);
			i = atoi(c);

			if (i > -1 && i < NUM_FLARETEXTURES)
				s->image = r_flaretextures[i];
			else
				s->image = R_FindImage(va("pics/flares/%s", c), it_material);

			if (s->image == r_noTexture) {
				Com_Printf("R_ParseStage: Failed to resolve flare: %s\n", c);
				return -1;
			}

			s->flags |= STAGE_FLARE;
			continue;
		}

		if (*c == '}') {
			Com_DPrintf(DEBUG_RENDERER, "Parsed stage\n"
					"  flags: %d\n"
					"  image: %s\n"
					"  blend: %d %d\n"
					"  color: %3f %3f %3f\n"
					"  pulse: %3f\n"
					"  pulse duty cycle: %1.2f\n"
					"  stretch: %3f %3f\n"
					"  rotate: %3f\n"
					"  scroll.s: %3f\n"
					"  scroll.t: %3f\n"
					"  scale.s: %3f\n"
					"  scale.t: %3f\n"
					"  terrain.floor: %5f\n"
					"  terrain.ceil: %5f\n"
					"  anim.num_frames: %d\n"
					"  anim.fps: %3f\n",
					s->flags, (s->image ? s->image->name : "nullptr"),
					s->blend.src, s->blend.dest,
					s->color[0], s->color[1], s->color[2],
					s->pulse.hz, s->pulse.dutycycle, s->stretch.amp, s->stretch.hz,
					s->rotate.hz, s->scroll.s, s->scroll.t,
					s->scale.s, s->scale.t, s->terrain.floor, s->terrain.ceil,
					s->anim.num_frames, s->anim.fps);

			/* a texture or envmap means render it */
			if (s->flags & (STAGE_TEXTURE | STAGE_ENVMAP))
				s->flags |= STAGE_RENDER;

			if (s->flags & (STAGE_TERRAIN | STAGE_DIRTMAP))
				s->flags |= STAGE_LIGHTING;

			return 0;
		}

		Com_Printf("Invalid token: '%s'\n", c);
	}

	Com_Printf("R_ParseStage: Malformed stage\n");
	return -1;
}
Exemple #9
0
void
Mod_LoadTexinfo(lump_t *l)
{
	texinfo_t *in;
	mtexinfo_t *out, *step;
	int i, j, count;
	char name[MAX_QPATH];
	int next;

	in = (void *)(mod_base + l->fileofs);

	if (l->filelen % sizeof(*in))
	{
		ri.Sys_Error(ERR_DROP, "MOD_LoadBmodel: funny lump size in %s",
				loadmodel->name);
	}

	count = l->filelen / sizeof(*in);
	out = Hunk_Alloc(count * sizeof(*out));

	loadmodel->texinfo = out;
	loadmodel->numtexinfo = count;

	for (i = 0; i < count; i++, in++, out++)
	{
		for (j = 0; j < 4; j++)
		{
			out->vecs[0][j] = LittleFloat(in->vecs[0][j]);
			out->vecs[1][j] = LittleFloat(in->vecs[1][j]);
		}

		out->flags = LittleLong(in->flags);
		next = LittleLong(in->nexttexinfo);

		if (next > 0)
		{
			out->next = loadmodel->texinfo + next;
		}
		else
		{
			out->next = NULL;
		}

		Com_sprintf(name, sizeof(name), "textures/%s.wal", in->texture);

		out->image = R_FindImage(name, it_wall);

		if (!out->image)
		{
			R_Printf(PRINT_ALL, "Couldn't load %s\n", name);
			out->image = r_notexture;
		}
	}

	/* count animation frames */
	for (i = 0; i < count; i++)
	{
		out = &loadmodel->texinfo[i];
		out->numframes = 1;

		for (step = out->next; step && step != out; step = step->next)
		{
			out->numframes++;
		}
	}
}
Exemple #10
0
/*
=================
Mod_LoadAliasModel
=================
*/
void Mod_LoadAliasModel (model_t *mod, void *buffer)
{
	int					i, j;
	dmdl_t				*pinmodel, *pheader;
	dstvert_t			*pinst, *poutst;
	dtriangle_t			*pintri, *pouttri;
	daliasframe_t		*pinframe, *poutframe;
	int					*pincmd, *poutcmd;
	int					version;

	pinmodel = (dmdl_t *)buffer;

	version = LittleLong (pinmodel->version);
	if (version != ALIAS_VERSION)
		ri.Sys_Error (ERR_DROP, "%s has wrong version number (%i should be %i)",
				 mod->name, version, ALIAS_VERSION);

	pheader = Hunk_Alloc (LittleLong(pinmodel->ofs_end));
	
	// byte swap the header fields and sanity check
	for (i=0 ; i<sizeof(dmdl_t)/4 ; i++)
		((int *)pheader)[i] = LittleLong (((int *)buffer)[i]);

	if (pheader->skinheight > MAX_LBM_HEIGHT)
		ri.Sys_Error (ERR_DROP, "model %s has a skin taller than %d", mod->name,
				   MAX_LBM_HEIGHT);

	if (pheader->num_xyz <= 0)
		ri.Sys_Error (ERR_DROP, "model %s has no vertices", mod->name);

	if (pheader->num_xyz > MAX_VERTS)
		ri.Sys_Error (ERR_DROP, "model %s has too many vertices", mod->name);

	if (pheader->num_st <= 0)
		ri.Sys_Error (ERR_DROP, "model %s has no st vertices", mod->name);

	if (pheader->num_tris <= 0)
		ri.Sys_Error (ERR_DROP, "model %s has no triangles", mod->name);

	if (pheader->num_frames <= 0)
		ri.Sys_Error (ERR_DROP, "model %s has no frames", mod->name);

//
// load base s and t vertices (not used in gl version)
//
	pinst = (dstvert_t *) ((byte *)pinmodel + pheader->ofs_st);
	poutst = (dstvert_t *) ((byte *)pheader + pheader->ofs_st);

	for (i=0 ; i<pheader->num_st ; i++)
	{
		poutst[i].s = LittleShort (pinst[i].s);
		poutst[i].t = LittleShort (pinst[i].t);
	}

//
// load triangle lists
//
	pintri = (dtriangle_t *) ((byte *)pinmodel + pheader->ofs_tris);
	pouttri = (dtriangle_t *) ((byte *)pheader + pheader->ofs_tris);

	for (i=0 ; i<pheader->num_tris ; i++)
	{
		for (j=0 ; j<3 ; j++)
		{
			pouttri[i].index_xyz[j] = LittleShort (pintri[i].index_xyz[j]);
			pouttri[i].index_st[j] = LittleShort (pintri[i].index_st[j]);
		}
	}

//
// load the frames
//
	for (i=0 ; i<pheader->num_frames ; i++)
	{
		pinframe = (daliasframe_t *) ((byte *)pinmodel 
			+ pheader->ofs_frames + i * pheader->framesize);
		poutframe = (daliasframe_t *) ((byte *)pheader 
			+ pheader->ofs_frames + i * pheader->framesize);

		memcpy (poutframe->name, pinframe->name, sizeof(poutframe->name));
		for (j=0 ; j<3 ; j++)
		{
			poutframe->scale[j] = LittleFloat (pinframe->scale[j]);
			poutframe->translate[j] = LittleFloat (pinframe->translate[j]);
		}
		// verts are all 8 bit, so no swapping needed
		memcpy (poutframe->verts, pinframe->verts, 
			pheader->num_xyz*sizeof(dtrivertx_t));

	}

	mod->type = mod_alias;

	//
	// load the glcmds
	//
	pincmd = (int *) ((byte *)pinmodel + pheader->ofs_glcmds);
	poutcmd = (int *) ((byte *)pheader + pheader->ofs_glcmds);
	for (i=0 ; i<pheader->num_glcmds ; i++)
		poutcmd[i] = LittleLong (pincmd[i]);


	// register all skins
	memcpy ((char *)pheader + pheader->ofs_skins, (char *)pinmodel + pheader->ofs_skins,
		pheader->num_skins*MAX_SKINNAME);
	for (i=0 ; i<pheader->num_skins ; i++)
	{
		mod->skins[i] = R_FindImage ((char *)pheader + pheader->ofs_skins + i*MAX_SKINNAME, it_skin);
	}
}
Exemple #11
0
/*
=================
Mod_LoadTexinfo
=================
*/
void Mod_LoadTexinfo (lump_t *l)
{
	texinfo_t *in;
	mtexinfo_t *out, *step;
	int 	i, j, count;
	float	len1, len2;
	char	name[MAX_QPATH];
	int		next;

	in = (void *)(mod_base + l->fileofs);
	if (l->filelen % sizeof(*in))
		ri.Sys_Error (ERR_DROP,"MOD_LoadBmodel: funny lump size in %s",loadmodel->name);
	count = l->filelen / sizeof(*in);
	out = Hunk_Alloc ( (count+6)*sizeof(*out));	// extra for skybox

	loadmodel->texinfo = out;
	loadmodel->numtexinfo = count;

	for ( i=0 ; i<count ; i++, in++, out++)
	{
		for (j=0 ; j<8 ; j++)
			out->vecs[0][j] = LittleFloat (in->vecs[0][j]);
		len1 = VectorLength (out->vecs[0]);
		len2 = VectorLength (out->vecs[1]);
		len1 = (len1 + len2)/2;
		if (len1 < 0.32)
			out->mipadjust = 4;
		else if (len1 < 0.49)
			out->mipadjust = 3;
		else if (len1 < 0.99)
			out->mipadjust = 2;
		else
			out->mipadjust = 1;
#if 0
		if (len1 + len2 < 0.001)
			out->mipadjust = 1;		// don't crash
		else
			out->mipadjust = 1 / floor( (len1+len2)/2 + 0.1 );
#endif

		out->flags = LittleLong (in->flags);

		next = LittleLong (in->nexttexinfo);
		if (next > 0)
			out->next = loadmodel->texinfo + next;
                /*
                 * PATCH: eliasm
                 *
                 * This patch fixes the problem where the game
                 * domed core when loading a new level.
                 */
                else {
                  out->next = NULL;
                }
                /* END OF PATCH */

		Com_sprintf (name, sizeof(name), "textures/%s.wal", in->texture);
		out->image = R_FindImage (name, it_wall);
		if (!out->image)
		{
			out->image = r_notexture_mip; // texture not found
			out->flags = 0;
		}
	}

	// count animation frames
	for (i=0 ; i<count ; i++)
	{
		out = &loadmodel->texinfo[i];
		out->numframes = 1;
		for (step = out->next ; step && step != out ; step=step->next)
			out->numframes++;
	}
}
Exemple #12
0
/*
===============
RE_RegisterSkin
===============
*/
struct image_s *RE_RegisterSkin(char *name)
{
  return R_FindImage(name, it_skin);
}