示例#1
0
文件: view.c 项目: DrBeef/QuakeGVR
/*
===============
V_ParseDamage
===============
*/
void V_ParseDamage (void)
{
	int armor, blood;
	vec3_t from;
	//vec3_t forward, right;
	vec3_t localfrom;
	entity_t *ent;
	//float side;
	float count;

	armor = MSG_ReadByte(&cl_message);
	blood = MSG_ReadByte(&cl_message);
	MSG_ReadVector(&cl_message, from, cls.protocol);

	// Send the Dmg Globals to CSQC
	CL_VM_UpdateDmgGlobals(blood, armor, from);

	count = blood*0.5 + armor*0.5;
	if (count < 10)
		count = 10;

	cl.faceanimtime = cl.time + 0.2;		// put sbar face into pain frame

	cl.cshifts[CSHIFT_DAMAGE].percent += 3*count;
	cl.cshifts[CSHIFT_DAMAGE].alphafade = 150;
	if (cl.cshifts[CSHIFT_DAMAGE].percent < 0)
		cl.cshifts[CSHIFT_DAMAGE].percent = 0;
	if (cl.cshifts[CSHIFT_DAMAGE].percent > 150)
		cl.cshifts[CSHIFT_DAMAGE].percent = 150;

	if (armor > blood)
	{
		cl.cshifts[CSHIFT_DAMAGE].destcolor[0] = 200;
		cl.cshifts[CSHIFT_DAMAGE].destcolor[1] = 100;
		cl.cshifts[CSHIFT_DAMAGE].destcolor[2] = 100;
	}
	else if (armor)
	{
		cl.cshifts[CSHIFT_DAMAGE].destcolor[0] = 220;
		cl.cshifts[CSHIFT_DAMAGE].destcolor[1] = 50;
		cl.cshifts[CSHIFT_DAMAGE].destcolor[2] = 50;
	}
	else
	{
		cl.cshifts[CSHIFT_DAMAGE].destcolor[0] = 255;
		cl.cshifts[CSHIFT_DAMAGE].destcolor[1] = 0;
		cl.cshifts[CSHIFT_DAMAGE].destcolor[2] = 0;
	}

	// calculate view angle kicks
	if (cl.entities[cl.viewentity].state_current.active)
	{
		ent = &cl.entities[cl.viewentity];
		Matrix4x4_Transform(&ent->render.inversematrix, from, localfrom);
		VectorNormalize(localfrom);
		v_dmg_pitch = count * localfrom[0] * v_kickpitch.value;
		v_dmg_roll = count * localfrom[1] * v_kickroll.value;
		v_dmg_time = v_kicktime.value;
	}
}
示例#2
0
/**
 * @brief Adds new stains from the view each frame.
 */
void R_AddStains(void) {

    const r_stain_t *s = r_view.stains;
    for (int32_t i = 0; i < r_view.num_stains; i++, s++) {

        R_StainNode(s, r_model_state.world->bsp->nodes);

        for (uint16_t i = 0; i < cl.frame.num_entities; i++) {

            const uint32_t snum = (cl.frame.entity_state + i) & ENTITY_STATE_MASK;
            const entity_state_t *st = &cl.entity_states[snum];

            if (st->solid != SOLID_BSP) {
                continue;
            }

            const cl_entity_t *ent = &cl.entities[st->number];
            const cm_bsp_model_t *mod = cl.cm_models[st->model1];

            if (mod == NULL || mod->head_node == -1) {
                continue;
            }

            r_bsp_node_t *node = &r_model_state.world->bsp->nodes[mod->head_node];

            r_stain_t stain = *s;
            Matrix4x4_Transform(&ent->inverse_matrix, s->origin, stain.origin);

            R_StainNode(&stain, node);
        }
    }

    g_hash_table_foreach(r_surfs_stained, R_AddStains_UploadSurfaces, NULL);
    g_hash_table_remove_all(r_surfs_stained);
}
示例#3
0
/**
 * Transforms a point by the inverse of the world-model matrix for the
 * specified entity.
 */
void R_TransformForEntity (const entity_t* e, const vec3_t in, vec3_t out)
{
	matrix4x4_t tmp, mat;

	Matrix4x4_CreateFromQuakeEntity(&tmp, e->origin[0], e->origin[1], e->origin[2], e->angles[0], e->angles[1],
			e->angles[2], e->getScaleX());

	Matrix4x4_Invert_Simple(&mat, &tmp);
	Matrix4x4_Transform(&mat, in, out);
}
示例#4
0
/**
 * @brief Applies any configuration and tag alignment, populating the model-view
 * matrix for the entity in the process.
 */
void R_SetMatrixForEntity(r_entity_t *e) {

	if (e->parent) {
		vec3_t forward;

		if (!IS_MESH_MODEL(e->model)) {
			Com_Warn("Invalid model for linked entity\n");
			return;
		}

		const r_entity_t *p = e->parent;
		while (p->parent) {
			p = p->parent;
		}

		AngleVectors(p->angles, forward, NULL, NULL);

		VectorClear(e->origin);
		VectorClear(e->angles);

		Matrix4x4_CreateFromEntity(&e->matrix, e->origin, e->angles, e->scale);

		R_ApplyMeshModelTag(e);

		R_ApplyMeshModelConfig(e);

		Matrix4x4_Invert_Simple(&e->inverse_matrix, &e->matrix);

		Matrix4x4_Transform(&e->matrix, vec3_origin, e->origin);
		Matrix4x4_Transform(&e->matrix, vec3_forward, forward);

		VectorAngles(forward, e->angles);
		return;
	}

	Matrix4x4_CreateFromEntity(&e->matrix, e->origin, e->angles, e->scale);

	if (IS_MESH_MODEL(e->model)) {
		R_ApplyMeshModelConfig(e);
	}

	Matrix4x4_Invert_Simple(&e->inverse_matrix, &e->matrix);
}
示例#5
0
/**
 * @brief
 */
void R_UseLight_default(const uint16_t light_index, const r_light_t *light) {

	r_default_program_t *p = &r_default_program;

	if (light && light->radius) {
		vec3_t origin;
		const matrix4x4_t *modelview = R_GetMatrixPtr(R_MATRIX_MODELVIEW);
		Matrix4x4_Transform(modelview, light->origin, origin);

		R_ProgramParameter3fv(&p->lights[light_index].origin, origin);
		R_ProgramParameter3fv(&p->lights[light_index].color, light->color);
		R_ProgramParameter1f(&p->lights[light_index].radius, light->radius);
	} else {
		R_ProgramParameter1f(&p->lights[light_index].radius, 0.0);
	}
}
示例#6
0
qboolean R_Shader_StartLightPass( unsigned int lightIndex ) {
	GLint valid;
	R_ShaderLight *light = GetLightFromIndex( lightIndex );
	matrix4x4_t *worldToViewMatrix = &r_refdef.lightShader.worldToViewMatrix;
	vec3_t lightPosition, newcolor;
	float f;
	
	assert( light->active  == true );

	// setup cubemap texture generation
	if( gl_support_cubemaps ) {
		matrix4x4_t worldToLightMatrix;
		matrix4x4_t viewToWorldMatrix;
		matrix4x4_t viewToLightMatrix;

		// setup the cubemap
		qglSelectTextureARB( GL_TEXTURE1_ARB );
		glEnable( GL_TEXTURE_CUBE_MAP_ARB );
		glBindTexture( GL_TEXTURE_CUBE_MAP_ARB, GL_LoadCubeTexImage( light->cubemapname, false, true ) ); 
		qglSelectTextureARB( GL_TEXTURE0_ARB );
		
		// invert worldToViewMatrix
		worldToLightMatrix = GetWorldToLightMatrix( light );
		Matrix4x4_Invert_Simple( &viewToWorldMatrix, worldToViewMatrix );
		Matrix4x4_Concat( &viewToLightMatrix, &worldToLightMatrix, &viewToWorldMatrix );

		qglUniformMatrix4fvARB( r_refdef.lightShader.viewToLightMatrix, 1, true, (float *)&viewToLightMatrix.m );
	}

	Matrix4x4_Transform( worldToViewMatrix, light->origin, lightPosition );
	//Con_Printf( "Light distance to origin: %f (vs %f)\n", VectorDistance( light->origin, r_refdef.vieworg ), VectorLength( lightPosition ) );
    
	qglUniform3fvARB( r_refdef.lightShader.lightPosition, 1, lightPosition );
	f = (light->style >= 0 ? d_lightstylevalue[light->style] : 128) * (1.0f / 256.0f) * r_shadow_lightintensityscale.value;
	VectorScale(light->color, f, newcolor);
	qglUniform3fvARB( r_refdef.lightShader.lightColor, 1, newcolor );
	qglUniform1fARB( r_refdef.lightShader.lightMaxDistance, light->maxDistance );

	qglValidateProgramARB( r_refdef.lightShader.programObject );
	qglGetObjectParameterivARB( r_refdef.lightShader.programObject, GL_OBJECT_VALIDATE_STATUS_ARB, &valid );
	return valid == true;
}
示例#7
0
float CL_SelectTraceLine(const vec3_t start, const vec3_t end, vec3_t impact, vec3_t normal, int *hitent, entity_render_t *ignoreent)
#endif
{
	float maxfrac, maxrealfrac;
	int n;
	entity_render_t *ent;
	float tracemins[3], tracemaxs[3];
	trace_t trace;
	float tempnormal[3], starttransformed[3], endtransformed[3];
#ifdef COLLISION_STUPID_TRACE_ENDPOS_IN_SOLID_WORKAROUND
	vec3_t end;
	vec_t len = 0;

	if(!VectorCompare(start, pEnd) && collision_endposnudge.value > 0)
	{
		// TRICK: make the trace 1 qu longer!
		VectorSubtract(pEnd, start, end);
		len = VectorNormalizeLength(end);
		VectorMA(pEnd, collision_endposnudge.value, end, end);
	}
	else
		VectorCopy(pEnd, end);
#endif

	memset (&trace, 0 , sizeof(trace_t));
	trace.fraction = 1;
	trace.realfraction = 1;
	VectorCopy (end, trace.endpos);

	if (hitent)
		*hitent = 0;
	if (cl.worldmodel && cl.worldmodel->TraceLine)
		cl.worldmodel->TraceLine(cl.worldmodel, NULL, NULL, &trace, start, end, SUPERCONTENTS_SOLID);

	if (normal)
		VectorCopy(trace.plane.normal, normal);
	maxfrac = trace.fraction;
	maxrealfrac = trace.realfraction;

	tracemins[0] = min(start[0], end[0]);
	tracemaxs[0] = max(start[0], end[0]);
	tracemins[1] = min(start[1], end[1]);
	tracemaxs[1] = max(start[1], end[1]);
	tracemins[2] = min(start[2], end[2]);
	tracemaxs[2] = max(start[2], end[2]);

	// look for embedded bmodels
	for (n = 0;n < cl.num_entities;n++)
	{
		if (!cl.entities_active[n])
			continue;
		ent = &cl.entities[n].render;
		if (!BoxesOverlap(ent->mins, ent->maxs, tracemins, tracemaxs))
			continue;
		if (!ent->model || !ent->model->TraceLine)
			continue;
		if ((ent->flags & RENDER_EXTERIORMODEL) && !chase_active.integer)
			continue;
		// if transparent and not selectable, skip entity
		if (!(cl.entities[n].state_current.effects & EF_SELECTABLE) && (ent->alpha < 1 || (ent->effects & (EF_ADDITIVE | EF_NODEPTHTEST))))
			continue;
		if (ent == ignoreent)
			continue;
		Matrix4x4_Transform(&ent->inversematrix, start, starttransformed);
		Matrix4x4_Transform(&ent->inversematrix, end, endtransformed);
		Collision_ClipTrace_Box(&trace, ent->model->normalmins, ent->model->normalmaxs, starttransformed, vec3_origin, vec3_origin, endtransformed, SUPERCONTENTS_SOLID, SUPERCONTENTS_SOLID, 0, NULL);
#ifdef COLLISION_STUPID_TRACE_ENDPOS_IN_SOLID_WORKAROUND
		if(!VectorCompare(start, pEnd) && collision_endposnudge.value > 0)
			Collision_ShortenTrace(&trace, len / (len + collision_endposnudge.value), pEnd);
#endif
		if (maxrealfrac < trace.realfraction)
			continue;

		ent->model->TraceLine(ent->model, ent->frameblend, ent->skeleton, &trace, starttransformed, endtransformed, SUPERCONTENTS_SOLID);

		if (maxrealfrac > trace.realfraction)
		{
			if (hitent)
				*hitent = n;
			maxfrac = trace.fraction;
			maxrealfrac = trace.realfraction;
			if (normal)
			{
				VectorCopy(trace.plane.normal, tempnormal);
				Matrix4x4_Transform3x3(&ent->matrix, tempnormal, normal);
			}
		}
	}
	maxfrac = bound(0, maxfrac, 1);
	maxrealfrac = bound(0, maxrealfrac, 1);
	//if (maxfrac < 0 || maxfrac > 1) Con_Printf("fraction out of bounds %f %s:%d\n", maxfrac, __FILE__, __LINE__);
	if (impact)
		VectorLerp(start, maxfrac, end, impact);
	return maxfrac;
}
示例#8
0
static void R_TrackSprite(const entity_render_t *ent, vec3_t origin, vec3_t left, vec3_t up, int *edge, float *dir_angle)
{
	float distance;
	vec3_t bCoord; // body coordinates of object
	unsigned int i;

	// temporarily abuse bCoord as the vector player->sprite-origin
	VectorSubtract(origin, r_refdef.view.origin, bCoord);
	distance = VectorLength(bCoord);

	// Now get the bCoords :)
	Matrix4x4_Transform(&r_refdef.view.inverse_matrix, origin, bCoord);

	*edge = 0; // FIXME::should assume edge == 0, which is correct currently
	for(i = 0; i < 4; ++i)
	{
		if(PlaneDiff(origin, &r_refdef.view.frustum[i]) < -EPSILON)
			break;
	}

	// If it wasn't outside a plane, no tracking needed
	if(i < 4)
	{
		float x, y;    // screen X and Y coordinates
		float ax, ay;  // absolute coords, used for division
		// I divide x and y by the greater absolute value to get ranges -1.0 to +1.0
		
		bCoord[2] *= r_refdef.view.frustum_x;
		bCoord[1] *= r_refdef.view.frustum_y;

		//Con_Printf("%f %f %f\n", bCoord[0], bCoord[1], bCoord[2]);
		
		ax = fabs(bCoord[1]);
		ay = fabs(bCoord[2]);
		// get the greater value and determine the screen edge it's on
		if(ax < ay)
		{
			ax = ay;
			// 180 or 0 degrees
			if(bCoord[2] < 0.0f)
				*edge = SIDE_BOTTOM;
			else
				*edge = SIDE_TOP;
		} else {
			if(bCoord[1] < 0.0f)
				*edge = SIDE_RIGHT;
			else
				*edge = SIDE_LEFT;
		}
		
		// umm... 
		if(ax < MIN_EPSILON) // this was == 0.0f before --blub
			ax = MIN_EPSILON;
		// get the -1 to +1 range
		x = bCoord[1] / ax;
		y = bCoord[2] / ax;

		ax = (1.0f / VectorLength(left));
		ay = (1.0f / VectorLength(up));
		// Using the placement below the distance of a sprite is
		// real dist = sqrt(d*d + dfxa*dfxa + dgyb*dgyb)
		// d is the distance we use
		// f is frustum X
		// x is x
		// a is ax
		// g is frustum Y
		// y is y
		// b is ay
		
		// real dist (r) shall be d, so
		// r*r = d*d + dfxa*dfxa + dgyb*dgyb
		// r*r = d*d * (1 + fxa*fxa + gyb*gyb)
		// d*d = r*r / (1 + fxa*fxa + gyb*gyb)
		// d = sqrt(r*r / (1 + fxa*fxa + gyb*gyb))
		// thus:
		distance = sqrt((distance*distance) / (1.0 +
					r_refdef.view.frustum_x*r_refdef.view.frustum_x * x*x * ax*ax +
					r_refdef.view.frustum_y*r_refdef.view.frustum_y * y*y * ay*ay));
		// ^ the one we want        ^ the one we have       ^ our factors
		
		// Place the sprite a few units ahead of the player
		VectorCopy(r_refdef.view.origin, origin);
		VectorMA(origin, distance, r_refdef.view.forward, origin);
		// Move the sprite left / up the screeen height
		VectorMA(origin, distance * r_refdef.view.frustum_x * x * ax, left, origin);
		VectorMA(origin, distance * r_refdef.view.frustum_y * y * ay, up, origin);

		if(r_track_sprites_flags.integer & TSF_ROTATE_CONTINOUSLY)
		{
			// compute the rotation, negate y axis, we're pointing outwards
			*dir_angle = atan(-y / x) * 180.0f/M_PI;
			// we need the real, full angle
			if(x < 0.0f)
				*dir_angle += 180.0f;
		}

		left[0] *= r_track_sprites_scalew.value;
		left[1] *= r_track_sprites_scalew.value;
		left[2] *= r_track_sprites_scalew.value;

		up[0] *= r_track_sprites_scaleh.value;
		up[1] *= r_track_sprites_scaleh.value;
		up[2] *= r_track_sprites_scaleh.value;
	}
}
示例#9
0
static void R_RotateSprite(const mspriteframe_t *frame, vec3_t origin, vec3_t left, vec3_t up, int edge, float dir_angle)
{
	if(!(r_track_sprites_flags.integer & TSF_ROTATE))
	{
		// move down by its size if on top, otherwise it's invisible
		if(edge == SIDE_TOP)
			VectorMA(origin, -(fabs(frame->up)+fabs(frame->down)), up, origin);
	} else {
		static float rotation_angles[5] =
		{
			0, // no edge
			-90.0f,	//top
			0.0f,	// left
			90.0f,	// bottom
			180.0f,	// right
		};
		
		// rotate around the hotspot according to which edge it's on
		// since the hotspot == the origin, only rotate the vectors
		matrix4x4_t rotm;
		vec3_t axis;
		vec3_t temp;
		vec2_t dir;
		float angle;

		if(edge < 1 || edge > 4)
			return; // this usually means something went wrong somewhere, there's no way to get a wrong edge value currently
		
		dir[0] = frame->right + frame->left;
		dir[1] = frame->down + frame->up;

		// only rotate when the hotspot isn't the center though.
		if(dir[0] < MIN_EPSILON && dir[1] < MIN_EPSILON)
		{
			return;
		}

		// Now that we've kicked center-hotspotted sprites, rotate using the appropriate matrix :)

		// determine the angle of a sprite, we could only do that once though and
		// add a `qboolean initialized' to the mspriteframe_t struct... let's get the direction vector of it :)

		angle = atan(dir[1] / dir[0]) * 180.0f/M_PI;

		// we need the real, full angle
		if(dir[0] < 0.0f)
			angle += 180.0f;

		// Rotate around rotation_angle - frame_angle
		// The axis SHOULD equal r_refdef.view.forward, but let's generalize this:
		CrossProduct(up, left, axis);
		if(r_track_sprites_flags.integer & TSF_ROTATE_CONTINOUSLY)
			Matrix4x4_CreateRotate(&rotm, dir_angle - angle, axis[0], axis[1], axis[2]);
		else
			Matrix4x4_CreateRotate(&rotm, rotation_angles[edge] - angle, axis[0], axis[1], axis[2]);
		Matrix4x4_Transform(&rotm, up, temp);
		VectorCopy(temp, up);
		Matrix4x4_Transform(&rotm, left, temp);
		VectorCopy(temp, left);
	}
}