/* * @brief Updates the clipping planes for the view frustum based on the origin * and angles for this frame. */ void R_UpdateFrustum(void) { int32_t i; if (!r_cull->value) return; cm_bsp_plane_t *p = r_locals.frustum; const vec_t fov_x = r_view.fov[0]; const vec_t fov_y = r_view.fov[1]; // rotate r_view.forward right by fov_x degrees RotatePointAroundVector(r_view.forward, r_view.right, -(90.0 - fov_x), (p++)->normal); // rotate r_view.forward left by fov_x degrees RotatePointAroundVector(r_view.forward, r_view.right, 90.0 - fov_x, (p++)->normal); // rotate r_view.forward up by fov_y degrees RotatePointAroundVector(r_view.forward, r_view.up, 90.0 - fov_y, (p++)->normal); // rotate r_view.forward down by fov_y degrees RotatePointAroundVector(r_view.forward, r_view.up, -(90.0 - fov_y), p->normal); for (i = 0; i < 4; i++) { r_locals.frustum[i].type = PLANE_ANY_Z; r_locals.frustum[i].dist = DotProduct(r_view.origin, r_locals.frustum[i].normal); r_locals.frustum[i].sign_bits = Cm_SignBitsForPlane(&r_locals.frustum[i]); } }
/* * @brief Updates the clipping planes for the view frustum based on the origin * and angles for this frame. */ void R_UpdateFrustum(void) { int32_t i; if (!r_cull->value) return; // rotate r_view.forward right by fov_x / 2 degrees RotatePointAroundVector(r_locals.frustum[0].normal, r_view.up, r_view.forward, -(90 - r_view.fov[0] / 2)); // rotate r_view.forward left by fov_x / 2 degrees RotatePointAroundVector(r_locals.frustum[1].normal, r_view.up, r_view.forward, 90 - r_view.fov[0] / 2); // rotate r_view.forward up by fov_x / 2 degrees RotatePointAroundVector(r_locals.frustum[2].normal, r_view.right, r_view.forward, 90 - r_view.fov[1] / 2); // rotate r_view.forward down by fov_x / 2 degrees RotatePointAroundVector(r_locals.frustum[3].normal, r_view.right, r_view.forward, -(90 - r_view.fov[1] / 2)); for (i = 0; i < 4; i++) { r_locals.frustum[i].type = PLANE_ANYZ; r_locals.frustum[i].dist = DotProduct(r_view.origin, r_locals.frustum[i].normal); r_locals.frustum[i].sign_bits = SignBitsForPlane(&r_locals.frustum[i]); } }
void R_SetFrustum (void) { int i; if (r_refdef.fov_x == 90) { // front side is visible VectorAdd (vpn, vright, frustum[0].normal); VectorSubtract (vpn, vright, frustum[1].normal); VectorAdd (vpn, vup, frustum[2].normal); VectorSubtract (vpn, vup, frustum[3].normal); } else { // rotate VPN right by FOV_X/2 degrees RotatePointAroundVector( frustum[0].normal, vup, vpn, -(90-r_refdef.fov_x / 2 ) ); // rotate VPN left by FOV_X/2 degrees RotatePointAroundVector( frustum[1].normal, vup, vpn, 90-r_refdef.fov_x / 2 ); // rotate VPN up by FOV_X/2 degrees RotatePointAroundVector( frustum[2].normal, vright, vpn, 90-r_refdef.fov_y / 2 ); // rotate VPN down by FOV_X/2 degrees RotatePointAroundVector( frustum[3].normal, vright, vpn, -( 90 - r_refdef.fov_y / 2 ) ); } for (i=0 ; i<4 ; i++) { frustum[i].type = PLANE_ANYZ; frustum[i].dist = DotProduct (r_origin, frustum[i].normal); frustum[i].signbits = SignbitsForPlane (&frustum[i]); } }
/* * R_SetupFrustum */ void R_SetupFrustum( const refdef_t *rd, float farClip, cplane_t *frustum ) { int i; vec3_t forward, left, up; // 0 - left // 1 - right // 2 - down // 3 - up // 4 - farclip VectorCopy( &rd->viewaxis[AXIS_FORWARD], forward ); VectorCopy( &rd->viewaxis[AXIS_RIGHT], left ); VectorCopy( &rd->viewaxis[AXIS_UP], up ); if( rd->rdflags & RDF_USEORTHO ) { VectorNegate( left, frustum[0].normal ); VectorCopy( left, frustum[1].normal ); VectorNegate( up, frustum[2].normal ); VectorCopy( up, frustum[3].normal ); for( i = 0; i < 4; i++ ) { frustum[i].type = PLANE_NONAXIAL; frustum[i].dist = DotProduct( rd->vieworg, frustum[i].normal ); frustum[i].signbits = SignbitsForPlane( &frustum[i] ); } frustum[0].dist -= rd->ortho_x; frustum[1].dist -= rd->ortho_x; frustum[2].dist -= rd->ortho_y; frustum[3].dist -= rd->ortho_y; } else { vec3_t right; VectorNegate( left, right ); // rotate rn.vpn right by FOV_X/2 degrees RotatePointAroundVector( frustum[0].normal, up, forward, -( 90-rd->fov_x / 2 ) ); // rotate rn.vpn left by FOV_X/2 degrees RotatePointAroundVector( frustum[1].normal, up, forward, 90-rd->fov_x / 2 ); // rotate rn.vpn up by FOV_X/2 degrees RotatePointAroundVector( frustum[2].normal, right, forward, 90-rd->fov_y / 2 ); // rotate rn.vpn down by FOV_X/2 degrees RotatePointAroundVector( frustum[3].normal, right, forward, -( 90 - rd->fov_y / 2 ) ); for( i = 0; i < 4; i++ ) { frustum[i].type = PLANE_NONAXIAL; frustum[i].dist = DotProduct( rd->vieworg, frustum[i].normal ); frustum[i].signbits = SignbitsForPlane( &frustum[i] ); } } // farclip VectorNegate( forward, frustum[4].normal ); frustum[4].type = PLANE_NONAXIAL; frustum[4].dist = DotProduct( rd->vieworg, frustum[4].normal ) - farClip; frustum[4].signbits = SignbitsForPlane( &frustum[4] ); }
void R_SetupFrustum (void) { int i; /* build the transformation matrix for the given view angles */ AngleVectors(refdef.viewAngles, r_locals.forward, r_locals.right, r_locals.up); #if 0 /* if we are not drawing world model, we are on the UI code. It break the default UI SCISSOR * Anyway we should merge that code into R_CleanupDepthBuffer (with some rework), it looks better */ /* clear out the portion of the screen that the NOWORLDMODEL defines */ if (refdef.rendererFlags & RDF_NOWORLDMODEL) { glEnable(GL_SCISSOR_TEST); glScissor(viddef.x, viddef.height - viddef.viewHeight - viddef.y, viddef.viewWidth, viddef.viewHeight); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); R_CheckError(); glDisable(GL_SCISSOR_TEST); } #endif if (r_isometric->integer) { /* 4 planes of a cube */ VectorScale(r_locals.right, +1, r_locals.frustum[0].normal); VectorScale(r_locals.right, -1, r_locals.frustum[1].normal); VectorScale(r_locals.up, +1, r_locals.frustum[2].normal); VectorScale(r_locals.up, -1, r_locals.frustum[3].normal); for (i = 0; i < 4; i++) { r_locals.frustum[i].type = PLANE_ANYZ; r_locals.frustum[i].dist = DotProduct(refdef.viewOrigin, r_locals.frustum[i].normal); } r_locals.frustum[0].dist -= 10 * refdef.fieldOfViewX; r_locals.frustum[1].dist -= 10 * refdef.fieldOfViewX; r_locals.frustum[2].dist -= 10 * refdef.fieldOfViewX * ((float) viddef.viewHeight / viddef.viewWidth); r_locals.frustum[3].dist -= 10 * refdef.fieldOfViewX * ((float) viddef.viewHeight / viddef.viewWidth); } else { /* rotate VPN right by FOV_X/2 degrees */ RotatePointAroundVector(r_locals.frustum[0].normal, r_locals.up, r_locals.forward, -(90 - refdef.fieldOfViewX / 2)); /* rotate VPN left by FOV_X/2 degrees */ RotatePointAroundVector(r_locals.frustum[1].normal, r_locals.up, r_locals.forward, 90 - refdef.fieldOfViewX / 2); /* rotate VPN up by FOV_X/2 degrees */ RotatePointAroundVector(r_locals.frustum[2].normal, r_locals.right, r_locals.forward, 90 - refdef.fieldOfViewY / 2); /* rotate VPN down by FOV_X/2 degrees */ RotatePointAroundVector(r_locals.frustum[3].normal, r_locals.right, r_locals.forward, -(90 - refdef.fieldOfViewY / 2)); for (i = 0; i < 4; i++) { r_locals.frustum[i].type = PLANE_ANYZ; r_locals.frustum[i].dist = DotProduct(refdef.viewOrigin, r_locals.frustum[i].normal); } } }
/** * @brief rotate a planet (sun or moon) with respect to the earth */ static inline void R_RotateCelestialBody (const vec4_t v, vec4_t r, const vec3_t rotate, const vec3_t earthPos, const float celestialDist) { vec4_t v1; vec3_t v2; vec3_t rotationAxis; VectorSet(v2, v[1], v[0], v[2]); VectorSet(rotationAxis, 0, 0, 1); RotatePointAroundVector(v1, rotationAxis, v2, -rotate[PITCH]); VectorSet(rotationAxis, 0, 1, 0); RotatePointAroundVector(v2, rotationAxis, v1, -rotate[YAW]); Vector4Set(r, earthPos[0] + celestialDist * v2[1], earthPos[1] + celestialDist * v2[0], -celestialDist * v2[2], 0); }
/* =============== CG_smoothWJTransitions =============== */ static void CG_smoothWJTransitions( playerState_t *ps, const vec3_t in, vec3_t out ) { int i; float stLocal, sFraction; qboolean performed = qfalse; vec3_t inAxis[ 3 ], outAxis[ 3 ]; Q_UNUSED(ps); if ( cg.snap->ps.pm_flags & PMF_FOLLOW ) { VectorCopy( in, out ); return; } AnglesToAxis( in, inAxis ); //iterate through ops for ( i = MAXSMOOTHS - 1; i >= 0; i-- ) { //if this op has time remaining, perform it if ( cg.time < cg.sList[ i ].time + cg_wwSmoothTime.integer ) { stLocal = ( ( cg.sList[ i ].time + cg_wwSmoothTime.integer ) - cg.time ) / cg_wwSmoothTime.integer; sFraction = 1.0f - ( ( cos( stLocal * M_PI * 2.0f ) + 1.0f ) / 2.0f ); RotatePointAroundVector( outAxis[ 0 ], cg.sList[ i ].rotAxis, inAxis[ 0 ], sFraction * cg.sList[ i ].rotAngle ); RotatePointAroundVector( outAxis[ 1 ], cg.sList[ i ].rotAxis, inAxis[ 1 ], sFraction * cg.sList[ i ].rotAngle ); RotatePointAroundVector( outAxis[ 2 ], cg.sList[ i ].rotAxis, inAxis[ 2 ], sFraction * cg.sList[ i ].rotAngle ); AxisCopy( outAxis, inAxis ); performed = qtrue; } } //if we performed any ops then return the smoothed angles //otherwise simply return the in angles if ( performed ) { AxisToAngles( outAxis, out ); } else { VectorCopy( in, out ); } }
/* ** RB_SurfaceLightningBolt */ static void RB_SurfaceLightningBolt( void ) { refEntity_t *e; int len; vec3_t right; vec3_t vec; vec3_t start, end; vec3_t v1, v2; int i; e = &backEnd.currentEntity->e; VectorCopy( e->oldorigin, end ); VectorCopy( e->origin, start ); // compute variables VectorSubtract( end, start, vec ); len = VectorNormalize( vec ); // compute side vector VectorSubtract( start, backEnd.viewParms.or.origin, v1 ); VectorNormalize( v1 ); VectorSubtract( end, backEnd.viewParms.or.origin, v2 ); VectorNormalize( v2 ); CrossProduct( v1, v2, right ); VectorNormalize( right ); for ( i = 0 ; i < 4 ; i++ ) { vec3_t temp; DoRailCore( start, end, right, len, 8 ); RotatePointAroundVector( temp, vec, right, 45 ); VectorCopy( temp, right ); } }
static bool BOT_DMclass_FindRocket( edict_t *self, vec3_t away_from_rocket ) { #define AI_ROCKET_DETECT_RADIUS 1000 #define AI_ROCKET_DANGER_RADIUS 200 int i, numtargets; int targets[MAX_EDICTS]; edict_t *target; float min_roxx_time = 1.0f; bool any_rocket = false; numtargets = GClip_FindRadius( self->s.origin, AI_ROCKET_DETECT_RADIUS, targets, MAX_EDICTS ); for( i = 0; i < numtargets; i++ ) { target = game.edicts + targets[i]; // Missile detection code if( target->r.svflags & SVF_PROJECTILE && target->s.type != ET_PLASMA ) // (plasmas come in bunchs so are too complex for the bot to dodge) { if( target->r.owner && target->r.owner != self ) { vec3_t end; trace_t trace; VectorMA( target->s.origin, 2, target->velocity, end ); G_Trace( &trace, target->s.origin, target->r.mins, target->r.maxs, end, target, MASK_SOLID ); if( trace.fraction < min_roxx_time ) { vec_t l; any_rocket = true; min_roxx_time = trace.fraction; VectorSubtract( trace.endpos, self->s.origin, end ); // ok... end is where the impact will be. // trace.fraction is the time. if( ( l = VectorLengthFast( end ) ) < AI_ROCKET_DANGER_RADIUS ) { RotatePointAroundVector( away_from_rocket, &axis_identity[AXIS_UP], end, -self->s.angles[YAW] ); VectorNormalize( away_from_rocket ); if( fabs( away_from_rocket[0] ) < 0.3 ) away_from_rocket[0] = 0; if( fabs( away_from_rocket[1] ) < 0.3 ) away_from_rocket[1] = 0; away_from_rocket[2] = 0; away_from_rocket[0] *= -1.0f; away_from_rocket[1] *= -1.0f; if( nav.debugMode && bot_showcombat->integer > 2 ) G_PrintChasersf( self, "%s: ^1projectile dodge: ^2%f, %f d=%f^7\n", self->ai->pers.netname, away_from_rocket[0], away_from_rocket[1], l ); } } } } } return any_rocket; #undef AI_ROCKET_DETECT_RADIUS #undef AI_ROCKET_DANGER_RADIUS }
void CG_ImpactMark(qhandle_t markShader, vec3_t origin, vec4_t projection, float radius, float orientation, float r, float g, float b, float a, int lifeTime) { int i; vec3_t pushedOrigin, axis[3]; vec4_t color; int fadeTime; vec3_t points[4]; // early out if (lifeTime == 0) { return; } // set projection (inverse of dir) //VectorSubtract( vec3_origin, dir, projection ); //VectorNormalize( projection ); //projection[ 3 ] = radius * 8; // make rotated polygon axis VectorCopy(projection, axis[0]); PerpendicularVector(axis[1], axis[0]); RotatePointAroundVector(axis[2], axis[0], axis[1], -orientation); CrossProduct(axis[0], axis[2], axis[1]); // push the origin out a bit VectorMA(origin, -1.0f, axis[0], pushedOrigin); // create the full polygon for (i = 0; i < 3; i++) { // new points[0][i] = pushedOrigin[i] - radius * axis[1][i] - radius * axis[2][i]; points[1][i] = pushedOrigin[i] - radius * axis[1][i] + radius * axis[2][i]; points[2][i] = pushedOrigin[i] + radius * axis[1][i] + radius * axis[2][i]; points[3][i] = pushedOrigin[i] + radius * axis[1][i] - radius * axis[2][i]; } // debug code #if 0 VectorSet(points[0], origin[0] - radius, origin[1] - radius, origin[2]); VectorSet(points[1], origin[0] - radius, origin[1] + radius, origin[2]); VectorSet(points[2], origin[0] + radius, origin[1] + radius, origin[2]); VectorSet(points[3], origin[0] + radius, origin[1] - radius, origin[2]); CG_Printf("Dir: %f %f %f\n", dir[0], dir[1], dir[2]); #endif // set color color[0] = r; color[1] = g; color[2] = b; color[3] = a; // set decal times (in seconds) fadeTime = lifeTime >> 4; // add the decal trap_R_ProjectDecal(markShader, 4, points, projection, color, lifeTime, fadeTime); }
/** * @brief Get the next point in the object path based on movement converting the positions from * polar coordinates to vector for the calculation and back again to be returned. * @param[in] movement The distance that the object needs to move. * @param[in] originalPoint The point from which the object is moving. * @param[in] orthogonalVector The orthogonal vector. * @param[out] finalPoint The next point from the original point + movement in "angle" direction. */ static void AIRFIGHT_GetNextPointInPathFromVector (const float *movement, const vec2_t originalPoint, const vec3_t orthogonalVector, vec2_t finalPoint) { vec3_t startPoint, finalVectorPoint; PolarToVec(originalPoint, startPoint); RotatePointAroundVector(finalVectorPoint, orthogonalVector, startPoint, *movement); VecToPolar(finalVectorPoint, finalPoint); }
/** * @brief Return longitude and latitude of a point of the screen for 3D geoscape (globe) * @param[in] node The current menuNode we have clicked on (3dmap or map) * @param[in] x,y Coordinates on the screen that were clicked on * @param[out] pos vec2_t was filled with longitude and latitude * @sa MAP_3DMapToScreen */ void uiGeoscapeNode::screenTo3DMap (const uiNode_t* node, int x, int y, vec2_t pos) { vec2_t mid; vec3_t v, v1, rotationAxis; float dist; const float radius = GLOBE_RADIUS; /* set mid to the coordinates of the center of the globe */ Vector2Set(mid, UI_MAPEXTRADATACONST(node).mapPos[0] + UI_MAPEXTRADATACONST(node).mapSize[0] / 2.0f, UI_MAPEXTRADATACONST(node).mapPos[1] + UI_MAPEXTRADATACONST(node).mapSize[1] / 2.0f); /* stop if we click outside the globe (distance is the distance of the point to the center of the globe) */ dist = sqrt((x - mid[0]) * (x - mid[0]) + (y - mid[1]) * (y - mid[1])); if (dist > radius) { Vector2Set(pos, -1.0, -1.0); return; } /* calculate the coordinates in the local frame * this frame is the frame of the screen. * v[0] is the vertical axis of the screen * v[1] is the horizontal axis of the screen * v[2] is the axis perpendicular to the screen - we get its value knowing that norm of v is egal to radius * (because the point is on the globe) */ v[0] = - (y - mid[1]); v[1] = - (x - mid[0]); v[2] = - sqrt(radius * radius - (x - mid[0]) * (x - mid[0]) - (y - mid[1]) * (y - mid[1])); VectorNormalize(v); /* rotate the vector to switch of reference frame * note the ccs.angles[ROLL] is always 0, so there is only 2 rotations and not 3 * and that GLOBE_ROTATE is already included in ccs.angles[YAW] * first rotation is along the horizontal axis of the screen, to put north-south axis of the earth * perpendicular to the screen */ VectorSet(rotationAxis, 0, 1, 0); RotatePointAroundVector(v1, rotationAxis, v, UI_MAPEXTRADATACONST(node).angles[YAW]); /* second rotation is to rotate the earth around its north-south axis * so that Greenwich meridian is along the vertical axis of the screen */ VectorSet(rotationAxis, 0, 0, 1); RotatePointAroundVector(v, rotationAxis, v1, UI_MAPEXTRADATACONST(node).angles[PITCH]); /* we therefore got in v the coordinates of the point in the static frame of the earth * that we can convert in polar coordinates to get its latitude and longitude */ VecToPolar(v, pos); }
/* ============= CG_DrawDir Draw dot marking the direction to an enemy ============= */ static void CG_DrawDir( rectDef_t *rect, vec3_t origin, vec4_t colour ) { vec3_t drawOrigin; vec3_t noZOrigin; vec3_t normal, antinormal, normalDiff; vec3_t view, noZview; vec3_t up = { 0.0f, 0.0f, 1.0f }; vec3_t top = { 0.0f, -1.0f, 0.0f }; float angle; playerState_t *ps = &cg.snap->ps; if ( ps->stats[ STAT_STATE ] & SS_WALLCLIMBING ) { if ( ps->stats[ STAT_STATE ] & SS_WALLCLIMBINGCEILING ) { VectorSet( normal, 0.0f, 0.0f, -1.0f ); } else { VectorCopy( ps->grapplePoint, normal ); } } else { VectorSet( normal, 0.0f, 0.0f, 1.0f ); } AngleVectors( entityPositions.vangles, view, NULL, NULL ); ProjectPointOnPlane( noZOrigin, origin, normal ); ProjectPointOnPlane( noZview, view, normal ); VectorNormalize( noZOrigin ); VectorNormalize( noZview ); //calculate the angle between the images of the blip and the view angle = RAD2DEG( acos( DotProduct( noZOrigin, noZview ) ) ); CrossProduct( noZOrigin, noZview, antinormal ); VectorNormalize( antinormal ); //decide which way to rotate VectorSubtract( normal, antinormal, normalDiff ); if ( VectorLength( normalDiff ) < 1.0f ) { angle = 360.0f - angle; } RotatePointAroundVector( drawOrigin, up, top, angle ); trap_R_SetColor( colour ); CG_DrawPic( rect->x + ( rect->w / 2 ) - ( BLIPX2 / 2 ) - drawOrigin[ 0 ] * ( rect->w / 2 ), rect->y + ( rect->h / 2 ) - ( BLIPY2 / 2 ) + drawOrigin[ 1 ] * ( rect->h / 2 ), BLIPX2, BLIPY2, cgs.media.scannerBlipShader ); trap_R_SetColor( NULL ); }
/* =============== R_SetupFrustum =============== */ void R_SetupFrustum( void ) { vec3_t farPoint; int i; // 0 - left // 1 - right // 2 - down // 3 - up // 4 - farclip // 5 - nearclip if( RI.drawOrtho ) { R_SetupFrustumOrtho(); return; } // rotate RI.vforward right by FOV_X/2 degrees RotatePointAroundVector( RI.frustum[0].normal, RI.cull_vup, RI.cull_vforward, -( 90 - RI.refdef.fov_x / 2 )); // rotate RI.vforward left by FOV_X/2 degrees RotatePointAroundVector( RI.frustum[1].normal, RI.cull_vup, RI.cull_vforward, 90 - RI.refdef.fov_x / 2 ); // rotate RI.vforward up by FOV_X/2 degrees RotatePointAroundVector( RI.frustum[2].normal, RI.cull_vright, RI.cull_vforward, 90 - RI.refdef.fov_y / 2 ); // rotate RI.vforward down by FOV_X/2 degrees RotatePointAroundVector( RI.frustum[3].normal, RI.cull_vright, RI.cull_vforward, -( 90 - RI.refdef.fov_y / 2 )); // negate forward vector VectorNegate( RI.cull_vforward, RI.frustum[4].normal ); for( i = 0; i < 4; i++ ) { RI.frustum[i].type = PLANE_NONAXIAL; RI.frustum[i].dist = DotProduct( RI.cullorigin, RI.frustum[i].normal ); RI.frustum[i].signbits = SignbitsForPlane( RI.frustum[i].normal ); } VectorMA( RI.cullorigin, R_GetFarClip(), RI.cull_vforward, farPoint ); RI.frustum[i].type = PLANE_NONAXIAL; RI.frustum[i].dist = DotProduct( farPoint, RI.frustum[i].normal ); RI.frustum[i].signbits = SignbitsForPlane( RI.frustum[i].normal ); }
static void BestJumpingDirection (gedict_t* self) { float raw_avg_angle = AverageTraceAngle (self, false, self->fb.debug_path); float avg_angle; if (raw_avg_angle < 0) avg_angle = min (raw_avg_angle, -15); else avg_angle = max (raw_avg_angle, 15); RotatePointAroundVector (self->fb.dir_move_, g_globalvars.v_up, g_globalvars.v_forward, avg_angle); }
/* ============= CG_DrawBlips Draw blips and stalks for the human scanner ============= */ static void CG_DrawBlips( rectDef_t *rect, vec3_t origin, vec4_t colour ) { vec3_t drawOrigin; vec3_t up = { 0, 0, 1 }; float alphaMod = 1.0f; float timeFractionSinceRefresh = 1.0f - ( ( float )( cg.time - entityPositions.lastUpdateTime ) / ( float ) HUMAN_SCANNER_UPDATE_PERIOD ); vec4_t localColour; Vector4Copy( colour, localColour ); RotatePointAroundVector( drawOrigin, up, origin, -entityPositions.vangles[ 1 ] - 90 ); drawOrigin[ 0 ] /= ( 2 * HELMET_RANGE / rect->w ); drawOrigin[ 1 ] /= ( 2 * HELMET_RANGE / rect->h ); drawOrigin[ 2 ] /= ( 2 * HELMET_RANGE / rect->w ); alphaMod = FAR_ALPHA + ( ( drawOrigin[ 1 ] + ( rect->h / 2.0f ) ) / rect->h ) * ( NEAR_ALPHA - FAR_ALPHA ); localColour[ 3 ] *= alphaMod; localColour[ 3 ] *= ( 0.5f + ( timeFractionSinceRefresh * 0.5f ) ); if ( localColour[ 3 ] > 1.0f ) { localColour[ 3 ] = 1.0f; } else if ( localColour[ 3 ] < 0.0f ) { localColour[ 3 ] = 0.0f; } trap_R_SetColor( localColour ); if ( drawOrigin[ 2 ] > 0 ) { CG_DrawPic( rect->x + ( rect->w / 2 ) - ( STALKWIDTH / 2 ) - drawOrigin[ 0 ], rect->y + ( rect->h / 2 ) + drawOrigin[ 1 ] - drawOrigin[ 2 ], STALKWIDTH, drawOrigin[ 2 ], cgs.media.scannerLineShader ); } else { CG_DrawPic( rect->x + ( rect->w / 2 ) - ( STALKWIDTH / 2 ) - drawOrigin[ 0 ], rect->y + ( rect->h / 2 ) + drawOrigin[ 1 ], STALKWIDTH, -drawOrigin[ 2 ], cgs.media.scannerLineShader ); } CG_DrawPic( rect->x + ( rect->w / 2 ) - ( BLIPX / 2 ) - drawOrigin[ 0 ], rect->y + ( rect->h / 2 ) - ( BLIPY / 2 ) + drawOrigin[ 1 ] - drawOrigin[ 2 ], BLIPX, BLIPY, cgs.media.scannerBlipShader ); trap_R_SetColor( NULL ); }
/*** Rotates point around a given vector. @function RotatePointAround @param dir Vector to rotate around (must be normalized). @param point Point to be rotated. @param degrees How many degrees to rotate. @param dest Point after rotation. */ static int Vector_RotatePointAround(lua_State *L) { vec_t *dst, *dir, *point; vec_t degrees; dst = Lua_GetVector(L, 1); dir = Lua_GetVector(L, 2); point = Lua_GetVector(L, 3); degrees = luaL_checknumber(L, 4); RotatePointAroundVector(dst, dir, point, degrees); return 0; }
static void ShowStats(edict_t *ent, edict_t *player) { // float dist = 0.0; vec3_t v; int j; char stats[500]; BlinkyClient_t * bdata; char pname[11]; int health, armor, armorpow; int xd,yd,zd; vec3_t dp, normal={0,0,-1}; static int CellsIndex = -1; int index; j = 0; if (-1 == CellsIndex) CellsIndex = ITEM_INDEX(FindItem("cells")); bdata = &ent->client->blinky_client; VectorSubtract(ent->s.origin, player->s.origin, v); zd = -v[2]/SCANNER_UNIT; // save height differential v[2] = 0; // remove height component RotatePointAroundVector(dp, normal, v, ent->s.angles[1]); xd = -dp[0]/SCANNER_UNIT; yd = dp[1]/SCANNER_UNIT; if (player->client) strncpy(pname, player->client->pers.netname, sizeof(pname)-1); else strncpy(pname, player->classname, sizeof(pname)-1); pname[sizeof(pname)-1] = 0; health = player->health; armorpow = 0; if (PowerArmorType(ent)) armorpow = ent->client->pers.inventory[CellsIndex]; index = ArmorIndex (ent); if (index) armor = ent->client->pers.inventory[index]; if (armorpow) sprintf(stats+j, "%s: armor=%3d(%3d), health=%3d (f=%+5d,r=%+5d,u=%+5d)\n" , pname, armor,armorpow,health,xd, yd, zd); else sprintf(stats+j, "%s: armor=%3d, health=%3d (f=%+5d,r=%+5d,u=%+5d)\n" , pname, armor,health,xd, yd, zd); gi.cprintf(ent, PRINT_CHAT, "%s", stats); }
void FrustumCheck::R_SetFrustum (vec3_t vangles, vec3_t vorigin, float view_hor, float view_ver, float dist) { int i; vec3_t vpn, vright, vup; AngleVectors (vangles, vpn, vright, vup); // rotate VPN right by FOV_X/2 degrees RotatePointAroundVector( frustum[0].normal, vup, vpn, -(90-view_hor / 2 ) ); // rotate VPN left by FOV_X/2 degrees RotatePointAroundVector( frustum[1].normal, vup, vpn, 90-view_hor / 2 ); // rotate VPN up by FOV_X/2 degrees RotatePointAroundVector( frustum[2].normal, vright, vpn, 90-(view_ver) / 2 ); // rotate VPN down by FOV_X/2 degrees RotatePointAroundVector( frustum[3].normal, vright, vpn, -( 90 -(view_ver) / 2 ) ); for (i=0 ; i<4 ; i++) { frustum[i].type = PLANE_ANYZ; frustum[i].dist = DotProduct (vorigin, frustum[i].normal); frustum[i].signbits = SignbitsForPlane (&frustum[i]); } // buz: set also clipping by distance vec3_t farpoint = vorigin + (vpn * dist); farclip.normal = vpn * -1; farclip.type = PLANE_ANYZ; farclip.dist = DotProduct (farpoint, farclip.normal); farclip.signbits = SignbitsForPlane (&farclip); farclipset = 1; // save params for building stencil clipping volume VectorCopy(vorigin, m_origin); VectorCopy(vangles, m_angles); m_fov_hor = view_hor; m_fov_ver = view_ver; m_dist = dist; }
void FrustumCheck::R_SetFrustum (vec3_t vangles, vec3_t vorigin, float viewsize) { int i; vec3_t vpn, vright, vup; AngleVectors (vangles, vpn, vright, vup); if (viewsize == 90) { // front side is visible VectorAdd (vpn, vright, frustum[0].normal); VectorSubtract (vpn, vright, frustum[1].normal); VectorAdd (vpn, vup, frustum[2].normal); VectorSubtract (vpn, vup, frustum[3].normal); } else { // rotate VPN right by FOV_X/2 degrees RotatePointAroundVector( frustum[0].normal, vup, vpn, -(90-viewsize / 2 ) ); // rotate VPN left by FOV_X/2 degrees RotatePointAroundVector( frustum[1].normal, vup, vpn, 90-viewsize / 2 ); // rotate VPN up by FOV_X/2 degrees RotatePointAroundVector( frustum[2].normal, vright, vpn, 90-(viewsize*0.75) / 2 ); // rotate VPN down by FOV_X/2 degrees RotatePointAroundVector( frustum[3].normal, vright, vpn, -( 90 -(viewsize*0.75) / 2 ) ); } for (i=0 ; i<4 ; i++) { frustum[i].type = PLANE_ANYZ; frustum[i].dist = DotProduct (vorigin, frustum[i].normal); frustum[i].signbits = SignbitsForPlane (&frustum[i]); } farclipset = 0; // buz }
void R_SetFrustum (void) { int i; // rotate VPN right by FOV_X/2 degrees RotatePointAroundVector (frustum[0].normal, vup, vpn, -(90 - r_refdef.fov_x / 2)); // rotate VPN left by FOV_X/2 degrees RotatePointAroundVector (frustum[1].normal, vup, vpn, 90 - r_refdef.fov_x / 2); // rotate VPN up by FOV_Y/2 degrees RotatePointAroundVector (frustum[2].normal, vright, vpn, 90 - r_refdef.fov_y / 2); // rotate VPN down by FOV_Y/2 degrees RotatePointAroundVector (frustum[3].normal, vright, vpn, -(90 - r_refdef.fov_y / 2)); for (i = 0; i < 4; i++) { frustum[i].type = PLANE_ANYZ; frustum[i].dist = DotProduct (r_origin, frustum[i].normal); frustum[i].signbits = SignbitsForPlane (&frustum[i]); } }
static void BotMoveTowardsLinkedMarker(gedict_t* self, vec3_t dir_move) { vec3_t temp; gedict_t* goalentity_ = &g_edicts[self->s.v.goalentity]; gedict_t* linked = self->fb.linked_marker; qbool onGround = ((int)self->s.v.flags & FL_ONGROUND); qbool curlJump = ((int)self->fb.path_state & BOTPATH_CURLJUMP_HINT); VectorAdd(linked->s.v.absmin, linked->s.v.view_ofs, temp); VectorSubtract(temp, self->s.v.origin, temp); normalize(temp, dir_move); if (curlJump && (onGround || self->s.v.velocity[2] > 0)) { vec3_t up = { 0, 0, 1 }; if (self->isBot && self->fb.debug_path) { G_bprint (PRINT_HIGH, "%3.2f: Moving %3d > %3d, dir %3.1f %3.1f %3.1f\n", g_globalvars.time, self->fb.touch_marker->fb.index + 1, self->fb.linked_marker->fb.index + 1, PASSVEC3 (dir_move)); } RotatePointAroundVector (dir_move, up, dir_move, self->fb.angle_hint); if (self->isBot && self->fb.debug_path) { G_bprint (PRINT_HIGH, "%3.2f: Rotating %d, %3.1f %3.1f %3.1f\n", g_globalvars.time, self->fb.angle_hint, PASSVEC3 (dir_move)); } } if (self->isBot && self->fb.debug_path) { //G_bprint (PRINT_HIGH, "%3.2f: Moving %3d > %3d, dir %3.1f %3.1f %3.1f\n", g_globalvars.time, self->fb.touch_marker->fb.index + 1, self->fb.linked_marker->fb.index + 1, PASSVEC3 (dir_move)); } if (self->fb.path_state & DELIBERATE_BACKUP) { if (linked->fb.arrow_time > g_globalvars.time) { VectorInverse (dir_move); } else { self->fb.path_state &= ~DELIBERATE_BACKUP; } } else if (linked == self->fb.touch_marker) { if (goalentity_ == self->fb.touch_marker) { if (WaitingToRespawn(self->fb.touch_marker)) { VectorClear(dir_move); } } else { VectorClear(dir_move); } } }
static int vector_RotatePointAround(lua_State * L) { vec_t *dst; vec_t *dir; vec_t *point; vec_t degrees; dst = lua_getvector(L, 1); dir = lua_getvector(L, 2); point = lua_getvector(L, 3); degrees = luaL_checknumber(L, 4); RotatePointAroundVector(dst, dir, point, degrees); return 1; }
void RotateAroundDirection( vector3 axis[3], float yaw ) { // create an arbitrary axis[1] PerpendicularVector( &axis[1], &axis[0] ); // rotate it around axis[0] by yaw if ( yaw ) { vector3 temp; VectorCopy( &axis[1], &temp ); RotatePointAroundVector( &axis[1], &axis[0], &temp, yaw ); } // cross to get axis[2] CrossProduct( &axis[0], &axis[1], &axis[2] ); }
static void Tess_SurfaceSprite() { vec3_t delta, left, up; float radius; vec4_t color; GLimp_LogComment( "--- Tess_SurfaceSprite ---\n" ); radius = backEnd.currentEntity->e.radius; if( tess.surfaceShader->autoSpriteMode == 1 ) { // the calculations are done in GLSL shader Tess_AddSprite( backEnd.currentEntity->e.origin, backEnd.currentEntity->e.shaderRGBA, radius, backEnd.currentEntity->e.rotation ); return; } VectorSubtract( backEnd.currentEntity->e.origin, backEnd.viewParms.pvsOrigin, delta ); if( VectorNormalize( delta ) < NORMAL_EPSILON ) return; CrossProduct( backEnd.viewParms.orientation.axis[ 2 ], delta, left ); if( VectorNormalize( left ) < NORMAL_EPSILON ) VectorSet( left, 1, 0, 0 ); if( backEnd.currentEntity->e.rotation != 0 ) RotatePointAroundVector( left, delta, left, backEnd.currentEntity->e.rotation ); CrossProduct( delta, left, up ); VectorScale( left, radius, left ); VectorScale( up, radius, up ); if ( backEnd.viewParms.isMirror ) VectorSubtract( vec3_origin, left, left ); color[ 0 ] = backEnd.currentEntity->e.shaderRGBA[ 0 ] * ( 1.0 / 255.0 ); color[ 1 ] = backEnd.currentEntity->e.shaderRGBA[ 1 ] * ( 1.0 / 255.0 ); color[ 2 ] = backEnd.currentEntity->e.shaderRGBA[ 2 ] * ( 1.0 / 255.0 ); color[ 3 ] = backEnd.currentEntity->e.shaderRGBA[ 3 ] * ( 1.0 / 255.0 ); Tess_AddQuadStamp( backEnd.currentEntity->e.origin, left, up, color ); }
void hover_dodge (edict_t *self, edict_t *attacker, float eta) /* FS: Zaero specific game dll changes */ { int delta = 0; vec3_t forward, right; vec3_t dir; int count = 0; if (self->monsterinfo.currentmove == &hover_move_attack1) if (random() < 0.75) // if we're attacking, stop attacking and dodge 1/4 the time return; self->monsterinfo.attack_state = AS_FLY_STRAFE; // TODO choose an angle to move based on what's around me // start at a random value self->monsterinfo.flyStrafePitch = crandom() * 180; // choose a random delta dir delta = (random() < 0.5 ? 10 : -10); AngleVectors(self->s.angles, forward, right, NULL); // now try to find a direction that'll give us sufficient room to move // (ie. away from walls) count = 36; while(1) { trace_t tr; vec3_t end; RotatePointAroundVector(dir, forward, right, self->monsterinfo.flyStrafePitch); VectorMA(self->s.origin, 96, dir, end); // trace out in this direction tr = gi.trace(self->s.origin, self->mins, self->maxs, end, self, MASK_MONSTERSOLID); if (tr.fraction >= 1.0) break; if (count-- <= 0) break; // we've tried enough times; self->monsterinfo.flyStrafePitch += delta; } self->monsterinfo.flyStrafeTimeout = level.time + /*eta + */ 1.0; //if (random() < 0.5) // self->monsterinfo.currentmove = &hover_move_run; }
static void RocketThink( gentity_t *self ) { vec3_t currentDir, targetDir, newDir, rotAxis; float rotAngle; if ( level.time > self->timestamp ) { self->think = G_ExplodeMissile; self->nextthink = level.time; return; } self->nextthink = level.time + ROCKET_TURN_PERIOD; // Calculate current and target direction. VectorNormalize2( self->s.pos.trDelta, currentDir ); VectorSubtract( self->target->r.currentOrigin, self->r.currentOrigin, targetDir ); VectorNormalize( targetDir ); // Don't turn anymore after the target was passed. if ( DotProduct( currentDir, targetDir ) < 0 ) { return; } // Calculate new direction. Use a fixed turning angle. CrossProduct( currentDir, targetDir, rotAxis ); rotAngle = RAD2DEG( acos( DotProduct( currentDir, targetDir ) ) ); RotatePointAroundVector( newDir, rotAxis, currentDir, Math::Clamp( rotAngle, -ROCKET_TURN_ANGLE, ROCKET_TURN_ANGLE ) ); // Check if new direction is safe. Turn anyway if old direction is unsafe, too. if ( !G_RocketpodSafeShot( ENTITYNUM_NONE, self->r.currentOrigin, newDir ) && G_RocketpodSafeShot( ENTITYNUM_NONE, self->r.currentOrigin, currentDir ) ) { return; } // Update trajectory. VectorScale( newDir, BG_Missile( self->s.modelindex )->speed, self->s.pos.trDelta ); SnapVector( self->s.pos.trDelta ); VectorCopy( self->r.currentOrigin, self->s.pos.trBase ); // TODO: Snap this, too? self->s.pos.trTime = level.time; }
void CTerrainMap::AddPlayer(vec3_t origin, vec3_t angles) { // draw player start on automap CDraw32 draw; vec3_t up; vec3_t pt[4] = {{0,0,0},{-5,-5,0},{10,0,0},{-5,5,0}}; vec3_t p; int x,y,i; float facing; POINT poly[4]; facing = angles[1]; up[0] = 0; up[1] = 0; up[2] = 1; x = (int)origin[0]; y = (int)origin[1]; ConvertPos(x, y); x++; y++; for (i=0; i<4; i++) { RotatePointAroundVector( p, up, pt[i], facing ); poly[i].x = (int)(-p[0] + x); poly[i].y = (int)(p[1] + y); } // draw arrowhead shadow draw.DrawPolygon(4, poly, CPixel32(0,0,0,128), CPixel32(0,0,0,128)); // draw arrowhead for (i=0; i<4; i++) { poly[i].x--; poly[i].y--; } draw.DrawPolygon(4, poly, CPixel32(255,255,255), CPixel32(255,255,255)); }
/* ============== CG_SurfaceLightningBolt ============== */ void CG_SurfaceLightningBolt( const refEntity_t *originEnt ) { int len; vec3_t forward = { 1, 0, 0 }; vec3_t right = { 0, 0, 1 }; vec3_t vec; vec3_t start, end; int i; #define NUM_BOLT_POLYS 4 polyVert_t verts[NUM_BOLT_POLYS*4]; refEntity_t re; re = *originEnt; re.reType = RT_POLY_LOCAL; re.renderfx |= RF_AUTOAXIS2; VectorCopy( re.oldorigin, end ); VectorCopy( re.origin, start ); // compute variables VectorSubtract( end, start, vec ); len = VectorNormalize( vec ); // setup start and end in local space VectorMA( vec3_origin, -len/2.0f, forward, start ); VectorMA( start, len, forward, end ); for ( i = 0 ; i < NUM_BOLT_POLYS ; i++ ) { vec3_t temp; CG_DoRailCore( &verts[i*4], re.shaderRGBA, start, end, right, len, 8 ); RotatePointAroundVector( temp, vec, right, 180.0f / NUM_BOLT_POLYS ); VectorCopy( temp, right ); } trap_R_AddPolyRefEntityToScene( &re, 4, verts, NUM_BOLT_POLYS ); }
/* =============== CG_smoothWWTransitions =============== */ static void CG_smoothWWTransitions( playerState_t *ps, const vec3_t in, vec3_t out ) { vec3_t surfNormal, rotAxis, temp; vec3_t refNormal = { 0.0f, 0.0f, 1.0f }; vec3_t ceilingNormal = { 0.0f, 0.0f, -1.0f }; int i; float stLocal, sFraction, rotAngle; float smoothTime, timeMod; qboolean performed = qfalse; vec3_t inAxis[ 3 ], lastAxis[ 3 ], outAxis[ 3 ]; if( cg.snap->ps.pm_flags & PMF_FOLLOW ) { VectorCopy( in, out ); return; } //set surfNormal BG_GetClientNormal( ps, surfNormal ); AnglesToAxis( in, inAxis ); //if we are moving from one surface to another smooth the transition if( !VectorCompare( surfNormal, cg.lastNormal ) ) { //if we moving from the ceiling to the floor special case //( x product of colinear vectors is undefined) if( VectorCompare( ceilingNormal, cg.lastNormal ) && VectorCompare( refNormal, surfNormal ) ) { AngleVectors( in, temp, NULL, NULL ); ProjectPointOnPlane( rotAxis, temp, refNormal ); VectorNormalize( rotAxis ); rotAngle = 180.0f; timeMod = 1.5f; } else { AnglesToAxis( cg.lastVangles, lastAxis ); rotAngle = DotProduct( inAxis[ 0 ], lastAxis[ 0 ] ) + DotProduct( inAxis[ 1 ], lastAxis[ 1 ] ) + DotProduct( inAxis[ 2 ], lastAxis[ 2 ] ); rotAngle = RAD2DEG( acos( ( rotAngle - 1.0f ) / 2.0f ) ); CrossProduct( lastAxis[ 0 ], inAxis[ 0 ], temp ); VectorCopy( temp, rotAxis ); CrossProduct( lastAxis[ 1 ], inAxis[ 1 ], temp ); VectorAdd( rotAxis, temp, rotAxis ); CrossProduct( lastAxis[ 2 ], inAxis[ 2 ], temp ); VectorAdd( rotAxis, temp, rotAxis ); VectorNormalize( rotAxis ); timeMod = 1.0f; } //add the op CG_addSmoothOp( rotAxis, rotAngle, timeMod ); } //iterate through ops for( i = MAXSMOOTHS - 1; i >= 0; i-- ) { smoothTime = (int)( cg_wwSmoothTime.integer * cg.sList[ i ].timeMod ); //if this op has time remaining, perform it if( cg.time < cg.sList[ i ].time + smoothTime ) { stLocal = 1.0f - ( ( ( cg.sList[ i ].time + smoothTime ) - cg.time ) / smoothTime ); sFraction = -( cos( stLocal * M_PI ) + 1.0f ) / 2.0f; RotatePointAroundVector( outAxis[ 0 ], cg.sList[ i ].rotAxis, inAxis[ 0 ], sFraction * cg.sList[ i ].rotAngle ); RotatePointAroundVector( outAxis[ 1 ], cg.sList[ i ].rotAxis, inAxis[ 1 ], sFraction * cg.sList[ i ].rotAngle ); RotatePointAroundVector( outAxis[ 2 ], cg.sList[ i ].rotAxis, inAxis[ 2 ], sFraction * cg.sList[ i ].rotAngle ); AxisCopy( outAxis, inAxis ); performed = qtrue; } } //if we performed any ops then return the smoothed angles //otherwise simply return the in angles if( performed ) AxisToAngles( outAxis, out ); else VectorCopy( in, out ); //copy the current normal to the lastNormal VectorCopy( in, cg.lastVangles ); VectorCopy( surfNormal, cg.lastNormal ); }