/* ============= 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 ); }
/* =============== CG_PositionAndOrientateBuildable =============== */ static void CG_PositionAndOrientateBuildable( const vec3_t angles, const vec3_t inOrigin, const vec3_t normal, const int skipNumber, const vec3_t mins, const vec3_t maxs, vec3_t outAxis[ 3 ], vec3_t outOrigin ) { vec3_t forward, start, end; trace_t tr, box_tr; float mag, fraction; AngleVectors( angles, forward, NULL, NULL ); VectorCopy( normal, outAxis[ 2 ] ); ProjectPointOnPlane( outAxis[ 0 ], forward, outAxis[ 2 ] ); if( !VectorNormalize( outAxis[ 0 ] ) ) { AngleVectors( angles, NULL, NULL, forward ); ProjectPointOnPlane( outAxis[ 0 ], forward, outAxis[ 2 ] ); VectorNormalize( outAxis[ 0 ] ); } CrossProduct( outAxis[ 0 ], outAxis[ 2 ], outAxis[ 1 ] ); outAxis[ 1 ][ 0 ] = -outAxis[ 1 ][ 0 ]; outAxis[ 1 ][ 1 ] = -outAxis[ 1 ][ 1 ]; outAxis[ 1 ][ 2 ] = -outAxis[ 1 ][ 2 ]; VectorMA( inOrigin, -TRACE_DEPTH, normal, end ); VectorMA( inOrigin, 1.0f, normal, start ); // Take both capsule and box traces. If the capsule trace does not differ // significantly from the box trace use it. This may cause buildables to be // positioned *inside* the surface on which it is placed. This is intentional CG_CapTrace( &tr, start, mins, maxs, end, skipNumber, MASK_PLAYERSOLID ); CG_Trace( &box_tr, start, mins, maxs, end, skipNumber, MASK_PLAYERSOLID ); mag = Distance( tr.endpos, box_tr.endpos ); fraction = tr.fraction; // this is either too far off of the bbox to be useful for gameplay purposes // or the model is positioned in thin air anyways. if( mag > 15.0f || tr.fraction == 1.0f ) fraction = box_tr.fraction; VectorMA( inOrigin, fraction * -TRACE_DEPTH, normal, outOrigin ); }
/* ** assumes "src" is normalized */ void PerpendicularVector( vec3_t dst, const vec3_t src ) { int pos; int i; float minelem = 1.0F; vec3_t tempvec; /* ** find the smallest magnitude axially aligned vector */ for ( pos = 0, i = 0; i < 3; i++ ) { if ( fabs( src[i] ) < minelem ) { pos = i; minelem = fabs( src[i] ); } } tempvec[0] = tempvec[1] = tempvec[2] = 0.0F; tempvec[pos] = 1.0F; /* ** project the point onto the plane defined by src */ ProjectPointOnPlane( dst, tempvec, src ); /* ** normalize the result */ VectorNormalize( dst ); }
void PerpendicularVector( Coord *dst, Coord src ) { int pos; float minelem = 1.0F; Coord tempvec; /* ** find the smallest magnitude axially aligned vector */ pos=0; if ( fabs( src.x ) < minelem ) { pos=0; minelem = fabs( src.x ); } if ( fabs( src.y ) < minelem ) { pos=1; minelem = fabs( src.y ); } if ( fabs( src.y ) < minelem ) { pos=2; minelem = fabs( src.z ); } tempvec.x=0; tempvec.y=0; tempvec.z=0; switch(pos) { case 0: tempvec.x=1; break; case 1: tempvec.y=1; break; case 2: tempvec.z=1; break; } /* ** project the point onto the plane defined by src */ ProjectPointOnPlane( dst, tempvec, src ); /* ** normalize the result */ VectorNormalize( dst ); }
/* =============== CG_PositionAndOrientateBuildable =============== */ static void CG_PositionAndOrientateBuildable( const vec3_t angles, const vec3_t inOrigin, const vec3_t normal, const int skipNumber, const vec3_t mins, const vec3_t maxs, vec3_t outAxis[ 3 ], vec3_t outOrigin ) { vec3_t forward, start, end; trace_t tr; AngleVectors( angles, forward, NULL, NULL ); VectorCopy( normal, outAxis[ 2 ] ); ProjectPointOnPlane( outAxis[ 0 ], forward, outAxis[ 2 ] ); if( !VectorNormalize( outAxis[ 0 ] ) ) { AngleVectors( angles, NULL, NULL, forward ); ProjectPointOnPlane( outAxis[ 0 ], forward, outAxis[ 2 ] ); VectorNormalize( outAxis[ 0 ] ); } CrossProduct( outAxis[ 0 ], outAxis[ 2 ], outAxis[ 1 ] ); outAxis[ 1 ][ 0 ] = -outAxis[ 1 ][ 0 ]; outAxis[ 1 ][ 1 ] = -outAxis[ 1 ][ 1 ]; outAxis[ 1 ][ 2 ] = -outAxis[ 1 ][ 2 ]; VectorMA( inOrigin, -TRACE_DEPTH, normal, end ); VectorMA( inOrigin, 1.0f, normal, start ); CG_CapTrace( &tr, start, mins, maxs, end, skipNumber, CONTENTS_SOLID | CONTENTS_PLAYERCLIP ); if( tr.fraction == 1.0f ) { //erm we missed completely - try again with a box trace CG_Trace( &tr, start, mins, maxs, end, skipNumber, CONTENTS_SOLID | CONTENTS_PLAYERCLIP ); } VectorMA( inOrigin, tr.fraction * -TRACE_DEPTH, normal, outOrigin ); }
int qlua_ProjectToPlane(lua_State *L) { vec3_t dst,src,plane; luaL_checktype(L,1,LUA_TVECTOR); luaL_checktype(L,2,LUA_TVECTOR); luaL_checktype(L,3,LUA_TVECTOR); lua_tovector(L,1,src); lua_tovector(L,2,plane); lua_tovector(L,3,dst); ProjectPointOnPlane(dst,src,plane); lua_pushvector(L,dst); return 1; }
/** * @brief Assumes input vector is normalized. */ void PerpendicularVector(const vec3_t in, vec3_t out) { int32_t pos = 0; vec_t min_elem = 1.0; vec3_t tmp; // find the smallest magnitude axially aligned vector for (int32_t i = 0; i < 3; i++) { if (fabsf(in[i]) < min_elem) { pos = i; min_elem = fabsf(in[i]); } } VectorClear(tmp); tmp[pos] = 1.0; // project the point onto the plane ProjectPointOnPlane(tmp, in, out); // normalize the result VectorNormalize(out); }
/* =============== 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 ); }