From ab51fc359691c325577751771c04bcf3001627ef Mon Sep 17 00:00:00 2001 From: Day Date: Fri, 17 Apr 2015 13:21:14 +0200 Subject: [PATCH 1/4] Fov is now accessible through javascript. Oolite.gameSettings.fov (read-only): player game option fov, in degrees PlayerShip.viewFov (read/write): current view fov, in degrees --- src/Core/Entities/PlayerEntity.h | 5 ++-- src/Core/Entities/PlayerEntity.m | 14 +++++++--- src/Core/Entities/PlayerEntityControls.m | 33 +++++++++++++----------- src/Core/Scripting/OOJSPlayerShip.m | 15 ++++++++++- src/Core/Universe.m | 3 ++- 5 files changed, 47 insertions(+), 23 deletions(-) diff --git a/src/Core/Entities/PlayerEntity.h b/src/Core/Entities/PlayerEntity.h index c10e3bcc7..1bb7879d9 100644 --- a/src/Core/Entities/PlayerEntity.h +++ b/src/Core/Entities/PlayerEntity.h @@ -721,8 +721,6 @@ typedef enum StickProfileScreen *stickProfileScreen; - double maxFieldOfView; - double fieldOfView; #if OO_FOV_INFLIGHT_CONTROL_ENABLED double fov_delta; #endif @@ -1161,6 +1159,9 @@ typedef enum */ - (GLfloat) insideAtmosphereFraction; +- (void) viewFov:(float)fovDegrees; +- (float) viewFov; + @end diff --git a/src/Core/Entities/PlayerEntity.m b/src/Core/Entities/PlayerEntity.m index bf4bc917a..c2bb4759f 100644 --- a/src/Core/Entities/PlayerEntity.m +++ b/src/Core/Entities/PlayerEntity.m @@ -1581,7 +1581,6 @@ - (void) deferredInit NSAssert(gOOPlayer == self, @"Expected only one PlayerEntity to exist at a time."); NSAssert([super initWithKey:PLAYER_SHIP_DESC definition:[NSDictionary dictionary]] == self, @"PlayerEntity requires -[ShipEntity initWithKey:definition:] to return unmodified self."); - maxFieldOfView = MAX_FOV; #if OO_FOV_INFLIGHT_CONTROL_ENABLED fov_delta = 2.0; // multiply by 2 each second #endif @@ -1624,7 +1623,6 @@ - (BOOL) setUpAndConfirmOK:(BOOL)stopOnError - (BOOL) setUpAndConfirmOK:(BOOL)stopOnError saveGame:(BOOL)saveGame { - fieldOfView = [[UNIVERSE gameView] fov:YES]; unsigned i; showDemoShips = NO; @@ -2837,8 +2835,6 @@ - (void) doBookkeeping:(double) delta_t [hud setScannerZoom:z1]; } - [[UNIVERSE gameView] setFov:fieldOfView fromFraction:YES]; - // scanner sanity check - lose any targets further than maximum scanner range ShipEntity *primeTarget = [self primaryTarget]; if (primeTarget && HPdistance2([primeTarget position], [self position]) > SCANNER_MAX_RANGE2 && !autopilot_engaged) @@ -12435,6 +12431,16 @@ - (BOOL) suppressClangStuff } #endif +- (void) viewFov:(float)fovDegrees +{ + [[UNIVERSE gameView] setFov:fovDegrees fromFraction:NO]; +} + +- (float) viewFov +{ + return [[UNIVERSE gameView] fov:NO]; +} + @end diff --git a/src/Core/Entities/PlayerEntityControls.m b/src/Core/Entities/PlayerEntityControls.m index bde75572b..6c41d2c42 100644 --- a/src/Core/Entities/PlayerEntityControls.m +++ b/src/Core/Entities/PlayerEntityControls.m @@ -1408,32 +1408,36 @@ - (void) pollFlightControls:(double)delta_t // Field of view controls if (![UNIVERSE displayGUI]) { - if (([gameView isDown:key_inc_field_of_view] || joyButtonState[BUTTON_INC_FIELD_OF_VIEW]) && (fieldOfView < MAX_FOV)) + float fov = [gameView fov:YES]; + if (([gameView isDown:key_inc_field_of_view] || joyButtonState[BUTTON_INC_FIELD_OF_VIEW]) && (fov < MAX_FOV)) { - fieldOfView *= pow(fov_delta, delta_t); - if (fieldOfView > MAX_FOV) fieldOfView = MAX_FOV; + fov *= pow(fov_delta, delta_t); + if (fov > MAX_FOV) fov = MAX_FOV; + [gameView setFov:(fov) fromFraction:YES]; } - if (([gameView isDown:key_dec_field_of_view] || joyButtonState[BUTTON_DEC_FIELD_OF_VIEW]) && (fieldOfView > MIN_FOV)) + if (([gameView isDown:key_dec_field_of_view] || joyButtonState[BUTTON_DEC_FIELD_OF_VIEW]) && (fov > MIN_FOV)) { - fieldOfView /= pow(fov_delta, delta_t); - if (fieldOfView < MIN_FOV) fieldOfView = MIN_FOV; + fov /= pow(fov_delta, delta_t); + if (fov < MIN_FOV) fov = MIN_FOV; + [gameView setFov:(fov) fromFraction:YES]; } NSDictionary *functionForFovAxis = [[stickHandler axisFunctions] oo_dictionaryForKey:[[NSNumber numberWithInt:AXIS_FIELD_OF_VIEW] stringValue]]; if ([stickHandler joystickCount] != 0 && functionForFovAxis != nil) { - // TODO think reqFov through double reqFov = [stickHandler getAxisState: AXIS_FIELD_OF_VIEW]; - if (fieldOfView < maxFieldOfView * reqFov) + if (fov < MAX_FOV * reqFov) { - fieldOfView *= pow(fov_delta, delta_t); - if (fieldOfView > MAX_FOV) fieldOfView = MAX_FOV; + fov *= pow(fov_delta, delta_t); + if (fov > MAX_FOV) fov = MAX_FOV; + [gameView setFov:(fov) fromFraction:YES]; } - if (fieldOfView > maxFieldOfView * reqFov) + if (fov > MAX_FOV * reqFov) { - fieldOfView /= pow(fov_delta, delta_t); - if (fieldOfView < MIN_FOV) fieldOfView = MIN_FOV; + fov /= pow(fov_delta, delta_t); + if (fov < MIN_FOV) fov = MIN_FOV; + [gameView setFov:(fov) fromFraction:YES]; } } } @@ -3145,14 +3149,13 @@ sets the actual screen resolution (controller just stores if (fov > MAX_FOV_DEG) fov = MAX_FOV_DEG; if (fov < MIN_FOV_DEG) fov = MIN_FOV_DEG; [gameView setFov:fov fromFraction:NO]; - fieldOfView = [gameView fov:YES]; int fovTicks = (int)((fov - MIN_FOV_DEG) / fovStep); NSString* fovWordDesc = DESC(@"gameoptions-fov-value"); NSString* v1_string = @"|||||||||||||||||||||||||"; NSString* v0_string = @"........................."; v1_string = [v1_string substringToIndex:fovTicks]; v0_string = [v0_string substringToIndex:20 - fovTicks]; - [gui setText:[NSString stringWithFormat:@"%@%@%@ (%d%c) ", fovWordDesc, v1_string, v0_string, (int)fov, 176 /*176 is the degrees symbol ASCII code*/] forRow:GUI_ROW(GAME,FOV) align:GUI_ALIGN_CENTER]; + [gui setText:[NSString stringWithFormat:@"%@%@%@ (%d%c) ", fovWordDesc, v1_string, v0_string, (int)fov, 176 /*176 is the degrees symbol ASCII code*/] forRow:GUI_ROW(GAME,FOV) align:GUI_ALIGN_CENTER]; [[NSUserDefaults standardUserDefaults] setFloat:[gameView fov:NO] forKey:@"fov-value"]; timeLastKeyPress = script_time; } diff --git a/src/Core/Scripting/OOJSPlayerShip.m b/src/Core/Scripting/OOJSPlayerShip.m index 531b01e2e..32076184c 100644 --- a/src/Core/Scripting/OOJSPlayerShip.m +++ b/src/Core/Scripting/OOJSPlayerShip.m @@ -146,6 +146,7 @@ kPlayerShip_viewPositionForward, // view position offset, vector, read-only kPlayerShip_viewPositionPort, // view position offset, vector, read-only kPlayerShip_viewPositionStarboard, // view position offset, vector, read-only + kPlayerShip_viewFov, // view fov in degrees, positive float, read/write kPlayerShip_weaponsOnline, // weapons online status, boolean, read-only kPlayerShip_yaw, // yaw (overrules Ship) }; @@ -201,6 +202,7 @@ { "viewPositionForward", kPlayerShip_viewPositionForward, OOJS_PROP_READONLY_CB }, { "viewPositionPort", kPlayerShip_viewPositionPort, OOJS_PROP_READONLY_CB }, { "viewPositionStarboard", kPlayerShip_viewPositionStarboard, OOJS_PROP_READONLY_CB }, + { "viewFov", kPlayerShip_viewFov, OOJS_PROP_READWRITE_CB }, { "weaponsOnline", kPlayerShip_weaponsOnline, OOJS_PROP_READONLY_CB }, { "yaw", kPlayerShip_yaw, OOJS_PROP_READONLY_CB }, { 0 } @@ -469,6 +471,9 @@ static JSBool PlayerShipGetProperty(JSContext *context, JSObject *this, jsid pro case kPlayerShip_viewPositionStarboard: return VectorToJSValue(context, [player viewpointOffsetStarboard], value); + case kPlayerShip_viewFov: + return JS_NewNumberValue(context, [player viewFov], value); + case kPlayerShip_currentWeapon: result = [player weaponTypeForFacing:[player currentWeaponFacing] strict:NO]; break; @@ -709,7 +714,15 @@ static JSBool PlayerShipSetProperty(JSContext *context, JSObject *this, jsid pro [player adjustTradeInFactorBy:(newLevel-[player tradeInFactor])]; return YES; } - + + case kPlayerShip_viewFov: + if (JS_ValueToNumber(context, *value, &fValue)) + { + [player viewFov:fValue]; + return YES; + } + break; + case kPlayerShip_currentWeapon: { BOOL exists = NO; diff --git a/src/Core/Universe.m b/src/Core/Universe.m index 0bf326169..a9536116e 100644 --- a/src/Core/Universe.m +++ b/src/Core/Universe.m @@ -4048,7 +4048,8 @@ - (NSDictionary *) gameSettings [result oo_setFloat:[gameView gammaValue] forKey:@"gammaValue"]; #endif - [result oo_setFloat:[gameView fov:NO] forKey:@"fovValue"]; + NSUserDefaults *prefs = [NSUserDefaults standardUserDefaults]; + [result oo_setFloat:[prefs oo_floatForKey:@"fov-value" defaultValue:57.2f] forKey:@"fovValue"]; [result setObject:OOStringFromGraphicsDetail([self detailLevel]) forKey:@"detailLevel"]; From dd3d0f7da4c2ae4cfab58aabb61d7fc9107d6694 Mon Sep 17 00:00:00 2001 From: Day Date: Wed, 22 Apr 2015 09:19:48 +0200 Subject: [PATCH 2/4] BUGFIXES The game options gui now displays correctly not the currently used angle of view value, but the player chosen angle of view. Moreover, modifying the currently used angle of view doesn't modify anymore the player chosen angle of view. --- src/Core/Entities/PlayerEntity.m | 2 +- src/Core/Entities/PlayerEntityControls.m | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/Core/Entities/PlayerEntity.m b/src/Core/Entities/PlayerEntity.m index c2bb4759f..381020263 100644 --- a/src/Core/Entities/PlayerEntity.m +++ b/src/Core/Entities/PlayerEntity.m @@ -8278,7 +8278,7 @@ - (void) setGuiToGameOptionsScreen #endif // field of view control - float fov = [gameView fov:NO]; + float fov = [[NSUserDefaults standardUserDefaults] floatForKey:@"fov-value"]; int fovTicks = (int)((fov - MIN_FOV_DEG) * 20 / (MAX_FOV_DEG - MIN_FOV_DEG)); NSString* fovWordDesc = DESC(@"gameoptions-fov-value"); v1_string = @"|||||||||||||||||||||||||"; diff --git a/src/Core/Entities/PlayerEntityControls.m b/src/Core/Entities/PlayerEntityControls.m index 6c41d2c42..74799e190 100644 --- a/src/Core/Entities/PlayerEntityControls.m +++ b/src/Core/Entities/PlayerEntityControls.m @@ -3142,7 +3142,7 @@ sets the actual screen resolution (controller just stores { BOOL rightKeyDown = [gameView isDown:key_gui_arrow_right]; BOOL leftKeyDown = [gameView isDown:key_gui_arrow_left]; - float fov = [gameView fov:NO]; + float fov = [[NSUserDefaults standardUserDefaults] floatForKey:@"fov-value"]; float fovStep = (MAX_FOV_DEG - MIN_FOV_DEG) / 20.0f; fov += (((rightKeyDown && (fov < MAX_FOV_DEG)) ? fovStep : 0.0f) - ((leftKeyDown && (fov > MIN_FOV_DEG)) ? fovStep : 0.0f)); @@ -3156,7 +3156,7 @@ sets the actual screen resolution (controller just stores v1_string = [v1_string substringToIndex:fovTicks]; v0_string = [v0_string substringToIndex:20 - fovTicks]; [gui setText:[NSString stringWithFormat:@"%@%@%@ (%d%c) ", fovWordDesc, v1_string, v0_string, (int)fov, 176 /*176 is the degrees symbol ASCII code*/] forRow:GUI_ROW(GAME,FOV) align:GUI_ALIGN_CENTER]; - [[NSUserDefaults standardUserDefaults] setFloat:[gameView fov:NO] forKey:@"fov-value"]; + [[NSUserDefaults standardUserDefaults] setFloat:fov forKey:@"fov-value"]; timeLastKeyPress = script_time; } fovControlPressed = YES; From ef6b61b30cbd7fbf14331c16f2f0305f2f88ad84 Mon Sep 17 00:00:00 2001 From: Day Date: Wed, 22 Apr 2015 22:45:45 +0200 Subject: [PATCH 3/4] Standard fov in fraction (not in degrees) is now 1.0. Removes magic numbers. --- src/Cocoa/MyOpenGLView.h | 4 ++-- src/Cocoa/MyOpenGLView.m | 4 ++-- src/Core/HeadUpDisplay.m | 4 ++-- src/Core/Universe.m | 4 ++-- src/SDL/MyOpenGLView.h | 4 ++-- src/SDL/MyOpenGLView.m | 4 ++-- 6 files changed, 12 insertions(+), 12 deletions(-) diff --git a/src/Cocoa/MyOpenGLView.h b/src/Cocoa/MyOpenGLView.h index f2befb25a..374caa8fe 100644 --- a/src/Cocoa/MyOpenGLView.h +++ b/src/Cocoa/MyOpenGLView.h @@ -35,8 +35,8 @@ MA 02110-1301, USA. #define MIN_FOV_DEG 30.0f #define MAX_FOV_DEG 80.0f -#define MIN_FOV (tan((MIN_FOV_DEG / 2) * M_PI / 180.0f)) -#define MAX_FOV (tan((MAX_FOV_DEG / 2) * M_PI / 180.0f)) +#define MIN_FOV (2 * tan((MIN_FOV_DEG / 2) * M_PI / 180.0f)) +#define MAX_FOV (2 * tan((MAX_FOV_DEG / 2) * M_PI / 180.0f)) #define NUM_KEYS 320 #define MOUSE_DOUBLE_CLICK_INTERVAL 0.40 diff --git a/src/Cocoa/MyOpenGLView.m b/src/Cocoa/MyOpenGLView.m index 1fbf62393..d63ea963f 100644 --- a/src/Cocoa/MyOpenGLView.m +++ b/src/Cocoa/MyOpenGLView.m @@ -1229,13 +1229,13 @@ - (float) gammaValue - (void) setFov:(float)value fromFraction:(BOOL)fromFraction { - _fov = fromFraction ? value : tan((value / 2) * M_PI / 180); + _fov = fromFraction ? value : 2 * tan((value / 2) * M_PI / 180); } - (float) fov:(BOOL)inFraction { - return inFraction ? _fov : 2 * atan(_fov) * 180 / M_PI; + return inFraction ? _fov : 2 * atan(_fov / 2) * 180 / M_PI; } @end diff --git a/src/Core/HeadUpDisplay.m b/src/Core/HeadUpDisplay.m index afbb09884..cd5ff14ff 100644 --- a/src/Core/HeadUpDisplay.m +++ b/src/Core/HeadUpDisplay.m @@ -3431,7 +3431,7 @@ static void hudDrawReticleOnTarget(Entity *target, PlayerEntity *player1, GLfloa p1 = HPVectorToVector(HPvector_subtract([target position], [player1 viewpointPosition])); GLfloat rdist = magnitude(p1); - GLfloat rsize = [target collisionRadius] / (2 * [[UNIVERSE gameView] fov:YES]); // FIXME integrate 2 into fov to remove magic number + GLfloat rsize = [target collisionRadius] / [[UNIVERSE gameView] fov:YES]; if (rsize < rdist * scale) rsize = rdist * scale; @@ -3667,7 +3667,7 @@ static void hudRotateViewpointForVirtualDepth(PlayerEntity * player1, Vector p1) // The field of view transformation is really a scale operation on the view window. // We must unapply it through these transformations for them to be right. - float ratio = 2 * [[UNIVERSE gameView] fov:YES]; // FIXME 2 is magic number; fov should integrate it + float ratio = [[UNIVERSE gameView] fov:YES]; OOGLScaleModelView(make_vector(1/ratio, 1/ratio, 1.0f)); // deal with view directions diff --git a/src/Core/Universe.m b/src/Core/Universe.m index 0190a33ad..dd25d4fa7 100644 --- a/src/Core/Universe.m +++ b/src/Core/Universe.m @@ -4406,10 +4406,10 @@ - (void) drawUniverse { float nearPlane = vdist ? 1.0 : INTERMEDIATE_CLEAR_DEPTH; float farPlane = vdist ? INTERMEDIATE_CLEAR_DEPTH : MAX_CLEAR_DEPTH; - float ratio = (displayGUI ? 0.5 : [gameView fov:YES]) * nearPlane; // 0.5 is field of view ratio for GUIs + float ratio = (displayGUI ? 1.0 : [gameView fov:YES]) * nearPlane; // 1.0 is field of view ratio for GUIs OOGLResetProjection(); - OOGLFrustum(-ratio, ratio, -aspect*ratio, aspect*ratio, nearPlane, farPlane); + OOGLFrustum(-ratio/2, ratio/2, -aspect*ratio/2, aspect*ratio/2, nearPlane, farPlane); [self getActiveViewMatrix:&view_matrix forwardVector:&view_dir upVector:&view_up]; diff --git a/src/SDL/MyOpenGLView.h b/src/SDL/MyOpenGLView.h index 21b026cae..9c284df6e 100644 --- a/src/SDL/MyOpenGLView.h +++ b/src/SDL/MyOpenGLView.h @@ -32,8 +32,8 @@ MA 02110-1301, USA. #define MIN_FOV_DEG 30.0f #define MAX_FOV_DEG 80.0f -#define MIN_FOV (tan((MIN_FOV_DEG / 2) * M_PI / 180.0f)) -#define MAX_FOV (tan((MAX_FOV_DEG / 2) * M_PI / 180.0f)) +#define MIN_FOV (2 * tan((MIN_FOV_DEG / 2) * M_PI / 180.0f)) +#define MAX_FOV (2 * tan((MAX_FOV_DEG / 2) * M_PI / 180.0f)) #define MOUSEVIRTUALSTICKSENSITIVITYFACTOR 0.95f #define MOUSEX_MAXIMUM 0.6 diff --git a/src/SDL/MyOpenGLView.m b/src/SDL/MyOpenGLView.m index fb77ccfa7..ebe016e2a 100644 --- a/src/SDL/MyOpenGLView.m +++ b/src/SDL/MyOpenGLView.m @@ -2323,13 +2323,13 @@ - (float) gammaValue - (void) setFov:(float)value fromFraction:(BOOL)fromFraction { - _fov = fromFraction ? value : tan((value / 2) * M_PI / 180); + _fov = fromFraction ? value : 2 * tan((value / 2) * M_PI / 180); } - (float) fov:(BOOL)inFraction { - return inFraction ? _fov : 2 * atan(_fov) * 180 / M_PI; + return inFraction ? _fov : 2 * atan(_fov / 2) * 180 / M_PI; } From f92d4cbd134b48087507fbf826098fea9a99d212 Mon Sep 17 00:00:00 2001 From: Day Date: Thu, 23 Apr 2015 07:53:38 +0200 Subject: [PATCH 4/4] The javascript property player.ship.viewFov is not anymore an angle in degrees, but a multiplier of oolite.fov.value, itself an angle in degrees. --- src/Core/Entities/PlayerEntity.h | 2 +- src/Core/Entities/PlayerEntity.m | 10 +++++++--- src/Core/Scripting/OOJSPlayerShip.m | 2 +- 3 files changed, 9 insertions(+), 5 deletions(-) diff --git a/src/Core/Entities/PlayerEntity.h b/src/Core/Entities/PlayerEntity.h index 1bb7879d9..95f907411 100644 --- a/src/Core/Entities/PlayerEntity.h +++ b/src/Core/Entities/PlayerEntity.h @@ -1159,7 +1159,7 @@ typedef enum */ - (GLfloat) insideAtmosphereFraction; -- (void) viewFov:(float)fovDegrees; +- (void) viewFov:(float)fovMultiplier; - (float) viewFov; @end diff --git a/src/Core/Entities/PlayerEntity.m b/src/Core/Entities/PlayerEntity.m index f905c16cd..fbb78893c 100644 --- a/src/Core/Entities/PlayerEntity.m +++ b/src/Core/Entities/PlayerEntity.m @@ -12429,14 +12429,18 @@ - (BOOL) suppressClangStuff } #endif -- (void) viewFov:(float)fovDegrees +- (void) viewFov:(float)fovMultiplier { - [[UNIVERSE gameView] setFov:fovDegrees fromFraction:NO]; + float gameOptionsFovInDegrees = [[NSUserDefaults standardUserDefaults] floatForKey:@"fov-value"]; + float gameOptionsFovInFraction = (2 * tan(gameOptionsFovInDegrees / 2 * M_PI / 180)); + [[UNIVERSE gameView] setFov:gameOptionsFovInFraction*fovMultiplier fromFraction:YES]; } - (float) viewFov { - return [[UNIVERSE gameView] fov:NO]; + float gameOptionsFovInDegrees = [[NSUserDefaults standardUserDefaults] floatForKey:@"fov-value"]; + float gameOptionsFovInFraction = (2 * tan(gameOptionsFovInDegrees / 2 * M_PI / 180)); + return [[UNIVERSE gameView] fov:YES] / gameOptionsFovInFraction; } @end diff --git a/src/Core/Scripting/OOJSPlayerShip.m b/src/Core/Scripting/OOJSPlayerShip.m index 32076184c..dd26e6ca4 100644 --- a/src/Core/Scripting/OOJSPlayerShip.m +++ b/src/Core/Scripting/OOJSPlayerShip.m @@ -146,7 +146,7 @@ kPlayerShip_viewPositionForward, // view position offset, vector, read-only kPlayerShip_viewPositionPort, // view position offset, vector, read-only kPlayerShip_viewPositionStarboard, // view position offset, vector, read-only - kPlayerShip_viewFov, // view fov in degrees, positive float, read/write + kPlayerShip_viewFov, // view fov as a multiplier of game options fov, positive float, read/write kPlayerShip_weaponsOnline, // weapons online status, boolean, read-only kPlayerShip_yaw, // yaw (overrules Ship) };