/* * CG_Event_Jump */ void CG_Event_Jump( entity_state_t *state, int parm ) { #define MOVEDIREPSILON 0.25f centity_t *cent; int xyspeedcheck; cent = &cg_entities[state->number]; xyspeedcheck = SQRTFAST( cent->animVelocity[0]*cent->animVelocity[0] + cent->animVelocity[1]*cent->animVelocity[1] ); if( xyspeedcheck < 100 ) { // the player is jumping on the same place, not running CG_PModel_AddAnimation( state->number, LEGS_JUMP_NEUTRAL, 0, 0, EVENT_CHANNEL ); CG_SexedSound( state->number, CHAN_BODY, va( S_PLAYER_JUMP_1_to_2, ( rand()&1 )+1 ), cg_volume_players->value ); } else { vec3_t movedir, viewaxis[3]; movedir[0] = cent->animVelocity[0]; movedir[1] = cent->animVelocity[1]; movedir[2] = 0; VectorNormalizeFast( movedir ); AngleVectors( tv( 0, cent->current.angles[YAW], 0 ), viewaxis[FORWARD], viewaxis[RIGHT], viewaxis[UP] ); // see what's his relative movement direction if( DotProduct( movedir, viewaxis[FORWARD] ) > MOVEDIREPSILON ) { cent->jumpedLeft = !cent->jumpedLeft; if( !cent->jumpedLeft ) { CG_PModel_AddAnimation( state->number, LEGS_JUMP_LEG2, 0, 0, EVENT_CHANNEL ); CG_SexedSound( state->number, CHAN_BODY, va( S_PLAYER_JUMP_1_to_2, ( rand()&1 )+1 ), cg_volume_players->value ); } else { CG_PModel_AddAnimation( state->number, LEGS_JUMP_LEG1, 0, 0, EVENT_CHANNEL ); CG_SexedSound( state->number, CHAN_BODY, va( S_PLAYER_JUMP_1_to_2, ( rand()&1 )+1 ), cg_volume_players->value ); } } else { CG_PModel_AddAnimation( state->number, LEGS_JUMP_NEUTRAL, 0, 0, EVENT_CHANNEL ); CG_SexedSound( state->number, CHAN_BODY, va( S_PLAYER_JUMP_1_to_2, ( rand()&1 )+1 ), cg_volume_players->value ); } } #undef MOVEDIREPSILON //racesow - lm: filter out other players if( ISVIEWERENTITY( state->number )) CG_AddJumpspeed(); //!racesow }
/* ================= CL_MouseMove ================= */ void CL_MouseMove( usercmd_t *cmd ) { float mx, my; float accelSensitivity; float rate; const float speed = static_cast<float>(frame_msec); const float pitch = cl_bUseFighterPitch?m_pitchVeh->value:m_pitch->value; // allow mouse smoothing if ( m_filter->integer ) { mx = ( cl.mouseDx[0] + cl.mouseDx[1] ) * 0.5; my = ( cl.mouseDy[0] + cl.mouseDy[1] ) * 0.5; } else { mx = cl.mouseDx[cl.mouseIndex]; my = cl.mouseDy[cl.mouseIndex]; } cl.mouseIndex ^= 1; cl.mouseDx[cl.mouseIndex] = 0; cl.mouseDy[cl.mouseIndex] = 0; rate = SQRTFAST( mx * mx + my * my ) / speed; if ( cl_mYawOverride || cl_mPitchOverride ) {//FIXME: different people have different speed mouses, if ( cl_mSensitivityOverride ) { //this will f**k things up for them, need to clamp //max input? accelSensitivity = cl_mSensitivityOverride; } else { accelSensitivity = cl_sensitivity->value + rate * cl_mouseAccel->value; // scale by FOV accelSensitivity *= cl.cgameSensitivity; } } else { accelSensitivity = cl_sensitivity->value + rate * cl_mouseAccel->value; // scale by FOV accelSensitivity *= cl.cgameSensitivity; } if ( rate && cl_showMouseRate->integer ) { Com_Printf( "%f : %f\n", rate, accelSensitivity ); } mx *= accelSensitivity; my *= accelSensitivity; if (!mx && !my) { return; } // add mouse X/Y movement to cmd if ( in_strafe.active ) { cmd->rightmove = ClampChar( cmd->rightmove + m_side->value * mx ); } else { if ( cl_mYawOverride ) { cl.viewangles[YAW] -= cl_mYawOverride * mx; } else { cl.viewangles[YAW] -= m_yaw->value * mx; } } if ( (in_mlooking || cl_freelook->integer) && !in_strafe.active ) { // VVFIXME - This is supposed to be a CVAR const float cl_pitchSensitivity = 1.0f; if ( cl_mPitchOverride ) { if ( pitch > 0 ) { cl.viewangles[PITCH] += cl_mPitchOverride * my * cl_pitchSensitivity; } else { cl.viewangles[PITCH] -= cl_mPitchOverride * my * cl_pitchSensitivity; } } else { cl.viewangles[PITCH] += pitch * my * cl_pitchSensitivity; } } else { cmd->forwardmove = ClampChar( cmd->forwardmove - m_forward->value * my ); } }
static void SV_ClipMoveToEntities(trace_t &trace, const CVec3 &start, const CVec3 &end, const CBox &bounds, edict_t *passedict, int contentmask) { guard(SV_ClipMoveToEntities); if (trace.allsolid) return; int i; CVec3 amins, amaxs; for (i = 0; i < 3; i++) { if (start[i] < end[i]) { amins[i] = bounds.mins[i] + start[i]; amaxs[i] = bounds.maxs[i] + end[i]; } else { amins[i] = bounds.mins[i] + end[i]; amaxs[i] = bounds.maxs[i] + start[i]; } } edict_t *list[MAX_EDICTS]; int num = SV_AreaEdicts(amins, amaxs, ARRAY_ARG(list), AREA_SOLID); if (!num) return; float b1 = dot(bounds.mins, bounds.mins); float b2 = dot(bounds.maxs, bounds.maxs); float t = max(b1, b2); float traceWidth = SQRTFAST(t); CVec3 traceDir; VectorSubtract(end, start, traceDir); float traceLen = traceDir.Normalize() + traceWidth; for (i = 0; i < num; i++) { edict_t *edict = list[i]; entityHull_t &ent = ents[NUM_FOR_EDICT(edict)]; // if (!ent->linked) continue; if (edict->solid == SOLID_NOT || edict == passedict) continue; if (passedict) { if (edict->owner == passedict) continue; // don't clip against own missiles if (passedict->owner == edict) continue; // don't clip against owner } if (!(contentmask & CONTENTS_DEADMONSTER) && (edict->svflags & SVF_DEADMONSTER)) continue; CVec3 eCenter; VectorSubtract(ent.center, start, eCenter); // check position of point projection on line float entPos = dot(eCenter, traceDir); if (entPos < -traceWidth - ent.radius || entPos > traceLen + ent.radius) continue; // too near / too far // check distance between point and line CVec3 tmp; VectorMA(eCenter, -entPos, traceDir, tmp); float dist2 = dot(tmp, tmp); float dist0 = ent.radius + traceWidth; if (dist2 >= dist0 * dist0) continue; trace_t tr; if (ent.model) CM_TransformedBoxTrace(tr, start, end, bounds, ent.model->headnode, contentmask, edict->s.origin, ent.axis); else CM_TransformedBoxTrace(tr, start, end, bounds, CM_HeadnodeForBox(ent.bounds), contentmask, edict->s.origin, nullVec3); if (CM_CombineTrace(trace, tr)) trace.ent = edict; if (trace.allsolid) return; } unguard; }
void CL_MouseMove( usercmd_t *cmd ) { float mx, my; float accelSensitivity; float rate; const float speed = static_cast<float>(frame_msec); const float pitch = m_pitch->value; #ifdef _XBOX const float mouseSpeedX = 0.06f; const float mouseSpeedY = 0.05f; // allow mouse smoothing if ( m_filter->integer ) { mx = ( cl.mouseDx[0] + cl.mouseDx[1] ) * 0.5f * frame_msec * mouseSpeedX; my = ( cl.mouseDy[0] + cl.mouseDy[1] ) * 0.5f * frame_msec * mouseSpeedY; } else { int ax = cl.mouseDx[cl.mouseIndex]; int ay = cl.mouseDy[cl.mouseIndex]; CL_MouseClamp(&ax, &ay); mx = ax * speed * mouseSpeedX; my = ay * speed * mouseSpeedY; } extern short cg_crossHairStatus; const float m_hoverSensitivity = 0.4f; if (cg_crossHairStatus == 1) { mx *= m_hoverSensitivity; my *= m_hoverSensitivity; } #else // allow mouse smoothing if ( m_filter->integer ) { mx = ( cl.mouseDx[0] + cl.mouseDx[1] ) * 0.5; my = ( cl.mouseDy[0] + cl.mouseDy[1] ) * 0.5; } else { mx = cl.mouseDx[cl.mouseIndex]; my = cl.mouseDy[cl.mouseIndex]; } #endif cl.mouseIndex ^= 1; cl.mouseDx[cl.mouseIndex] = 0; cl.mouseDy[cl.mouseIndex] = 0; rate = SQRTFAST( mx * mx + my * my ) / speed; accelSensitivity = cl_sensitivity->value + rate * cl_mouseAccel->value; // scale by FOV accelSensitivity *= cl.cgameSensitivity; if ( rate && cl_showMouseRate->integer ) { Com_Printf( "%f : %f\n", rate, accelSensitivity ); } mx *= accelSensitivity; my *= accelSensitivity; if (!mx && !my) { #ifdef _XBOX // If there was a movement but no change in angles then start auto-leveling the camera extern int g_lastFireTime; float autolevelSpeed = 0.03f; if (cg_crossHairStatus != 1 && // Not looking at an enemy cl.joystickAxis[AXIS_FORWARD] && // Moving forward/backward cl.frame.ps.groundEntityNum != ENTITYNUM_NONE && // Not in the air Cvar_VariableIntegerValue("cl_autolevel") && // Autolevel is turned on g_lastFireTime < Sys_Milliseconds() - 1000) // Haven't fired recently { float normAngle = -SHORT2ANGLE(cl.frame.ps.delta_angles[PITCH]); // The adjustment to normAngle below is meant to add or remove some multiple // of 360, so that normAngle is within 180 of viewangles[PITCH]. It should // be correct. int diff = (int)(cl.viewangles[PITCH] - normAngle); if (diff > 180) normAngle += 360.0f * ((diff+180) / 360); else if (diff < -180) normAngle -= 360.0f * ((-diff+180) / 360); if (Cvar_VariableIntegerValue("cg_thirdperson") == 1) { // normAngle += 10; // Removed by BTO, 2003/05/14, I hate it autolevelSpeed *= 1.5f; } if (cl.viewangles[PITCH] > normAngle) { cl.viewangles[PITCH] -= autolevelSpeed * speed; if (cl.viewangles[PITCH] < normAngle) cl.viewangles[PITCH] = normAngle; } else if (cl.viewangles[PITCH] < normAngle) { cl.viewangles[PITCH] += autolevelSpeed * speed; if (cl.viewangles[PITCH] > normAngle) cl.viewangles[PITCH] = normAngle; } } #endif return; } // add mouse X/Y movement to cmd if ( in_strafe.active ) { cmd->rightmove = ClampChar( cmd->rightmove + m_side->value * mx ); } else { if ( cl_mYawOverride ) { cl.viewangles[YAW] -= cl_mYawOverride * mx; } else { cl.viewangles[YAW] -= m_yaw->value * mx; } } if ( (in_mlooking || cl_freelook->integer) && !in_strafe.active ) { // VVFIXME - This is supposed to be a CVAR #ifdef _XBOX const float cl_pitchSensitivity = 0.5f; #else const float cl_pitchSensitivity = 1.0f; #endif if ( cl_mPitchOverride ) { if ( pitch > 0 ) { cl.viewangles[PITCH] += cl_mPitchOverride * my * cl_pitchSensitivity; } else { cl.viewangles[PITCH] -= cl_mPitchOverride * my * cl_pitchSensitivity; } } else { cl.viewangles[PITCH] += pitch * my * cl_pitchSensitivity; } } else { cmd->forwardmove = ClampChar( cmd->forwardmove - m_forward->value * my ); } }
static void CG_DrawGrid(float x, float y, float w, float h, mapScissor_t *scissor) { vec2_t step; vec2_t dim_x, dim_y; vec4_t line; float xscale, yscale; float grid_x, grid_y; vec2_t dist; vec4_t gridColour; dist[0] = cg.mapcoordsMaxs[0] - cg.mapcoordsMins[0]; dist[1] = cg.mapcoordsMaxs[1] - cg.mapcoordsMins[1]; if (!gridInitDone) { gridStep[0] = 1200.f; gridStep[1] = 1200.f; // ensure minimal grid density while ((cg.mapcoordsMaxs[0] - cg.mapcoordsMins[0]) / gridStep[0] < 7) { gridStep[0] -= 50.f; } while ((cg.mapcoordsMins[1] - cg.mapcoordsMaxs[1]) / gridStep[1] < 7) { gridStep[1] -= 50.f; } gridStartCoord[0] = .5f * ((((cg.mapcoordsMaxs[0] - cg.mapcoordsMins[0]) / gridStep[0]) - ((int)((cg.mapcoordsMaxs[0] - cg.mapcoordsMins[0]) / gridStep[0]))) * gridStep[0]); gridStartCoord[1] = .5f * ((((cg.mapcoordsMins[1] - cg.mapcoordsMaxs[1]) / gridStep[1]) - ((int)((cg.mapcoordsMins[1] - cg.mapcoordsMaxs[1]) / gridStep[1]))) * gridStep[1]); gridInitDone = qtrue; } if (scissor) { dim_x[0] = cg.mapcoordsMins[0]; dim_x[1] = cg.mapcoordsMaxs[0]; dim_y[0] = cg.mapcoordsMaxs[1]; dim_y[1] = cg.mapcoordsMins[1]; // transform xscale = (w * scissor->zoomFactor) / dist[0]; yscale = (h * scissor->zoomFactor) / -dist[1]; dim_x[0] = (dim_x[0] - cg.mapcoordsMins[0]) * xscale; dim_x[1] = (dim_x[1] - cg.mapcoordsMins[0]) * xscale; dim_y[0] = (dim_y[0] - cg.mapcoordsMaxs[1]) * yscale; dim_y[1] = (dim_y[1] - cg.mapcoordsMaxs[1]) * yscale; grid_x = ((gridStartCoord[0] / dist[0]) * w * scissor->zoomFactor) - scissor->tl[0]; grid_y = ((-gridStartCoord[1] / dist[1]) * h * scissor->zoomFactor) - scissor->tl[1]; step[0] = gridStep[0] * xscale; step[1] = gridStep[1] * yscale; // draw Vector4Set(gridColour, clrBrownLine[0], clrBrownLine[1], clrBrownLine[2], .4f); trap_R_SetColor(gridColour); for ( ; grid_x < dim_x[1]; grid_x += step[0]) { if (grid_x < dim_x[0]) { continue; } if (grid_x > w) { break; } if (scissor->circular) { // clip line against circle float xc, yc; line[0] = x + grid_x; xc = line[0] >= x + .5f * w ? line[0] - (x + .5f * w) : (x + .5f * w) - line[0]; yc = SQRTFAST(Square(.5f * w) - Square(xc)); line[1] = y + (.5f * h) - yc; line[2] = 1.f; line[3] = 2 * yc; } else { Vector4Set(line, x + grid_x, y + dim_y[0], 1.f, h); } line[0] *= cgs.screenXScale; line[1] *= cgs.screenYScale; line[3] *= cgs.screenYScale; trap_R_DrawStretchPic(line[0], line[1], line[2], line[3], 0, 0, 0, 1, cgs.media.whiteShader); } for ( ; grid_y < dim_y[1]; grid_y += step[1]) { if (grid_y < dim_y[0]) { continue; } if (grid_y > h) { break; } if (scissor->circular) { // clip line against circle float xc, yc; line[1] = y + grid_y; yc = line[1] >= y + .5f * h ? line[1] - (y + .5f * h) : (y + .5f * h) - line[1]; xc = SQRTFAST(Square(.5f * h) - Square(yc)); line[0] = x + (.5f * w) - xc; line[2] = 2 * xc; line[3] = 1.f; } else { Vector4Set(line, x + dim_x[0], y + grid_y, w, 1); } line[0] *= cgs.screenXScale; line[1] *= cgs.screenYScale; line[2] *= cgs.screenXScale; trap_R_DrawStretchPic(line[0], line[1], line[2], line[3], 0, 0, 0, 1, cgs.media.whiteShader); } trap_R_SetColor(NULL); } else { char coord_char[3], coord_int; float text_width, text_height; vec2_t textOrigin; dim_x[0] = cg.mapcoordsMins[0]; dim_x[1] = cg.mapcoordsMaxs[0]; dim_y[0] = cg.mapcoordsMaxs[1]; dim_y[1] = cg.mapcoordsMins[1]; // transform xscale = w / dist[0]; yscale = h / -dist[1]; dim_x[0] = (dim_x[0] - cg.mapcoordsMins[0]) * xscale; dim_x[1] = (dim_x[1] - cg.mapcoordsMins[0]) * xscale; dim_y[0] = (dim_y[0] - cg.mapcoordsMaxs[1]) * yscale; dim_y[1] = (dim_y[1] - cg.mapcoordsMaxs[1]) * yscale; grid_x = gridStartCoord[0] * xscale; grid_y = gridStartCoord[1] * yscale; step[0] = gridStep[0] * xscale; step[1] = gridStep[1] * yscale; // draw textOrigin[0] = grid_x; textOrigin[1] = grid_y; Vector4Set(gridColour, clrBrownLine[0], clrBrownLine[1], clrBrownLine[2], 1.f); coord_char[1] = '\0'; for (coord_char[0] = ('A' - 1); grid_x < dim_x[1]; grid_x += step[0], coord_char[0]++) { if (coord_char[0] >= 'A') { text_width = CG_Text_Width_Ext(coord_char, 0.2f, 0, &cgs.media.limboFont2); text_height = CG_Text_Height_Ext(coord_char, 0.2f, 0, &cgs.media.limboFont2); CG_Text_Paint_Ext((x + grid_x) - (.5f * step[0]) - (.5f * text_width), y + dim_y[0] + textOrigin[1] + 1.5f * text_height, 0.2f, 0.2f, colorBlack, coord_char, 0, 0, 0, &cgs.media.limboFont2); } trap_R_SetColor(gridColour); Vector4Set(line, x + grid_x, y + dim_y[0], 1, dim_x[1] - dim_x[0]); CG_AdjustFrom640(&line[0], &line[1], &line[2], &line[3]); trap_R_DrawStretchPic(line[0], line[1], line[2], line[3], 0, 0, 0, 1, cgs.media.whiteShader); } for (coord_int = -1; grid_y < dim_y[1]; grid_y += step[1], coord_int++) { if (coord_int >= 0) { Com_sprintf(coord_char, sizeof(coord_char), "%i", coord_int); text_width = CG_Text_Width_Ext("0", 0.2f, 0, &cgs.media.limboFont2); text_height = CG_Text_Height_Ext(coord_char, 0.2f, 0, &cgs.media.limboFont2); CG_Text_Paint_Ext(x + dim_x[0] + textOrigin[0] + .5f * text_width, (y + grid_y) - (.5f * step[1]) + (.5f * text_height), 0.2f, 0.2f, colorBlack, coord_char, 0, 0, 0, &cgs.media.limboFont2); } trap_R_SetColor(gridColour); Vector4Set(line, x + dim_x[0], y + grid_y, dim_y[1] - dim_y[0], 1); CG_AdjustFrom640(&line[0], &line[1], &line[2], &line[3]); trap_R_DrawStretchPic(line[0], line[1], line[2], line[3], 0, 0, 0, 1, cgs.media.whiteShader); } trap_R_SetColor(NULL); } }
/* ================= CL_MouseMove ================= */ void CL_MouseMove( usercmd_t *cmd ) { float mx, my; const float speed = static_cast<float>(frame_msec); // allow mouse smoothing if ( m_filter->integer ) { mx = ( cl.mouseDx[0] + cl.mouseDx[1] ) * 0.5; my = ( cl.mouseDy[0] + cl.mouseDy[1] ) * 0.5; } else { mx = cl.mouseDx[cl.mouseIndex]; my = cl.mouseDy[cl.mouseIndex]; } cl.mouseIndex ^= 1; cl.mouseDx[cl.mouseIndex] = 0; cl.mouseDy[cl.mouseIndex] = 0; if ( mx == 0.0f && my == 0.0f ) return; if ( cl_mouseAccel->value != 0.0f ) { if ( cl_mouseAccelStyle->integer == 0 ) { float accelSensitivity; float rate; rate = SQRTFAST( mx * mx + my * my ) / speed; if ( cl_mYawOverride || cl_mPitchOverride ) {//FIXME: different people have different speed mouses, if ( cl_mSensitivityOverride ) { //this will f**k things up for them, need to clamp //max input? accelSensitivity = cl_mSensitivityOverride; } else { accelSensitivity = cl_sensitivity->value + rate * cl_mouseAccel->value; } } else { accelSensitivity = cl_sensitivity->value + rate * cl_mouseAccel->value; } mx *= accelSensitivity; my *= accelSensitivity; if ( cl_showMouseRate->integer ) Com_Printf( "rate: %f, accelSensitivity: %f\n", rate, accelSensitivity ); } else { float rate[2]; float power[2]; // sensitivity remains pretty much unchanged at low speeds // cl_mouseAccel is a power value to how the acceleration is shaped // cl_mouseAccelOffset is the rate for which the acceleration will have doubled the non accelerated amplification // NOTE: decouple the config cvars for independent acceleration setup along X and Y? rate[0] = fabs( mx ) / speed; rate[1] = fabs( my ) / speed; power[0] = powf( rate[0] / cl_mouseAccelOffset->value, cl_mouseAccel->value ); power[1] = powf( rate[1] / cl_mouseAccelOffset->value, cl_mouseAccel->value ); if ( cl_mYawOverride || cl_mPitchOverride ) {//FIXME: different people have different speed mouses, if ( cl_mSensitivityOverride ) { //this will f**k things up for them, need to clamp //max input? mx = cl_mSensitivityOverride * (mx + ((mx < 0) ? -power[0] : power[0]) * cl_mouseAccelOffset->value); my = cl_mSensitivityOverride * (my + ((my < 0) ? -power[1] : power[1]) * cl_mouseAccelOffset->value); } else { mx = cl_sensitivity->value * (mx + ((mx < 0) ? -power[0] : power[0]) * cl_mouseAccelOffset->value); my = cl_sensitivity->value * (my + ((my < 0) ? -power[1] : power[1]) * cl_mouseAccelOffset->value); } } else { mx = cl_sensitivity->value * (mx + ((mx < 0) ? -power[0] : power[0]) * cl_mouseAccelOffset->value); my = cl_sensitivity->value * (my + ((my < 0) ? -power[1] : power[1]) * cl_mouseAccelOffset->value); } if ( cl_showMouseRate->integer ) Com_Printf( "ratex: %f, ratey: %f, powx: %f, powy: %f\n", rate[0], rate[1], power[0], power[1] ); } } else { if ( cl_mYawOverride || cl_mPitchOverride ) {//FIXME: different people have different speed mouses, if ( cl_mSensitivityOverride ) { //this will f**k things up for them, need to clamp //max input? mx *= cl_mSensitivityOverride; my *= cl_mSensitivityOverride; } else { mx *= cl_sensitivity->value; my *= cl_sensitivity->value; } } else { mx *= cl_sensitivity->value; my *= cl_sensitivity->value; } } // ingame FOV mx *= cl.cgameSensitivity; my *= cl.cgameSensitivity; // add mouse X/Y movement to cmd if ( in_strafe.active ) cmd->rightmove = ClampChar( cmd->rightmove + m_side->value * mx ); else { if ( cl_mYawOverride ) cl.viewangles[YAW] -= cl_mYawOverride * mx; else cl.viewangles[YAW] -= m_yaw->value * mx; } if ( (in_mlooking || cl_freelook->integer) && !in_strafe.active ) { // VVFIXME - This is supposed to be a CVAR const float cl_pitchSensitivity = 1.0f; const float pitch = cl_bUseFighterPitch ? m_pitchVeh->value : m_pitch->value; if ( cl_mPitchOverride ) { if ( pitch > 0 ) cl.viewangles[PITCH] += cl_mPitchOverride * my * cl_pitchSensitivity; else cl.viewangles[PITCH] -= cl_mPitchOverride * my * cl_pitchSensitivity; } else cl.viewangles[PITCH] += pitch * my * cl_pitchSensitivity; } else cmd->forwardmove = ClampChar( cmd->forwardmove - m_forward->value * my ); }
void QClipMap46::TraceThroughSphere( traceWork_t* tw, vec3_t origin, float radius, vec3_t start, vec3_t end ) { float l1, l2, length, scale, fraction; float b, c, d, sqrtd; vec3_t v1, dir, intersection; // if inside the sphere VectorSubtract( start, origin, dir ); l1 = VectorLengthSquared( dir ); if ( l1 < Square( radius ) ) { tw->trace.fraction = 0; tw->trace.startsolid = true; // test for allsolid VectorSubtract( end, origin, dir ); l1 = VectorLengthSquared( dir ); if ( l1 < Square( radius ) ) { tw->trace.allsolid = true; } return; } // VectorSubtract( end, start, dir ); length = VectorNormalize( dir ); // l1 = DistanceFromLineSquaredDir( origin, start, end, dir ); VectorSubtract( end, origin, v1 ); l2 = VectorLengthSquared( v1 ); // if no intersection with the sphere and the end point is at least an epsilon away if ( l1 >= Square( radius ) && l2 > Square( radius + SURFACE_CLIP_EPSILON ) ) { return; } // // | origin - (start + t * dir) | = radius // a = dir[0]^2 + dir[1]^2 + dir[2]^2; // b = 2 * (dir[0] * (start[0] - origin[0]) + dir[1] * (start[1] - origin[1]) + dir[2] * (start[2] - origin[2])); // c = (start[0] - origin[0])^2 + (start[1] - origin[1])^2 + (start[2] - origin[2])^2 - radius^2; // VectorSubtract( start, origin, v1 ); // dir is normalized so a = 1 //float a = 1.0f; //dir[0] * dir[0] + dir[1] * dir[1] + dir[2] * dir[2]; b = 2.0f * ( dir[ 0 ] * v1[ 0 ] + dir[ 1 ] * v1[ 1 ] + dir[ 2 ] * v1[ 2 ] ); c = v1[ 0 ] * v1[ 0 ] + v1[ 1 ] * v1[ 1 ] + v1[ 2 ] * v1[ 2 ] - ( radius + RADIUS_EPSILON ) * ( radius + RADIUS_EPSILON ); d = b * b - 4.0f * c; // * a; if ( d > 0 ) { sqrtd = SQRTFAST( d ); // = (- b + sqrtd) * 0.5f; // / (2.0f * a); fraction = ( -b - sqrtd ) * 0.5f; // / (2.0f * a); // if ( fraction < 0 ) { fraction = 0; } else { fraction /= length; } if ( fraction < tw->trace.fraction ) { tw->trace.fraction = fraction; VectorSubtract( end, start, dir ); VectorMA( start, fraction, dir, intersection ); VectorSubtract( intersection, origin, dir ); #ifdef CAPSULE_DEBUG l2 = VectorLength( dir ); if ( l2 < radius ) { int bah = 1; } #endif scale = 1 / ( radius + RADIUS_EPSILON ); VectorScale( dir, scale, dir ); VectorCopy( dir, tw->trace.plane.normal ); VectorAdd( tw->modelOrigin, intersection, intersection ); tw->trace.plane.dist = DotProduct( tw->trace.plane.normal, intersection ); tw->trace.contents = BSP46CONTENTS_BODY; } } else if ( d == 0 ) { //t1 = (- b ) / 2; // slide along the sphere } // no intersection at all }
void QClipMap46::TraceThroughVerticalCylinder( traceWork_t* tw, vec3_t origin, float radius, float halfheight, vec3_t start, vec3_t end ) { float length, scale, fraction, l1, l2; float b, c, d, sqrtd; vec3_t v1, dir, start2d, end2d, org2d, intersection; // 2d coordinates VectorSet( start2d, start[ 0 ], start[ 1 ], 0 ); VectorSet( end2d, end[ 0 ], end[ 1 ], 0 ); VectorSet( org2d, origin[ 0 ], origin[ 1 ], 0 ); // if between lower and upper cylinder bounds if ( start[ 2 ] <= origin[ 2 ] + halfheight && start[ 2 ] >= origin[ 2 ] - halfheight ) { // if inside the cylinder VectorSubtract( start2d, org2d, dir ); l1 = VectorLengthSquared( dir ); if ( l1 < Square( radius ) ) { tw->trace.fraction = 0; tw->trace.startsolid = true; VectorSubtract( end2d, org2d, dir ); l1 = VectorLengthSquared( dir ); if ( l1 < Square( radius ) ) { tw->trace.allsolid = true; } return; } } // VectorSubtract( end2d, start2d, dir ); length = VectorNormalize( dir ); // l1 = DistanceFromLineSquaredDir( org2d, start2d, end2d, dir ); VectorSubtract( end2d, org2d, v1 ); l2 = VectorLengthSquared( v1 ); // if no intersection with the cylinder and the end point is at least an epsilon away if ( l1 >= Square( radius ) && l2 > Square( radius + SURFACE_CLIP_EPSILON ) ) { return; } // // // (start[0] - origin[0] - t * dir[0]) ^ 2 + (start[1] - origin[1] - t * dir[1]) ^ 2 = radius ^ 2 // (v1[0] + t * dir[0]) ^ 2 + (v1[1] + t * dir[1]) ^ 2 = radius ^ 2; // v1[0] ^ 2 + 2 * v1[0] * t * dir[0] + (t * dir[0]) ^ 2 + // v1[1] ^ 2 + 2 * v1[1] * t * dir[1] + (t * dir[1]) ^ 2 = radius ^ 2 // t ^ 2 * (dir[0] ^ 2 + dir[1] ^ 2) + t * (2 * v1[0] * dir[0] + 2 * v1[1] * dir[1]) + // v1[0] ^ 2 + v1[1] ^ 2 - radius ^ 2 = 0 // VectorSubtract( start, origin, v1 ); // dir is normalized so we can use a = 1 //float a = 1.0f; // * (dir[0] * dir[0] + dir[1] * dir[1]); b = 2.0f * ( v1[ 0 ] * dir[ 0 ] + v1[ 1 ] * dir[ 1 ] ); c = v1[ 0 ] * v1[ 0 ] + v1[ 1 ] * v1[ 1 ] - ( radius + RADIUS_EPSILON ) * ( radius + RADIUS_EPSILON ); d = b * b - 4.0f * c; // * a; if ( d > 0 ) { sqrtd = SQRTFAST( d ); // = (- b + sqrtd) * 0.5f;// / (2.0f * a); fraction = ( -b - sqrtd ) * 0.5f; // / (2.0f * a); // if ( fraction < 0 ) { fraction = 0; } else { fraction /= length; } if ( fraction < tw->trace.fraction ) { VectorSubtract( end, start, dir ); VectorMA( start, fraction, dir, intersection ); // if the intersection is between the cylinder lower and upper bound if ( intersection[ 2 ] <= origin[ 2 ] + halfheight && intersection[ 2 ] >= origin[ 2 ] - halfheight ) { // tw->trace.fraction = fraction; VectorSubtract( intersection, origin, dir ); dir[ 2 ] = 0; #ifdef CAPSULE_DEBUG l2 = VectorLength( dir ); if ( l2 <= radius ) { int bah = 1; } #endif scale = 1 / ( radius + RADIUS_EPSILON ); VectorScale( dir, scale, dir ); VectorCopy( dir, tw->trace.plane.normal ); VectorAdd( tw->modelOrigin, intersection, intersection ); tw->trace.plane.dist = DotProduct( tw->trace.plane.normal, intersection ); tw->trace.contents = BSP46CONTENTS_BODY; } } } else if ( d == 0 ) { //t[0] = (- b ) / 2 * a; // slide along the cylinder } // no intersection at all }