Quake3World.com https://www.quake3world.com/forum/ |
|
BFP camera code implementation https://www.quake3world.com/forum/viewtopic.php?f=16&t=54989 |
Page 1 of 1 |
Author: | LegendGuard [ 02-05-2023 06:23 AM ] |
Post subject: | BFP camera code implementation |
I'm implementing BFP camera view, but it doesn't do the same like original Bid For Power (BFP). But AFAIK, the code uses modified Q3 camera parts, it doesn't do the same as ZEQ2-Lite (nothing to do). The camera does a pretty wild flip when flying upside down, have less zoom/more distance than BFP, ... That's badly implemented. Just asking, what should be correct to be the same as BFP camera view? Video comparising camera implementation and original BFP camera: https://streamable.com/4gee0d Code of the camera implementation in CG_OffsetThirdPersonView: Code: /*
=============== CG_OffsetThirdPersonView =============== */ #define FOCUS_DISTANCE 512 static void CG_OffsetThirdPersonView( void ) { vec3_t forward, right, up; vec3_t view; vec3_t focusAngles; trace_t trace; static vec3_t mins = { -4, -4, -4 }; static vec3_t maxs = { 4, 4, 4 }; vec3_t focusPoint; float focusDist; float forwardScale, sideScale; // BFP - TODO: Improve camera, when player looks at the ground, the view should // be adjusted where the player position, in the screen, is further down like BFP does. // The camera isn't using a fixed view cg.refdef.vieworg[2] += cg.predictedPlayerState.viewheight; VectorCopy( cg.refdefViewAngles, focusAngles ); // if dead, look at killer if ( cg.predictedPlayerState.stats[STAT_HEALTH] <= 0 ) { focusAngles[YAW] = cg.predictedPlayerState.stats[STAT_DEAD_YAW]; cg.refdefViewAngles[YAW] = cg.predictedPlayerState.stats[STAT_DEAD_YAW]; } // if ( focusAngles[PITCH] > 45 ) { // focusAngles[PITCH] = 45; // don't go too far overhead // } AngleVectors( focusAngles, forward, NULL, NULL ); VectorMA( cg.refdef.vieworg, FOCUS_DISTANCE, forward, focusPoint ); VectorCopy( cg.refdef.vieworg, view ); // view[2] += 8; // BFP - Third person camera height view[2] += cg_thirdPersonHeight.value + 92; // BFP - Keep the looking on the ground at the same main focus position // if ( !( cg.predictedPlayerState.pm_flags & PMF_FLYING ) ) { cg.refdefViewAngles[PITCH] *= 1.55; // } AngleVectors( cg.refdefViewAngles, forward, right, up ); forwardScale = cos( cg_thirdPersonAngle.value / 180 * M_PI ); sideScale = sin( cg_thirdPersonAngle.value / 180 * M_PI ); VectorMA( view, -cg_thirdPersonRange.value * forwardScale, forward, view ); VectorMA( view, -cg_thirdPersonRange.value * sideScale, right, view ); // trace a ray from the origin to the viewpoint to make sure the view isn't // in a solid block. Use an 8 by 8 block to prevent the view from near clipping anything // if (!cg_cameraMode.integer) { CG_Trace( &trace, cg.refdef.vieworg, mins, maxs, view, cg.predictedPlayerState.clientNum, MASK_SOLID ); if ( trace.fraction != 1.0 ) { VectorCopy( trace.endpos, view ); view[2] += (1.0 - trace.fraction) * 32; // try another trace to this position, because a tunnel may have the ceiling // close enogh that this is poking out CG_Trace( &trace, cg.refdef.vieworg, mins, maxs, view, cg.predictedPlayerState.clientNum, MASK_SOLID ); VectorCopy( trace.endpos, view ); } // } VectorCopy( view, cg.refdef.vieworg ); // select pitch to look at focus point from vieword VectorSubtract( focusPoint, cg.refdef.vieworg, focusPoint ); focusDist = sqrt( focusPoint[0] * focusPoint[0] + focusPoint[1] * focusPoint[1] ); if ( focusDist < 1 ) { focusDist = 1; // should never happen } // cg.refdefViewAngles[PITCH] = -180 / M_PI * atan2( focusPoint[2], focusDist ); cg.refdefViewAngles[PITCH] = focusAngles[PITCH]; cg.refdefViewAngles[YAW] -= cg_thirdPersonAngle.value; //cg.refdefViewAngles[YAW] = focusAngles[YAW]; } |
Author: | LegendGuard [ 02-12-2023 08:34 AM ] |
Post subject: | Re: BFP camera code implementation |
Finally, BFP third person camera implemented! Wooohoooohoho!!! https://github.com/LegendaryGuard/BFP/c ... 220067e33d |
Author: | LegendGuard [ 02-22-2023 03:47 PM ] |
Post subject: | Re: BFP camera code implementation |
BFP 3rd person camera matches 100% to original BFP! Moreover, 1st person vis mode is implemented! Let's goooooo!! Here the 3rd person camera code: Code: #define FOCUS_DISTANCE 512
static void CG_OffsetThirdPersonView( void ) { vec3_t forward, right, up; vec3_t view; vec3_t focusAngles; trace_t trace; static vec3_t mins = { -4, -4, -4 }; static vec3_t maxs = { 4, 4, 4 }; float forwardScale, sideScale; // BFP - Camera setup variables vec3_t overrideOrg; float camAngle, camHeight, camRange; // BFP - Fly tilt int cmdNum; usercmd_t cmd; // BFP - Last angled for fly tilt angle to move smoothly similar to BFP vanilla static float lastAngled = 0.0f, lastRightAngled = 0.0f, lastUpAngled = 0.0f; float rightAngled, upAngled; // BFP - Camera setup camAngle = cg_thirdPersonAngle.value; camHeight = cg_thirdPersonHeight.value; camRange = cg_thirdPersonRange.value; if ( cg_fixedThirdPerson.integer >= 1 ) { // BFP - Fixed third person camera camAngle = 0.0f; camHeight = -60.0f; camRange = 110.0f; } VectorCopy( cg.refdef.vieworg, overrideOrg ); // cg.refdef.vieworg[2] += cg.predictedPlayerState.viewheight; // BFP - BFP camera position doesn't use that to move to player's height VectorCopy( cg.refdefViewAngles, focusAngles ); // if dead, look at killer if ( cg.predictedPlayerState.stats[STAT_HEALTH] <= 0 ) { focusAngles[YAW] = cg.predictedPlayerState.stats[STAT_DEAD_YAW]; cg.refdefViewAngles[YAW] = cg.predictedPlayerState.stats[STAT_DEAD_YAW]; } AngleVectors( focusAngles, forward, NULL, NULL ); VectorCopy( cg.refdef.vieworg, view ); AngleVectors( cg.refdefViewAngles, forward, right, up ); // BFP - Camera height setup VectorMA( overrideOrg, -camHeight, up, overrideOrg ); forwardScale = cos( camAngle / 180 * M_PI ); sideScale = sin( camAngle / 180 * M_PI ); // trace a ray from the origin to the viewpoint to make sure the view isn't // in a solid block. Use an 8 by 8 block to prevent the view from near clipping anything // BFP - cg_cameraMode cvar to detect if it's disabled doesn't exist // That traces the camera pivot CG_Trace( &trace, cg.refdef.vieworg, mins, maxs, view, cg.predictedPlayerState.clientNum, MASK_SOLID ); if ( trace.fraction != 1.0 ) { // BFP - Use the vector scale to trace something solid and add endpos VectorScale( trace.plane.normal, camRange, view ); VectorAdd( trace.endpos, view, cg.refdef.vieworg ); view[2] += (1.0 - trace.fraction) * 32; // try another trace to this position, because a tunnel may have the ceiling // close enogh that this is poking out CG_Trace( &trace, cg.refdef.vieworg, mins, maxs, view, cg.predictedPlayerState.clientNum, MASK_SOLID ); VectorCopy( trace.endpos, view ); } // BFP - Camera setup focusAngles[YAW] -= camAngle; // BFP - Fly tilt // Get the pressed keys to move left or right cmdNum = trap_GetCurrentCmdNumber(); trap_GetUserCmd( cmdNum, &cmd ); focusAngles[ROLL] = LERP( lastAngled, 0.0f, (float)(cg.frametime / 1000.00f) * 20.0f ); rightAngled = LERP( lastRightAngled, 0.0f, (float)(cg.frametime / 1000.00f) * 20.0f ); upAngled = LERP( lastUpAngled, 0.0f, (float)(cg.frametime / 1000.00f) * 20.0f ); if ( cg_flytilt.integer >= 1 && ( cg.predictedPlayerState.pm_flags & PMF_FLYING ) && ( cg.predictedPlayerState.eFlags & EF_AURA ) && &cmd ) { if ( cmd.rightmove < 0 ) { // Left focusAngles[ROLL] = LERP( lastAngled, -20.0f, (float)(cg.frametime / 1000.00f) * 15.0f ); rightAngled = LERP( lastRightAngled, focusAngles[ROLL] - 0.55f, (float)(cg.frametime / 1000.00f) * 15.0f ); upAngled = LERP( lastUpAngled, -acos( focusAngles[ROLL] / 180 * M_PI ) - 1.7f, (float)(cg.frametime / 1000.00f) * 15.0f ); } else if ( cmd.rightmove > 0 ) { // Right focusAngles[ROLL] = LERP( lastAngled, 20.0f, (float)(cg.frametime / 1000.00f) * 15.0f ); rightAngled = LERP( lastRightAngled, focusAngles[ROLL] - 0.55f, (float)(cg.frametime / 1000.00f) * 15.0f ); upAngled = LERP( lastUpAngled, -acos( focusAngles[ROLL] / 180 * M_PI ) - 1.7f, (float)(cg.frametime / 1000.00f) * 15.0f ); } } // Last roll where it was "lerped" lastAngled = focusAngles[ROLL]; lastRightAngled = rightAngled; lastUpAngled = upAngled; VectorCopy( focusAngles, cg.refdefViewAngles ); // VectorCopy( focusAngles, cg.predictedPlayerState.viewangles ); // For player model, doesn't make sense though :P // BFP - NOTE: Applying angles to height and slide (up and right vectors), while rolling with fly tilt, is an odd case, BFP has something that handles up and right vectors (· ·') *curiosity sweat* VectorMA( overrideOrg, -camRange * sideScale + rightAngled, right, cg.refdef.vieworg ); VectorMA( cg.refdef.vieworg, -camRange * forwardScale, forward, cg.refdef.vieworg ); VectorMA( cg.refdef.vieworg, upAngled, up, cg.refdef.vieworg ); // BFP - Trace the camera position when being near to something solid CG_Trace( &trace, view, mins, maxs, cg.refdef.vieworg, cg.predictedPlayerState.clientNum, MASK_SOLID ); if ( trace.fraction != 1.0f ) { VectorCopy( trace.endpos, cg.refdef.vieworg ); cg.refdef.vieworg[2] += ( 1.0f - trace.fraction ) * 32; CG_Trace( &trace, view, mins, maxs, cg.refdef.vieworg, cg.predictedPlayerState.clientNum, MASK_SOLID ); VectorCopy( trace.endpos, cg.refdef.vieworg ); } } |
Author: | LegendGuard [ 10-02-2023 02:59 AM ] |
Post subject: | Re: BFP camera code implementation |
Here the part of 1st person vis mode (if you wanna use the code, you will need to use correctly the functions due the difference of the functionality. Look carefully to the implementation in the repository on cg_view.c and cg_players.c): Code: void CG_OffsetFirstPersonView( centity_t *cent, refEntity_t *parent, qhandle_t parentModel ) { // BFP - First person setup, originally, Q3 doesn't use these parameters
float *origin; float *angles; float bob; float ratio; float delta; float speed; float f; vec3_t predictedVelocity; int timeDelta; orientation_t tagOrient; // BFP - First person vis mode orientation setup if ( cg.snap->ps.pm_type == PM_INTERMISSION ) { return; } origin = cg.refdef.vieworg; angles = cg.refdefViewAngles; // if dead, fix the angle and don't add any kick if ( cg.snap->ps.stats[STAT_HEALTH] <= 0 ) { angles[ROLL] = 40; angles[PITCH] = -15; angles[YAW] = cg.snap->ps.stats[STAT_DEAD_YAW]; origin[2] += cg.predictedPlayerState.viewheight; return; } // add angles based on weapon kick VectorAdd (angles, cg.kick_angles, angles); // add angles based on damage kick if ( cg.damageTime ) { ratio = cg.time - cg.damageTime; if ( ratio < DAMAGE_DEFLECT_TIME ) { ratio /= DAMAGE_DEFLECT_TIME; angles[PITCH] += ratio * cg.v_dmg_pitch; angles[ROLL] += ratio * cg.v_dmg_roll; } else { ratio = 1.0 - ( ratio - DAMAGE_DEFLECT_TIME ) / DAMAGE_RETURN_TIME; if ( ratio > 0 ) { angles[PITCH] += ratio * cg.v_dmg_pitch; angles[ROLL] += ratio * cg.v_dmg_roll; } } } // add angles based on velocity VectorCopy( cg.predictedPlayerState.velocity, predictedVelocity ); delta = DotProduct ( predictedVelocity, cg.refdef.viewaxis[0]); angles[PITCH] += delta * cg_runpitch.value; delta = DotProduct ( predictedVelocity, cg.refdef.viewaxis[1]); angles[ROLL] -= delta * cg_runroll.value; // add angles based on bob // make sure the bob is visible even at low speeds speed = cg.xyspeed > 200 ? cg.xyspeed : 200; delta = cg.bobfracsin * cg_bobpitch.value * speed; if (cg.predictedPlayerState.pm_flags & PMF_DUCKED) delta *= 3; // crouching angles[PITCH] += delta; delta = cg.bobfracsin * cg_bobroll.value * speed; if (cg.predictedPlayerState.pm_flags & PMF_DUCKED) delta *= 3; // crouching accentuates roll if (cg.bobcycle & 1) delta = -delta; angles[ROLL] += delta; //=================================== // add view height origin[2] += cg.predictedPlayerState.viewheight; // smooth out duck height changes timeDelta = cg.time - cg.duckTime; if ( timeDelta < DUCK_TIME) { cg.refdef.vieworg[2] -= cg.duckChange * (DUCK_TIME - timeDelta) / DUCK_TIME; } // add bob height bob = cg.bobfracsin * cg.xyspeed * cg_bobup.value; if (bob > 6) { bob = 6; } origin[2] += bob; // BFP - First person vis mode // pivot the eye based on a neck length #if 1 if ( cg_drawOwnModel.integer >= 1 ) { #define NECK_LENGTH 8 vec3_t forward, up; VectorClear( cg.refdefViewAngles ); if ( CG_GetTagOrientationFromPlayerEntityParentModel( cent, parent, parentModel, "tag_head", &tagOrient ) ) { VectorCopy( tagOrient.origin, cg.refdef.vieworg ); cg.refdef.vieworg[2] -= NECK_LENGTH; AngleVectors( cg.refdefViewAngles, forward, NULL, up ); VectorMA( cg.refdef.vieworg, -1, forward, cg.refdef.vieworg ); VectorMA( cg.refdef.vieworg, NECK_LENGTH, up, cg.refdef.vieworg ); } } #endif // add fall height delta = cg.time - cg.landTime; if ( delta < LAND_DEFLECT_TIME ) { f = delta / LAND_DEFLECT_TIME; cg.refdef.vieworg[2] += cg.landChange * f; } else if ( delta < LAND_DEFLECT_TIME + LAND_RETURN_TIME ) { delta -= LAND_DEFLECT_TIME; f = 1.0 - ( delta / LAND_RETURN_TIME ); cg.refdef.vieworg[2] += cg.landChange * f; } // add step offset CG_StepOffset(); // add kick offset VectorAdd (origin, cg.kick_origin, origin); } |
Page 1 of 1 | All times are UTC - 8 hours |
Powered by phpBB © 2000, 2002, 2005, 2007 phpBB Group http://www.phpbb.com/ |