Exemplo n.º 1
0
/*
=================
R_DrawSpriteModel
=================
*/
void R_DrawSpriteModel (entity_t *e)
{
    float			alpha = 1.0f;
    vec2_t			texCoord[4];
    vec3_t			point[4];
    dsprite_t		*psprite;
    dsprframe_t		*frame;
    float			*up, *right;
    int				i;

    // don't even bother culling, because it's just a single
    // polygon without a surface cache

    psprite = (dsprite_t *)currentmodel->extradata;

    e->frame %= psprite->numframes;

    frame = &psprite->frames[e->frame];

    if (!frame) return;

    c_alias_polys += 2;

    // normal sprite
    up = vup;
    right = vright;

    if (e->flags & RF_TRANSLUCENT)
        alpha = e->alpha;

    R_SetVertexRGBScale (true);

    // Psychospaz's additive transparency
    if ((currententity->flags & RF_TRANS_ADDITIVE) && (alpha != 1.0f))
    {
        GL_Enable (GL_BLEND);
        GL_TexEnv (GL_MODULATE);
        GL_Disable (GL_ALPHA_TEST);
        GL_DepthMask (false);
        GL_BlendFunc (GL_SRC_ALPHA, GL_ONE);
    }
    else
    {
        GL_TexEnv (GL_MODULATE);
        if (alpha == 1.0f) {
            GL_Enable (GL_ALPHA_TEST);
            GL_DepthMask (true);
        }
        else {
            GL_BlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
            GL_DepthMask (false);
            GL_Enable (GL_BLEND);
            GL_Disable (GL_ALPHA_TEST);
        }
    }
    GL_Bind(currentmodel->skins[0][e->frame]->texnum);

    Vector2Set(texCoord[0], 0, 1);
    Vector2Set(texCoord[1], 0, 0);
    Vector2Set(texCoord[2], 1, 0);
    Vector2Set(texCoord[3], 1, 1);

    VectorMA (e->origin, -frame->origin_y, up, point[0]);
    VectorMA (point[0], -frame->origin_x, right, point[0]);

    VectorMA (e->origin, frame->height - frame->origin_y, up, point[1]);
    VectorMA (point[1], -frame->origin_x, right, point[1]);

    VectorMA (e->origin, frame->height - frame->origin_y, up, point[2]);
    VectorMA (point[2], frame->width - frame->origin_x, right, point[2]);

    VectorMA (e->origin, -frame->origin_y, up, point[3]);
    VectorMA (point[3], frame->width - frame->origin_x, right, point[3]);

    rb_vertex = rb_index = 0;
    indexArray[rb_index++] = rb_vertex+0;
    indexArray[rb_index++] = rb_vertex+1;
    indexArray[rb_index++] = rb_vertex+2;
    indexArray[rb_index++] = rb_vertex+0;
    indexArray[rb_index++] = rb_vertex+2;
    indexArray[rb_index++] = rb_vertex+3;
    for (i=0; i<4; i++) {
        VA_SetElem2(texCoordArray[0][rb_vertex], texCoord[i][0], texCoord[i][1]);
        VA_SetElem3(vertexArray[rb_vertex], point[i][0], point[i][1], point[i][2]);
        VA_SetElem4(colorArray[rb_vertex], 1.0f, 1.0f, 1.0f, alpha);
        rb_vertex++;
    }
    RB_DrawArrays ();

    GL_BlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
    GL_TexEnv (GL_REPLACE);
    GL_DepthMask (true);
    GL_Disable (GL_ALPHA_TEST);
    GL_Disable (GL_BLEND);

    R_SetVertexRGBScale (false);

    RB_DrawMeshTris ();
    rb_vertex = rb_index = 0;
}
Exemplo n.º 2
0
/**
 * @brief Get the width of radar.
 * @param[in] node Node description of the radar
 * @param[in] gridSize size of the radar picture, in grid units.
 * @sa UI_InitRadar
 */
static void UI_GetRadarWidth (const uiNode_t *node, vec2_t gridSize)
{
    int j;
    int tileWidth[2];		/**< Contains the width of the first and the last tile of the first line (in screen unit) */
    int tileHeight[2];		/**< Contains the height of the first and the last tile of the first column  (in screen unit)*/
    int secondTileGridX;	/**< Contains the grid X position of 2nd tiles in first line */
    int secondTileGridY;	/**< Contains the grid Y position of 2nd tiles in first column */
    float ratioConversion;	/**< ratio conversion between screen coordinates and grid coordinates */
    const int ROUNDING_PIXEL = 1;	/**< Number of pixel to remove to avoid rounding errors (and lines between tiles)
									 * We remove pixel because this is much nicer if tiles overlap a little bit rather than
									 * if they are too distant one from the other */

    /* Set radar.gridMax */
    radar.gridMax[0] = radar.gridMin[0];
    radar.gridMax[1] = radar.gridMin[1];

    /* Initialize secondTileGridX to value higher that real value */
    secondTileGridX = radar.gridMin[0] + 1000;
    secondTileGridY = radar.gridMin[1] + 1000;

    /* Initialize screen size of last tile (will be used only if there is 1 tile in a line or in a row) */
    Vector2Set(tileWidth, 0, 0);
    Vector2Set(tileHeight, 0, 0);

    for (j = 0; j < radar.numImages; j++) {
        const hudRadarImage_t *image = &radar.images[j];

        assert(image->gridX >= radar.gridMin[0]);
        assert(image->gridY >= radar.gridMin[1]);

        /* we can assume this because every random map tile has it's origin in
         * (0, 0) and therefore there are no intersections possible on the min
         * x and the min y axis. We just have to add the image->w and image->h
         * values of those images that are placed on the gridMin values.
         * This also works for static maps, because they have a gridX and gridY
         * value of zero */

        if (image->gridX == radar.gridMin[0]) {
            /* radar.gridMax[1] is the maximum for FIRST column (maximum depends on column) */
            if (image->gridY > radar.gridMax[1]) {
                tileHeight[1] = image->height;
                radar.gridMax[1] = image->gridY;
            }
            if (image->gridY == radar.gridMin[1]) {
                /* This is the tile of the map in the lower left: */
                tileHeight[0] = image->height;
                tileWidth[0] = image->width;
            } else if (image->gridY < secondTileGridY)
                secondTileGridY = image->gridY;
        }
        if (image->gridY == radar.gridMin[1]) {
            /* radar.gridMax[1] is the maximum for FIRST line (maximum depends on line) */
            if (image->gridX > radar.gridMax[0]) {
                tileWidth[1] = image->width;
                radar.gridMax[0] = image->gridX;
            } else if (image->gridX < secondTileGridX)
                secondTileGridX = image->gridX;
        }
    }

    /* Maybe there was only one tile in a line or in a column? */
    if (!tileHeight[1])
        tileHeight[1] = tileHeight[0];
    if (!tileWidth[1])
        tileWidth[1] = tileWidth[0];

    /* Now we get the ratio conversion between screen coordinates and grid coordinates.
     * The problem is that some tiles may have L or T shape.
     * But we now that the tile in the lower left follows for sure the side of the map on it's whole length
     * at least either on its height or on its width.*/
    ratioConversion = std::max((secondTileGridX - radar.gridMin[0]) / (tileWidth[0] - ROUNDING_PIXEL),
                               (secondTileGridY - radar.gridMin[1]) / (tileHeight[0] - ROUNDING_PIXEL));

    /* And now we fill radar.w and radar.h */
    radar.w = floor((radar.gridMax[0] - radar.gridMin[0]) / ratioConversion) + tileWidth[1];
    radar.h = floor((radar.gridMax[1] - radar.gridMin[1]) / ratioConversion) + tileHeight[1];

    Vector2Set(gridSize, round(radar.w * ratioConversion), round(radar.h * ratioConversion));
}
Exemplo n.º 3
0
/**
 * @brief Draws the image node
 * @param[in] node The UI node to draw
 */
void uiImageNode::draw (uiNode_t* node)
{
	vec2_t size;
	vec2_t nodepos;
	const image_t* image;
	vec2_t imagepos;
	vec2_t nodesize;

	const char* imageName = UI_GetReferenceString(node, node->image);
	if (Q_strnull(imageName))
		return;

	image = UI_LoadImage(imageName);
	if (!image)
		return;

	/* mouse darken effect */
	/** @todo convert all pic using mousefx into button.
	 * @todo delete mousefx
	 */
#if 0
	if (node->mousefx && node->state) {
		vec4_t color;
		VectorScale(node->color, 0.8, color);
		color[3] = node->color[3];
		R_Color(color);
	}
#endif

	UI_GetNodeAbsPos(node, nodepos);
	Vector2Copy(node->box.size, nodesize);
	nodesize[0] -= node->padding + node->padding;
	if (nodesize[0] < 0)
		nodesize[0] = 0;
	nodesize[1] -= node->padding + node->padding;
	if (nodesize[1] < 0)
		nodesize[1] = 0;

	/** @todo code is duplicated in the ekg node code */
	if (node->box.size[0] && !node->box.size[1]) {
		const float scale = image->width / node->box.size[0];
		Vector2Set(size, node->box.size[0], image->height / scale);
	} else if (node->box.size[1] && !node->box.size[0]) {
		const float scale = image->height / node->box.size[1];
		Vector2Set(size, image->width / scale, node->box.size[1]);
	} else {
		Vector2Copy(nodesize, size);

		if (EXTRADATA(node).preventRatio) {
			/* maximize the image into the bounding box */
			const float ratio = (float) image->width / (float) image->height;
			if (size[1] * ratio > size[0]) {
				Vector2Set(size, size[0], size[0] / ratio);
			} else {
				Vector2Set(size, size[1] * ratio, size[1]);
			}
		}
	}

	UI_ImageAlignBoxInBox(nodepos, nodesize, size, (align_t) node->contentAlign, imagepos);
	UI_DrawNormImage(false, imagepos[0] + node->padding, imagepos[1] + node->padding, size[0], size[1],
			EXTRADATA(node).texh[0], EXTRADATA(node).texh[1],
			EXTRADATA(node).texl[0], EXTRADATA(node).texl[1], image);

	/** @todo convert all pic using mousefx into button.
	 * @todo delete mousefx
	 */
#if 0
	if (node->mousefx && node->state) {
		R_Color(nullptr);
	}
#endif
}
Exemplo n.º 4
0
static void UI_KeyBindingNodeDraw (uiNode_t *node)
{
	static const int panelTemplate[] = {
		CORNER_SIZE, MID_SIZE, CORNER_SIZE,
		CORNER_SIZE, MID_SIZE, CORNER_SIZE,
		MARGE
	};
	const char *binding, *description, *command;
	int texX, texY;
	const float *textColor;
	const char *image;
	vec2_t pos;
	const char *font = UI_GetFontFromNode(node);
	const int bindingWidth = EXTRADATA(node).bindingWidth;
	const int descriptionWidth = node->size[0] - bindingWidth;
	vec2_t descriptionPos, descriptionSize;
	vec2_t bindingPos, bindingSize;

	if (node->state) {
		textColor = node->color;
		texX = TILE_SIZE;
		texY = 0;
	} else {
		textColor = node->color;
		texX = 0;
		texY = 0;
	}
	if (UI_HasFocus(node))
		textColor = node->selectedColor;

	UI_GetNodeAbsPos(node, pos);

	Vector2Set(descriptionSize, descriptionWidth, node->size[1]);
	Vector2Set(bindingSize, bindingWidth, node->size[1]);
	Vector2Set(descriptionPos, pos[0], pos[1]);
	Vector2Set(bindingPos, pos[0] + descriptionWidth + node->padding, pos[1]);

	image = UI_GetReferenceString(node, node->image);
	if (image) {
		UI_DrawPanel(descriptionPos, descriptionSize, image, texX, texY, panelTemplate);
		UI_DrawPanel(bindingPos, bindingSize, image, texX, texY, panelTemplate);
	}

	binding = UI_GetReferenceString(node, node->text);
	if (Q_strnull(binding))
		binding = _("NONE");

	/** @todo check that this is a keybinding value (with macro expansion) */
	command = node->text + 9;
	description = Cmd_GetCommandDesc(command);
	if (description[0] == '\0')
		description = command;

	R_Color(textColor);

	UI_DrawStringInBox(font, node->contentAlign,
		descriptionPos[0] + node->padding, descriptionPos[1] + node->padding,
		descriptionSize[0] - node->padding - node->padding, descriptionSize[1] - node->padding - node->padding,
		description, LONGLINES_PRETTYCHOP);

	UI_DrawStringInBox(font, node->contentAlign,
		bindingPos[0] + node->padding, bindingPos[1] + node->padding,
		bindingSize[0] - node->padding - node->padding, bindingSize[1] - node->padding - node->padding,
		binding, LONGLINES_PRETTYCHOP);

	R_Color(NULL);
}
Exemplo n.º 5
0
void CG_DoGlass( vector3 verts[4], vector3 *normal, vector3 *dmgPt, vector3 *dmgDir, float dmgRadius, int maxShards )
{
	int			i, t;
	int			mxHeight, mxWidth;
	float		height, width;
	float		stepWidth, stepHeight;
	float		timeDecay;
	float		x, z;
	float		xx, zz;
	float		dif;
	int			time = 0;
	int			glassShards = 0;
	qboolean	stick = qtrue;
	vector3		subVerts[4];
	vector2		biPoints[4];

	// To do a smarter tesselation, we should figure out the relative height and width of the brush face,
	//	then use this to pick a lod value from 1-3 in each axis.  This will give us 1-9 lod levels, which will
	//	hopefully be sufficient.
	CG_CalcHeightWidth( verts, &height, &width );

	trap_S_StartSound( dmgPt, -1, CHAN_AUTO, trap_S_RegisterSound("sound/effects/glassbreak1.wav"));

	// Pick "LOD" for height
	if ( height < 100 )
	{
		stepHeight = 0.2f;
		mxHeight = 5;
		timeDecay = TIME_DECAY_SLOW;
	}
	else if ( height > 220 )
	{
		stepHeight = 0.05f;
		mxHeight = 20;
		timeDecay = TIME_DECAY_FAST;
	}
	else
	{
		stepHeight = 0.1f;
		mxHeight = 10;
		timeDecay = TIME_DECAY_MED;
	}

	// Pick "LOD" for width
	/*
	if ( width < 100 )
	{
		stepWidth = 0.2f;
		mxWidth = 5;
		timeDecay = ( timeDecay + TIME_DECAY_SLOW ) * 0.5f;
	}
	else if ( width > 220 )
	{
		stepWidth = 0.05f;
		mxWidth = 20;
		timeDecay = ( timeDecay + TIME_DECAY_FAST ) * 0.5f;
	}
	else
	{
		stepWidth = 0.1f;
		mxWidth = 10;
		timeDecay = ( timeDecay + TIME_DECAY_MED ) * 0.5f;
	}
	*/

	//Attempt to scale the glass directly to the size of the window

	stepWidth = (0.25f - (width*0.0002)); //(width*0.0005));
	mxWidth = width*0.2;
	timeDecay = ( timeDecay + TIME_DECAY_FAST ) * 0.5f;

	if (stepWidth < 0.01f)
	{
		stepWidth = 0.01f;
	}
	if (mxWidth < 5)
	{
		mxWidth = 5;
	}

	for ( z = 0.0f, i = 0; z < 1.0f; z += stepHeight, i++ )
	{
		for ( x = 0.0f, t = 0; x < 1.0f; x += stepWidth, t++ )
		{
			// This is nasty..
			if ( t > 0 && t < mxWidth )
			{
				xx = x - offX[i][t];
			}
			else
			{
				xx = x;
			}

			if ( i > 0 && i < mxHeight )
			{
				zz = z - offZ[t][i];
			}
			else
			{
				zz = z;
			}

			Vector2Set( &biPoints[0], xx, zz );

			if ( t + 1 > 0 && t + 1 < mxWidth )
			{
				xx = x - offX[i][t + 1];
			}
			else
			{
				xx = x;
			}

			if ( i > 0 && i < mxHeight )
			{
				zz = z - offZ[t + 1][i];
			}
			else
			{
				zz = z;
			}

			Vector2Set( &biPoints[1], xx + stepWidth, zz );

			if ( t + 1 > 0 && t + 1 < mxWidth )
			{
				xx = x - offX[i + 1][t + 1];
			}
			else
			{
				xx = x;
			}

			if ( i + 1 > 0 && i + 1 < mxHeight )
			{
				zz = z - offZ[t + 1][i + 1];
			}
			else
			{
				zz = z;
			}

			Vector2Set( &biPoints[2], xx + stepWidth, zz + stepHeight);

			if ( t > 0 && t < mxWidth )
			{
				xx = x - offX[i + 1][t];
			}
			else
			{
				xx = x;
			}

			if ( i + 1 > 0 && i + 1 < mxHeight )
			{
				zz = z - offZ[t][i + 1];
			}
			else
			{
				zz = z;
			}

			Vector2Set( &biPoints[3], xx, zz + stepHeight );

			CG_CalcBiLerp( verts, subVerts, biPoints );
			
			dif = DistanceSquared( &subVerts[0], dmgPt ) * timeDecay - random() * 32;
			
			// If we decrease dif, we are increasing the impact area, making it more likely to blow out large holes
			dif -= dmgRadius * dmgRadius;

			if ( dif > 1 )
			{
				stick = qtrue;
				time = dif + random() * 200;
			}
			else
			{
				stick = qfalse;
				time = 0;
			}

			CG_DoGlassQuad( subVerts, biPoints, stick, time, dmgDir );
			glassShards++;

			if (maxShards && glassShards >= maxShards)
			{
				return;
			}
		}
	}
}
Exemplo n.º 6
0
void R_DrawCameraEffect (void)
{
	image_t			*image[2];
	int32_t				x, y, w, h, i, j;
	float			texparms[2][4];
	vec2_t			texCoord[4];
	vec3_t			verts[4];
	renderparms_t	cameraParms;

	image[0] = R_DrawFindPic ("/gfx/2d/screenstatic.tga");
	image[1] = R_DrawFindPic ("/gfx/2d/scanlines.tga");

	if (!image[0] || !image[1])
		return;

	x = y = 0; w = vid.width; h = vid.height;
	GL_Disable (GL_ALPHA_TEST);
	GL_TexEnv (GL_MODULATE);
	GL_Enable (GL_BLEND);
	GL_BlendFunc (GL_DST_COLOR, GL_SRC_COLOR);
	GL_DepthMask   (false);

	VectorSet(verts[0], x, y, 0);
	VectorSet(verts[1], x+w, y, 0);
	VectorSet(verts[2], x+w, y+h, 0);
	VectorSet(verts[3], x, y+h, 0);

	Vector4Set(texparms[0], 2, 2, -30, 10);
	Vector4Set(texparms[1], 1, 10, 0, 0);

	rb_vertex = rb_index = 0;
	indexArray[rb_index++] = rb_vertex+0;
	indexArray[rb_index++] = rb_vertex+1;
	indexArray[rb_index++] = rb_vertex+2;
	indexArray[rb_index++] = rb_vertex+0;
	indexArray[rb_index++] = rb_vertex+2;
	indexArray[rb_index++] = rb_vertex+3;
	rb_vertex = 4;

	for (i=0; i<2; i++)
	{
		GL_Bind (image[i]->texnum);
		Vector2Set(texCoord[0], x/image[i]->width, y/image[i]->height);
		Vector2Set(texCoord[1], (x+w)/image[i]->width, y/image[i]->height);
		Vector2Set(texCoord[2], (x+w)/image[i]->width, (y+h)/image[i]->height);
		Vector2Set(texCoord[3], x/image[i]->width, (y+h)/image[i]->height);
		Mod_SetRenderParmsDefaults (&cameraParms);
		cameraParms.scale_x = texparms[i][0];
		cameraParms.scale_y = texparms[i][1];
		cameraParms.scroll_x = texparms[i][2];
		cameraParms.scroll_y = texparms[i][3];
		RB_ModifyTextureCoords (&texCoord[0][0], &verts[0][0], 4, cameraParms);
		for (j=0; j<4; j++) {
			VA_SetElem2(texCoordArray[0][j], texCoord[j][0], texCoord[j][1]);
			VA_SetElem3(vertexArray[j], verts[j][0], verts[j][1], verts[j][2]);
			VA_SetElem4(colorArray[j], 1, 1, 1, 1);
		}
		RB_DrawArrays ();
	}
	rb_vertex = rb_index = 0;

	GL_DepthMask (true);
	GL_BlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
	GL_Disable (GL_BLEND);
	GL_TexEnv (GL_REPLACE);
	GL_Enable (GL_ALPHA_TEST);
}
Exemplo n.º 7
0
/*
 =============
 R_DrawScaledImage
 Psychospaz's code for drawing stretched crosshairs
 =============
 */
void R_DrawScaledImage (int32_t x, int32_t y, float scale, float alpha, image_t *gl)
{
    float	xoff, yoff;
    float	scale_x, scale_y;
    int32_t		i;
    vec2_t	texCoord[4], verts[4];
    
    if (scrap_dirty)
        Scrap_Upload ();
    
    // add alpha support
    if (gl->has_alpha || alpha < 1.0)
    {
        GL_Disable (GL_ALPHA_TEST);
        GL_TexEnv (GL_MODULATE);
        GL_Enable (GL_BLEND);
        GL_DepthMask (false);
    }
    
    GL_Bind (gl->texnum);
    
    scale_x = scale_y = scale;
    scale_x *= gl->replace_scale_w; // scale down if replacing a pcx image
    scale_y *= gl->replace_scale_h; // scale down if replacing a pcx image
    
    Vector2Set(texCoord[0], gl->sl, gl->tl);
    Vector2Set(texCoord[1], gl->sh, gl->tl);
    Vector2Set(texCoord[2], gl->sh, gl->th);
    Vector2Set(texCoord[3], gl->sl, gl->th);
    
    xoff = gl->width*scale_x-gl->width;
    yoff = gl->height*scale_y-gl->height;
    
    Vector2Set(verts[0], x, y);
    Vector2Set(verts[1], x+gl->width+xoff, y);
    Vector2Set(verts[2], x+gl->width+xoff, y+gl->height+yoff);
    Vector2Set(verts[3], x, y+gl->height+yoff);
    
    rb_vertex = rb_index = 0;
    indexArray[rb_index++] = rb_vertex+0;
    indexArray[rb_index++] = rb_vertex+1;
    indexArray[rb_index++] = rb_vertex+2;
    indexArray[rb_index++] = rb_vertex+0;
    indexArray[rb_index++] = rb_vertex+2;
    indexArray[rb_index++] = rb_vertex+3;
    for (i=0; i<4; i++) {
        VA_SetElem2(texCoordArray[0][rb_vertex], texCoord[i][0], texCoord[i][1]);
        VA_SetElem3(vertexArray[rb_vertex], verts[i][0], verts[i][1], 0);
        VA_SetElem4(colorArray[rb_vertex], 1.0, 1.0, 1.0, alpha);
        rb_vertex++;
    }
    RB_RenderMeshGeneric (false);
    
    if (gl->has_alpha || alpha < 1.0)
    {
        GL_DepthMask (true);
        GL_TexEnv (GL_REPLACE);
        GL_Disable (GL_BLEND);
        GL_Enable (GL_ALPHA_TEST); // add alpha support
    }
}
Exemplo n.º 8
0
/*
================
R_DrawChar
Draws one variable sized graphics character with 0 being transparent.
It can be clipped to the top of the screen to allow the console to be
smoothly scrolled off.
================
*/
void R_DrawChar (float x, float y, int32_t num, float scale, 
	 int32_t red, int32_t green, int32_t blue, int32_t alpha, qboolean italic, qboolean last)
{
	int32_t			row, col, i;
	float		frow, fcol, size, cscale, italicAdd;
	vec2_t		texCoord[4], verts[4];
	qboolean	addChar = true;

	num &= 255;

	if (alpha > 255)
		alpha = 255;
	else if (alpha < 1)
		alpha = 1;

	if ((num & 127) == 32)	// space
		addChar = false;
	if (y <= -(scale * DEFAULT_FONT_SIZE))	// totally off screen
		addChar = false;

	row = num >> 4;
	col = num&15;

	frow = row*0.0625;
	fcol = col*0.0625;
	size = 0.0625;
	cscale = scale * DEFAULT_FONT_SIZE;

	italicAdd = (italic) ? (cscale*0.25) : 0;

	if (addChar)
	{
		Vector2Set(texCoord[0], fcol, frow);
		Vector2Set(texCoord[1], fcol + size, frow);
		Vector2Set(texCoord[2], fcol + size, frow + size);
		Vector2Set(texCoord[3], fcol, frow + size);

		Vector2Set(verts[0], x+italicAdd, y);
		Vector2Set(verts[1], x+cscale+italicAdd, y);
		Vector2Set(verts[2], x+cscale-italicAdd, y+cscale);
		Vector2Set(verts[3], x-italicAdd, y+cscale);

		if (char_count == 0)
			rb_vertex = rb_index = 0;
		if (rb_vertex + 4 >= MAX_VERTICES || rb_index + 6 >= MAX_INDICES)
			R_FlushChars ();
		indexArray[rb_index++] = rb_vertex+0;
		indexArray[rb_index++] = rb_vertex+1;
		indexArray[rb_index++] = rb_vertex+2;
		indexArray[rb_index++] = rb_vertex+0;
		indexArray[rb_index++] = rb_vertex+2;
		indexArray[rb_index++] = rb_vertex+3;
		for (i=0; i<4; i++) {
			VA_SetElem2(texCoordArray[0][rb_vertex], texCoord[i][0], texCoord[i][1]);
			VA_SetElem3(vertexArray[rb_vertex], verts[i][0], verts[i][1], 0);
			VA_SetElem4(colorArray[rb_vertex], red*DIV255, green*DIV255, blue*DIV255, alpha*DIV255);
			rb_vertex++;
		}
		char_count++;
	}
	if (last)
		R_FlushChars ();
}
Exemplo n.º 9
0
void CG_DoGlass( vec3_t verts[4], vec3_t normal, vec3_t dmgPt, vec3_t dmgDir, float dmgRadius )
{
	int		i, t;
	int		mxHeight, mxWidth;
	float	height, width;
	float	stepWidth, stepHeight;
	float	timeDecay;
	float	x, z;
	float	xx, zz;
	int		time = 0;
	bool	stick = true;
	vec3_t	subVerts[4];
	vec2_t	biPoints[4];

	// To do a smarter tesselation, we should figure out the relative height and width of the brush face,
	//	then use this to pick a lod value from 1-3 in each axis.  This will give us 1-9 lod levels, which will
	//	hopefully be sufficient.
	CG_CalcHeightWidth( verts, &height, &width );

	cgi_S_StartSound( dmgPt, -1, CHAN_AUTO, cgi_S_RegisterSound("sound/effects/glassbreak1.wav"));

	// Pick "LOD" for height
	if ( height < 100 )
	{
		stepHeight = 0.2f;
		mxHeight = 5;
		timeDecay = TIME_DECAY_SLOW;
	}
/*	else if ( height > 220 ) // was originally mxHeight = 20....but removing this whole section because it causes huge number of chunks...which is bad
	{
		stepHeight = 0.075f;
		mxHeight = 15;
		timeDecay = TIME_DECAY_FAST;
	}*/
	else
	{
		stepHeight = 0.1f;
		mxHeight = 10;
		timeDecay = TIME_DECAY_MED;
	}

	// Pick "LOD" for width
	if ( width < 100 )
	{
		stepWidth = 0.2f;
		mxWidth = 5;
		timeDecay = ( timeDecay + TIME_DECAY_SLOW ) * 0.5f;
	}
/*	else if ( width > 220 ) // don't do this because it causes too much chug with large glass panes...especially when more than one pane can be broken at a time
	{
		stepWidth = 0.075f;
		mxWidth = 15;
		timeDecay = ( timeDecay + TIME_DECAY_FAST ) * 0.5f;
	}*/
	else
	{
		stepWidth = 0.1f;
		mxWidth = 10;
		timeDecay = ( timeDecay + TIME_DECAY_MED ) * 0.5f;
	}

	for ( z = 0.0f, i = 0; z < 1.0f; z += stepHeight, i++ )
	{
		for ( x = 0.0f, t = 0; x < 1.0f; x += stepWidth, t++ )
		{
			// This is nasty..we do this because we don't want to add a random offset on the edge of the glass brush
			//	...but we do in the center, otherwise the breaking scheme looks way too orderly
			if ( t > 0 && t < mxWidth )
			{
				xx = x - offX[i][t];
			}
			else
			{
				xx = x;
			}

			if ( i > 0 && i < mxHeight )
			{
				zz = z - offZ[t][i];
			}
			else
			{
				zz = z;
			}

			Vector2Set( biPoints[0], xx, zz );

			if ( t + 1 > 0 && t + 1 < mxWidth )
			{
				xx = x - offX[i][t + 1];
			}
			else
			{
				xx = x;
			}

			if ( i > 0 && i < mxHeight )
			{
				zz = z - offZ[t + 1][i];
			}
			else
			{
				zz = z;
			}

			Vector2Set( biPoints[1], xx + stepWidth, zz );

			if ( t + 1 > 0 && t + 1 < mxWidth )
			{
				xx = x - offX[i + 1][t + 1];
			}
			else
			{
				xx = x;
			}

			if ( i + 1 > 0 && i + 1 < mxHeight )
			{
				zz = z - offZ[t + 1][i + 1];
			}
			else
			{
				zz = z;
			}

			Vector2Set( biPoints[2], xx + stepWidth, zz + stepHeight);

			if ( t > 0 && t < mxWidth )
			{
				xx = x - offX[i + 1][t];
			}
			else
			{
				xx = x;
			}

			if ( i + 1 > 0 && i + 1 < mxHeight )
			{
				zz = z - offZ[t][i + 1];
			}
			else
			{
				zz = z;
			}

			Vector2Set( biPoints[3], xx, zz + stepHeight );

			CG_CalcBiLerp( verts, subVerts, biPoints );

			float dif = DistanceSquared( subVerts[0], dmgPt ) * timeDecay - random() * 32;

			// If we decrease dif, we are increasing the impact area, making it more likely to blow out large holes
			dif -= dmgRadius * dmgRadius;

			if ( dif > 1 )
			{
				stick = true;
				time = dif + random() * 200;
			}
			else
			{
				stick = false;
				time = 0;
			}

			CG_DoGlassQuad( subVerts, biPoints, stick, time, dmgDir );
		}
	}
}
Exemplo n.º 10
0
/**
 * @brief Update xviInfection value for each nation, using the XVI overlay.
 * @note should be executed after all daily event that could change XVI overlay
 */
void CP_UpdateNationXVIInfection (void)
{
	/* No need to update XVI levels if the overlay didn't change */
	if (!xviNationInfectionNeedsUpdate)
		return;

	/* width in pixel of the XVI overlay */
	int width;
	/* height in pixel of the XVI overlay */
	int height;
	CP_GetXVIMapDimensions(&width, &height);

	const float heightPerDegree = height / 180.0f;
	const float widthPerDegree = width / 360.0f;
	/* parameter used to normalize nation XVI level.
	 * decrease this factor to increase XVI level per nation */
	const float AREA_FACTOR = 650.0f;
	/* area used to normalized XVI infection level for each nation.
	 * depend on overlay size so that if we change resolution of
	 * overlay it doesn't impact nation XIInfection */
	const float normalizingArea = width * height / AREA_FACTOR;

	/* temporary array to store the XVI levels */
	float xviInfection[MAX_NATIONS];
	/* Initialize array */
	OBJZERO(xviInfection);

	for (int y = 0; y < height; y++) {
		int sum[MAX_NATIONS];
		const byte* previousNationColor;
		const nation_t* nation;
		/* current position (in latitude / longitude) */
		vec2_t currentPos;

		OBJZERO(sum);

		Vector2Set(currentPos, 180.0f, 90.0f - y / heightPerDegree);
		previousNationColor = GEO_GetColor(currentPos, MAPTYPE_NATIONS, nullptr);
		nation = GEO_GetNation(currentPos);

		for (int x = 0; x < width; x++) {
			const byte* nationColor;
			currentPos[0] = 180.0f - x / widthPerDegree;
			nationColor = GEO_GetColor(currentPos, MAPTYPE_NATIONS, nullptr);
			if (!VectorCompare(nationColor, previousNationColor)) {
				previousNationColor = nationColor;
				nation = GEO_GetNation(currentPos);
			}
			if (nation) {
				const int xviLevel = CP_GetXVILevel(x, y);
				if (xviLevel > 0)
					sum[nation->idx] += xviLevel;
			}
		}
		/* divide the total XVI infection by the area of a pixel
		 * because pixel are smaller as you go closer from the pole */
		for (int nationIdx = 0; nationIdx < ccs.numNations; nationIdx++)
			xviInfection[nationIdx] += ((float) sum[nationIdx]) / (cos(torad * currentPos[1]) * normalizingArea);
	}

	/* copy the new values of XVI infection level into nation array */
	for (int nationIdx = 0; nationIdx < ccs.numNations; nationIdx++) {
		nation_t* nation = NAT_GetNationByIDX(nationIdx);
		nation->stats[0].xviInfection = ceil(xviInfection[nation->idx]);
	}

	xviNationInfectionNeedsUpdate = false;
}