LCOV - code coverage report
Current view: top level - Core/Entities - OOSunEntity.m (source / functions) Hit Total Coverage
Test: coverxygen.info Lines: 0 21 0.0 %
Date: 2025-05-28 07:50:54 Functions: 0 0 -

          Line data    Source code
       1           0 : /*
       2             : 
       3             : OOSunEntity.m
       4             : 
       5             : Oolite
       6             : Copyright (C) 2004-2013 Giles C Williams and contributors
       7             : 
       8             : This program is free software; you can redistribute it and/or
       9             : modify it under the terms of the GNU General Public License
      10             : as published by the Free Software Foundation; either version 2
      11             : of the License, or (at your option) any later version.
      12             : 
      13             : This program is distributed in the hope that it will be useful,
      14             : but WITHOUT ANY WARRANTY; without even the implied warranty of
      15             : MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      16             : GNU General Public License for more details.
      17             : 
      18             : You should have received a copy of the GNU General Public License
      19             : along with this program; if not, write to the Free Software
      20             : Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
      21             : MA 02110-1301, USA.
      22             : 
      23             : */
      24             : 
      25             : #import "OOSunEntity.h"
      26             : #import "OOOpenGLExtensionManager.h"
      27             : #import "OOMacroOpenGL.h"
      28             : 
      29             : #import "Universe.h"
      30             : #import "AI.h"
      31             : #import "MyOpenGLView.h"
      32             : #import "ShipEntityAI.h"
      33             : #import "OOColor.h"
      34             : #import "OOCharacter.h"
      35             : #import "OOStringParsing.h"
      36             : #import "PlayerEntity.h"
      37             : #import "OOCollectionExtractors.h"
      38             : #import "OODebugFlags.h"
      39             : #import "OOStringExpander.h"
      40             : 
      41             : @interface OOSunEntity (Private)
      42             : 
      43           0 : - (void) calculateGLArrays:(GLfloat)inner_radius width:(GLfloat)width zDistance:(GLfloat)z_distance;
      44           0 : - (void) drawOpaqueParts;
      45           0 : - (void) drawTranslucentParts;
      46             : 
      47             : @end
      48             : 
      49             : 
      50             : @implementation OOSunEntity
      51             : 
      52             : #ifndef NDEBUG
      53           0 : - (id) init
      54             : {
      55             :         assert(0);
      56             :         return nil;
      57             : }
      58             : #endif
      59             : 
      60             : 
      61             : - (BOOL) setSunColor:(OOColor*)sun_color
      62             : {
      63             :         if (sun_color == nil) return NO;
      64             :         
      65             :         OO_ENTER_OPENGL();
      66             :         
      67             :         float           hue, sat, bri, alf;
      68             :         OOColor         *color = nil;
      69             :         
      70             :         // blend some white into the sun color to brighten it up
      71             :         sun_color = [sun_color blendedColorWithFraction:0.3 ofColor:[OOColor whiteColor]];
      72             :         
      73             :         [sun_color getHue:&hue saturation:&sat brightness:&bri alpha:&alf];
      74             :         hue /= 360;
      75             :         
      76             : /*
      77             :         // FIXME: do away with hue_drift altogether?
      78             :         // The following two lines are functionally identical to 1.73:
      79             :         randf();randf();        // avoid ranrot dirft!
      80             :         float hue_drift = 0.0f;
      81             : */
      82             :         
      83             :         // anything more than a minimal hue drift will wipe out the original colour.
      84             :         float hue_drift = 0.0038f * fabsf(randf() - randf());
      85             :         
      86             :         // set the lighting color for the sun
      87             :         GLfloat         r,g,b,a;
      88             :         [sun_color getRed:&r green:&g blue:&b alpha:&a];
      89             :         
      90             :         GLfloat         sun_ambient[] = { 0.0, 0.0, 0.0, 1.0};  // real ambient light inside gl_LightModel.ambient
      91             :         sun_diffuse[0] = 0.5f * (1.0f + r);     // paler
      92             :         sun_diffuse[1] = 0.5f * (1.0f + g);     // paler
      93             :         sun_diffuse[2] = 0.5f * (1.0f + b);     // paler
      94             :         sun_diffuse[3] = 1.0;
      95             :         sun_specular[0] = r;
      96             :         sun_specular[1] = g;
      97             :         sun_specular[2] = b;
      98             :         sun_specular[3] = 1.0;
      99             :         
     100             :         OOGL(glLightfv(GL_LIGHT1, GL_AMBIENT, sun_ambient));
     101             :         OOGL(glLightfv(GL_LIGHT1, GL_DIFFUSE, sun_diffuse));
     102             :         OOGL(glLightfv(GL_LIGHT1, GL_SPECULAR, sun_specular));
     103             :         
     104             :         // main disc less saturation (partially taken care of by the ACES tonemapper) more brightness
     105             :         color = [OOColor colorWithHue:hue saturation:sat * 0.75f brightness:1.0f alpha:1.0f];
     106             :         // our OpenGL color values are unclamped, so we can multiply the color components by
     107             :         // any value we want, in order to make the sun a truly bright object in the sky
     108             :         color = [OOColor colorWithRed:[color redComponent] * _sunBrightnessFactor green:[color greenComponent] * _sunBrightnessFactor blue:[color blueComponent] * _sunBrightnessFactor alpha:[color alphaComponent]];
     109             :         [color getRed:&discColor[0] green:&discColor[1] blue:&discColor[2] alpha:&discColor[3]];
     110             :         
     111             :         /*      Two inner corona layers with low alpha and saturation are additively
     112             :                 blended with main corona. This produces something vaguely like a bloom
     113             :                 effect.
     114             :         */
     115             :         hue += hue_drift * 3;
     116             :         // saturation = 1 would shift white to red
     117             :         color = [OOColor colorWithHue:hue saturation:OOClamp_0_1_f(sat*1.0f) brightness:bri * 0.75f alpha:0.45f];
     118             :         color = [OOColor colorWithRed:[color redComponent] * _sunBrightnessFactor green:[color greenComponent] * _sunBrightnessFactor blue:[color blueComponent] * _sunBrightnessFactor alpha:[color alphaComponent]];
     119             :         [color getRed:&outerCoronaColor[0] green:&outerCoronaColor[1] blue:&outerCoronaColor[2] alpha:&outerCoronaColor[3]];
     120             :         
     121             :         return YES;
     122             : }
     123             : 
     124             : 
     125             : - (id) initSunWithColor:(OOColor *)sun_color andDictionary:(NSDictionary *) dict
     126             : {
     127             :         int                     i;
     128             :         
     129             :         self = [super init];
     130             :         
     131             :         collision_radius = 100000.0; //  100km across
     132             :         
     133             :         scanClass = CLASS_NO_DRAW;
     134             :         
     135             :         _sunBrightnessFactor = [[NSUserDefaults standardUserDefaults] oo_floatForKey:@"sbf" defaultValue:80.0f];
     136             :         _sunCoronaAlphaFactor = [[NSUserDefaults standardUserDefaults] oo_floatForKey:@"scaf" defaultValue:0.005f];
     137             :         
     138             :         [self setSunColor:sun_color];
     139             : 
     140             :         [self setName:OOExpand([dict oo_stringForKey:KEY_SUNNAME defaultValue:@"[oolite-default-star-name]"])];
     141             :         
     142             :         corona_blending=OOClamp_0_1_f([dict oo_floatForKey:@"corona_hues" defaultValue:1.0f]);
     143             :         corona_speed_factor=[dict oo_floatForKey:@"corona_shimmer" defaultValue:-1.0];
     144             :         if(corona_speed_factor<0)
     145             :         {
     146             :                 // from .22222 to 2
     147             :                 corona_speed_factor = 1.0 / (0.5 + 2.0 * (randf() + randf()));
     148             :         }
     149             :         else
     150             :         {
     151             :                 //on average:  0 = .25 , 1 = 2.25  -  the same sun should give the same random component
     152             :                 corona_speed_factor=OOClamp_0_1_f(corona_speed_factor) * 2.0 + randf() * randf();
     153             :         }
     154             : #ifdef OO_DUMP_PLANETINFO
     155             :         OOLog(@"planetinfo.record",@"corona_shimmer = %f",corona_speed_factor);
     156             : #endif
     157             : 
     158             :         corona_stage = 0.0;
     159             :         for (i = 0; i < SUN_CORONA_SAMPLES; i++)
     160             :                 rvalue[i] = randf();
     161             :         
     162             :         // set up the radius properties
     163             :         [self changeSunProperty:@"sun_radius" withDictionary:dict];
     164             :         
     165             :         unsigned k = 0;
     166             :         for (unsigned i=0 ; i < 360 ; i++)
     167             :         {
     168             :                 unsigned j = (i+1)%360;
     169             : // disc
     170             :                 sunTriangles[k++] = 0;
     171             :                 sunTriangles[k++] = 1+i;
     172             :                 sunTriangles[k++] = 1+j;
     173             :         }
     174             :         for (unsigned i=0 ; i < 360 ; i++)
     175             :         {
     176             :                 unsigned j = (i+1)%360;
     177             : // ring 1
     178             :                 sunTriangles[k++] = 1+i;
     179             :                 sunTriangles[k++] = 1+j;
     180             :                 sunTriangles[k++] = 361+i;
     181             :                 sunTriangles[k++] = 1+j;
     182             :                 sunTriangles[k++] = 361+i;
     183             :                 sunTriangles[k++] = 361+j;
     184             : // ring 2
     185             :                 sunTriangles[k++] = 361+i;
     186             :                 sunTriangles[k++] = 361+j;
     187             :                 sunTriangles[k++] = 721+i;
     188             :                 sunTriangles[k++] = 361+j;
     189             :                 sunTriangles[k++] = 721+i;
     190             :                 sunTriangles[k++] = 721+j;
     191             : // ring 3
     192             :                 sunTriangles[k++] = 721+i;
     193             :                 sunTriangles[k++] = 721+j;
     194             :                 sunTriangles[k++] = 1081+i;
     195             :                 sunTriangles[k++] = 721+j;
     196             :                 sunTriangles[k++] = 1081+i;
     197             :                 sunTriangles[k++] = 1081+j;
     198             : // ring 4
     199             :                 sunTriangles[k++] = 1081+i;
     200             :                 sunTriangles[k++] = 1081+j;
     201             :                 sunTriangles[k++] = 1441+i;
     202             :                 sunTriangles[k++] = 1081+j;
     203             :                 sunTriangles[k++] = 1441+i;
     204             :                 sunTriangles[k++] = 1441+j;
     205             :         }
     206             : 
     207             :         return self;
     208             : }
     209             : 
     210             : 
     211           0 : - (void) dealloc
     212             : {
     213             :         DESTROY(_name);
     214             :         [super dealloc];
     215             : }
     216             : 
     217             : 
     218           0 : - (NSString*) descriptionComponents
     219             : {
     220             :         NSString *result = [NSString stringWithFormat:@"ID: %u position: %@ radius: %.3fkm", [self universalID], HPVectorDescription([self position]), 0.001 * [self radius]];
     221             :         if ([self goneNova])
     222             :         {
     223             :                 result = [result stringByAppendingString:@" (gone nova)"];
     224             :         }
     225             :         else if ([self willGoNova])
     226             :         {
     227             :                 result = [result stringByAppendingString:@" (will go nova)"];
     228             :         }
     229             :         
     230             :         return result;
     231             : }
     232             : 
     233             : 
     234           0 : - (BOOL) canCollide
     235             : {
     236             :         return YES;
     237             : }
     238             : 
     239             : 
     240             : #ifndef NDEBUG
     241           0 : - (BOOL) checkCloseCollisionWith:(Entity *)other
     242             : {
     243             :         if (gDebugFlags & DEBUG_COLLISIONS)
     244             :         {
     245             :                 OOLog(@"sun.collide", @"%@", @"SUN Collision!");
     246             :         }
     247             :         
     248             :         return [super checkCloseCollisionWith:other];
     249             : }
     250             : #endif
     251             : 
     252             : 
     253           0 : - (void) update:(OOTimeDelta) delta_t
     254             : {
     255             :         [super update:delta_t];
     256             :         
     257             :         PlayerEntity    *player = PLAYER;
     258             :         assert(player != nil);
     259             :         rotMatrix = OOMatrixForBillboard(position, [player viewpointPosition]);
     260             :         
     261             :         if (throw_sparks && _novaExpansionRate > 0.0f)       // going NOVA!
     262             :         {
     263             :                 if (_novaCountdown >= 0.0)   // countdown
     264             :                 {
     265             :                         _novaCountdown -= delta_t;
     266             :                         if (corona_speed_factor < 5.0)
     267             :                         {
     268             :                                 corona_speed_factor += 0.75 * delta_t;
     269             :                         }
     270             :                 }
     271             :                 else
     272             :                 {
     273             :                         if (_novaExpansionTimer <= 60.0)     // expand for a minute
     274             :                         {
     275             :                                 double sky_bri = 1.0 - 1.5 * _novaExpansionTimer;
     276             :                                 if (sky_bri < 0)
     277             :                                 {
     278             :                                         [UNIVERSE setSkyColorRed:0.0f           // back to black
     279             :                                                                            green:0.0f
     280             :                                                                                 blue:0.0f
     281             :                                                                            alpha:0.0f];
     282             :                                 }
     283             :                                 else
     284             :                                 {
     285             :                                         [UNIVERSE setSkyColorRed:sky_bri        // whiteout
     286             :                                                                            green:sky_bri
     287             :                                                                                 blue:sky_bri
     288             :                                                                            alpha:1.0f];
     289             :                                 }
     290             :                                 if (sky_bri == 1.0)
     291             :                                 {       
     292             :                                         // This sun has now gone nova!
     293             :                                         [UNIVERSE setSystemDataKey:@"sun_gone_nova" value:[NSNumber numberWithBool:YES] fromManifest:@"org.oolite.oolite"];
     294             :                                         [UNIVERSE setSystemDataKey:@"corona_flare" value:[NSNumber numberWithFloat:0.3] fromManifest:@"org.oolite.oolite"];
     295             :                                         [UNIVERSE setSystemDataKey:@"corona_hues" value:[NSNumber numberWithFloat:0.05] fromManifest:@"org.oolite.oolite"];
     296             :                                         // Novas are stored under the core manifest if the
     297             :                                         // player was there at the time. Default layer 2
     298             :                                         // is fine.
     299             :                                         OOLog(@"sun.nova.start", @"DEBUG: NOVA original radius %.1f", collision_radius);
     300             :                                 }
     301             :                                 discColor[0] = 1.0 * _sunBrightnessFactor;      discColor[1] = 1.0 * _sunBrightnessFactor;      discColor[2] = 1.0 * _sunBrightnessFactor;
     302             :                                 _novaExpansionTimer += delta_t;
     303             :                                 [UNIVERSE setSystemDataKey:@"sun_radius" value:[NSNumber numberWithFloat:collision_radius + delta_t * _novaExpansionRate] fromManifest:@"org.oolite.oolite"];
     304             :                         }
     305             :                         else
     306             :                         {
     307             :                                 OOLog(@"sun.nova.end", @"DEBUG: NOVA final radius %.1f", collision_radius);
     308             :                                 
     309             :                                 // reset at the new size
     310             :                                 [self resetNova];
     311             :                                 throw_sparks = YES;     // keep throw_sparks at YES to indicate the higher temperature
     312             :                         }
     313             :                 }
     314             :         }
     315             :         
     316             :         // update corona
     317             :         if (![UNIVERSE reducedDetail])
     318             :         {
     319             :                 corona_stage += corona_speed_factor * delta_t;
     320             :                 while (corona_stage > 1.0)
     321             :                 {
     322             :                         int i;
     323             :                         corona_stage -= 1.0;
     324             :                         for (i = 0; i < 360; i++)
     325             :                         {
     326             :                                 rvalue[i] = rvalue[360 + i];
     327             :                                 rvalue[360 + i] = randf();
     328             :                         }
     329             :                 }
     330             :         }
     331             : 
     332             : }
     333             : 
     334             : 
     335             : 
     336           0 : - (void) drawImmediate:(bool)immediate translucent:(bool)translucent
     337             : {
     338             :         if (![UNIVERSE breakPatternHide])
     339             :         {
     340             :                 if (translucent)
     341             :                 {
     342             :                         // nothing...
     343             :                 }
     344             :                 else
     345             :                 {
     346             :                         [self drawOpaqueParts];
     347             :                         /* Despite the side effects, we have to draw the translucent
     348             :                          * parts on the opaque pass. Planets, at long range, aren't
     349             :                          * depth-buffered. So if the translucent parts are drawn on the
     350             :                          * translucent pass, they appear in front of planets they are
     351             :                          * actually behind. Telabe in G3 is a good one to test with if
     352             :                          * you have any clever ideas.
     353             :                          *
     354             :                          * - CIM 8/7/2013 */
     355             :                         [self drawTranslucentParts];
     356             :                 }
     357             :         }
     358             : }
     359             : 
     360             : 
     361           0 : - (void) updateCameraRelativePosition
     362             : {
     363             :         HPVector cr_temp = HPvector_subtract([self absolutePositionForSubentity],[PLAYER viewpointPosition]);
     364             :         /* Special calculation as suns viewed over ~1E9 - and the bigger
     365             :          * ones are still just about visible at this range - get floating
     366             :          * point errors messing up the display */
     367             :         if (EXPECT_NOT(HPmagnitude2(cr_temp) > 1E18))
     368             :         {
     369             :                 cr_temp = HPvector_multiply_scalar(cr_temp,1E9/HPmagnitude(cr_temp));
     370             :         }
     371             :         cameraRelativePosition = HPVectorToVector(cr_temp);
     372             : }
     373             : 
     374             : 
     375           0 : - (void) drawOpaqueParts
     376             : {
     377             :         float sqrt_zero_distance = sqrt(cam_zero_distance);
     378             :         float effective_radius = collision_radius;
     379             :         float effective_cor16k = cor16k;
     380             : 
     381             :         /* At very long ranges the floating point inaccuracies make a
     382             :          * complete mess of the calculations, so if the sun is more than
     383             :          * 1E9 away, draw it closer but smaller. Painter's algorithm
     384             :          * should stop oddities with planets transiting it */
     385             :         float large_distance_compensator = sqrt_zero_distance / 1000000000.0f; //1E9
     386             :         if (large_distance_compensator > 1.0f)
     387             :         {
     388             :                 sqrt_zero_distance /= large_distance_compensator;
     389             :                 effective_radius /= large_distance_compensator;
     390             :                 effective_cor16k /= large_distance_compensator;
     391             :         }
     392             : 
     393             :         OO_ENTER_OPENGL();
     394             :         
     395             :         OOSetOpenGLState(OPENGL_STATE_ADDITIVE_BLENDING);
     396             : 
     397             :         if ([UNIVERSE reducedDetail])
     398             :         {       
     399             :                 int subdivideLevel = 2;         // 4 is probably the maximum!
     400             :                 float drawFactor = [[UNIVERSE gameView] viewSize].width / 100.0;
     401             :                 float drawRatio2 = drawFactor * effective_radius / sqrt_zero_distance; // equivalent to size on screen in pixels
     402             :         
     403             :                 if (cam_zero_distance > 0.0f)
     404             :                 {
     405             :                         subdivideLevel = 2 + floorf(drawRatio2);
     406             :                         if (subdivideLevel > 4)
     407             :                                 subdivideLevel = 4;
     408             :                 }
     409             :         
     410             :         /*
     411             :          
     412             :         The depth test gets disabled in parts of this and instead
     413             :         we rely on the painters algorithm instead.
     414             :          
     415             :         The depth buffer isn't granular enough to cope with huge objects at vast
     416             :         distances.
     417             :          
     418             :         */
     419             :                 BOOL ignoreDepthBuffer = cam_zero_distance > effective_radius * effective_radius * 25;
     420             :         
     421             :                 int steps = 2 * (MAX_SUBDIVIDE - subdivideLevel);
     422             : 
     423             :                 // Close enough not to draw flat?
     424             :                 if (ignoreDepthBuffer)  OOGL(glDisable(GL_DEPTH_TEST));
     425             :                 
     426             :                 OOGL(glColor3fv(discColor));
     427             :                 // FIXME: use vertex arrays
     428             :                 OOGL(glDisable(GL_BLEND));
     429             :                 OOGLBEGIN(GL_TRIANGLE_FAN);
     430             :                 GLDrawBallBillboard(effective_radius, steps, sqrt_zero_distance);
     431             :                 OOGLEND();
     432             :                 OOGL(glEnable(GL_BLEND));
     433             : 
     434             :                 if (ignoreDepthBuffer)  OOGL(glEnable(GL_DEPTH_TEST)); 
     435             :         
     436             :         }
     437             :         else
     438             :         {
     439             :                 [self calculateGLArrays:effective_radius
     440             :                                                   width:effective_cor16k
     441             :                                           zDistance:sqrt_zero_distance];
     442             :                 OOGL(glDisable(GL_BLEND));
     443             :                 OOGL(glVertexPointer(3, GL_FLOAT, 0, sunVertices));
     444             :                 
     445             :                 OOGL(glEnableClientState(GL_COLOR_ARRAY));
     446             :                 OOGL(glColorPointer(4, GL_FLOAT, 0, sunColors));
     447             :                 
     448             :                 OOGL(glDrawElements(GL_TRIANGLES, 3*360, GL_UNSIGNED_INT, sunTriangles));
     449             : 
     450             :                 OOGL(glDisableClientState(GL_COLOR_ARRAY));
     451             :                 OOGL(glEnable(GL_BLEND));
     452             : 
     453             :                 
     454             :         }
     455             :         
     456             :         OOVerifyOpenGLState();
     457             :         OOCheckOpenGLErrors(@"SunEntity after drawing %@", self);
     458             : }
     459             : 
     460             : 
     461           0 : - (void) drawTranslucentParts
     462             : {
     463             :         if ([UNIVERSE reducedDetail]) 
     464             :         {
     465             :                 return;
     466             :         }
     467             :         
     468             :         OO_ENTER_OPENGL();
     469             :         
     470             :         OOSetOpenGLState(OPENGL_STATE_ADDITIVE_BLENDING);
     471             : 
     472             :         OOGL(glVertexPointer(3, GL_FLOAT, 0, sunVertices));
     473             : 
     474             :         OOGL(glEnableClientState(GL_COLOR_ARRAY));
     475             :         OOGL(glColorPointer(4, GL_FLOAT, 0, sunColors));
     476             :         OOGL(glDrawElements(GL_TRIANGLES, 24*360, GL_UNSIGNED_INT, sunTriangles+(3*360)));
     477             : 
     478             :         OOGL(glDisableClientState(GL_COLOR_ARRAY));
     479             : 
     480             : 
     481             : }
     482             : 
     483           0 : - (void) calculateGLArrays:(GLfloat)inner_radius width:(GLfloat)width zDistance:(GLfloat)z_distance
     484             : {
     485             : //      if (EXPECT_NOT(inner_radius >= z_distance))  return; // inside the sphere
     486             :         
     487             :         GLfloat activity[8] = {0.84, 0.74, 0.64, 0.54, 
     488             :                                                                                                  0.3 , 0.4 , 0.7 , 0.8};
     489             :         
     490             :         GLfloat                         si, ci;
     491             :         GLfloat                         rv0, rv1, rv2, c0, c1, c2;
     492             :         GLfloat                         pt0, pt1; 
     493             :         
     494             :         unsigned short          i, j, k;
     495             :         GLfloat                         theta = 0.0f, delta;
     496             :         delta = M_PI / 180.0f;  // Convert step from degrees to radians
     497             :         pt0=(1.0 - corona_stage) * corona_blending;
     498             :         pt1=corona_stage * corona_blending;
     499             : 
     500             :         sunVertices[0] = 0.0;
     501             :         sunVertices[1] = 0.0;
     502             :         sunVertices[2] = 0.0;
     503             :         k = 3;
     504             :         for (j = 0 ; j <= 4 ; j++)
     505             :         {
     506             :                 GLfloat r = inner_radius;
     507             :                 switch (j) {
     508             :                 case 4:
     509             :                         r += width;
     510             :                         break;
     511             :                 case 3:
     512             :                         r += width/1.5f;
     513             :                         break;
     514             :                 case 2:
     515             :                         r += width/3.0f;
     516             :                         break;
     517             :                 case 1:
     518             :                                 r += width/15.0f;
     519             :                         break;
     520             :                 }
     521             :                 theta = 0.0;
     522             :                 for (i = 0 ; i < 360 ; i++)
     523             :                 {
     524             :                         GLfloat rm = 1.0;
     525             :                         if (j >= 1 && j < 4)
     526             :                         {
     527             :                                 rm = 1.0 + ((0.04/j)*(pt0 * (rvalue[i]+rvalue[i+1]+rvalue[i+2]) + pt1 * (rvalue[i+360]+rvalue[i+361]+rvalue[i+362])))/3;
     528             :                         }
     529             :                         GLfloat z = r * r * rm * rm / z_distance;
     530             :                         si = sinf(theta);
     531             :                         ci = cosf(theta);
     532             :                         theta += delta;
     533             :                         sunVertices[k++] = si * r * rm;
     534             :                         sunVertices[k++] = ci * r * rm;
     535             :                         sunVertices[k++] = -z;
     536             :                 }
     537             :         }
     538             : 
     539             :         GLfloat blackColor[4] = {0.0,0.0,0.0,0.0};
     540             :         GLfloat *color = blackColor;
     541             :         GLfloat alpha = 0.0;
     542             : 
     543             :         k=0;
     544             :         sunColors[k++] = discColor[0];
     545             :         sunColors[k++] = discColor[1];
     546             :         sunColors[k++] = discColor[2];
     547             :         sunColors[k++] = discColor[3] * _sunCoronaAlphaFactor;
     548             :         
     549             :         for (j = 0 ; j <= 4 ; j++)
     550             :         {
     551             :                 switch (j) {
     552             :                 case 4:
     553             :                         color = blackColor;
     554             :                         alpha = 0.0;
     555             :                         break;
     556             :                 case 3:
     557             :                         color = outerCoronaColor;
     558             :                         alpha = 0.1;
     559             :                         break;
     560             :                 case 2:
     561             :                         color = outerCoronaColor;
     562             :                         alpha = 0.6;
     563             :                         break;
     564             :                 case 1:
     565             :                         color = discColor;
     566             :                         alpha = 0.95;
     567             :                         break;
     568             :                 case 0:
     569             :                         color = discColor;
     570             :                         alpha = 1.0;
     571             :                         break;
     572             :                 }
     573             :                 for (i = 0 ; i < 360 ; i++)
     574             :                 {
     575             :                         if (j == 0) 
     576             :                         {
     577             :                                 sunColors[k++] = color[0];
     578             :                                 sunColors[k++] = color[1];
     579             :                                 sunColors[k++] = color[2];
     580             :                                 sunColors[k++] = alpha * _sunCoronaAlphaFactor;
     581             :                         }
     582             :                         else
     583             :                         {
     584             :                                 rv0 = pt0 * rvalue[i] + pt1 * rvalue[i + 360];
     585             :                                 rv1 = pt0 * rvalue[i + 1] + pt1 * rvalue[i + 361];
     586             :                                 rv2 = pt0 * rvalue[i + 2] + pt1 * rvalue[i + 362];
     587             :                                 c0 = color[0] * (activity[j-1] + rv0*activity[j+3]);
     588             :                                 c1 = color[1] * (activity[j-1] + rv1*activity[j+3]);
     589             :                                 c2 = color[2] * (activity[j-1] + rv2*activity[j+3]);
     590             :                                 if (c1 > c2 && c1 > c0)
     591             :                                 {
     592             :                                         c1 = fmaxf(c0,c2);
     593             :                                 }
     594             : 
     595             :                                 sunColors[k++] = c0;
     596             :                                 sunColors[k++] = c1;
     597             :                                 sunColors[k++] = c2;
     598             :                                 sunColors[k++] = alpha * _sunCoronaAlphaFactor;
     599             :                         }       
     600             :                 }
     601             :         }
     602             : }
     603             : 
     604             : 
     605             : - (void) drawDirectVisionSunGlare
     606             : {
     607             : #if SUN_DIRECT_VISION_GLARE
     608             :         OO_ENTER_OPENGL();
     609             :         
     610             :         OOSetOpenGLState(OPENGL_STATE_OVERLAY);
     611             :         
     612             :         GLfloat sunGlareAngularSize = atan([self radius]/HPdistance([PLAYER viewpointPosition], [self position])) * SUN_GLARE_MULT_FACTOR + (SUN_GLARE_ADD_FACTOR);
     613             : 
     614             :         GLfloat directVisionSunGlare = [PLAYER lookingAtSunWithThresholdAngleCos:cosf(sunGlareAngularSize)];
     615             :         if (directVisionSunGlare)
     616             :         {
     617             :                 NSSize  siz =   [[UNIVERSE gui] size];
     618             :                 MyOpenGLView *gameView = [UNIVERSE gameView];
     619             :                 GLfloat aspectRatio = ([gameView viewSize].width / [gameView viewSize].height);
     620             :                 GLfloat z  = [gameView display_z] / (aspectRatio > 4.0f/3.0f ? aspectRatio : 1.0f / aspectRatio);
     621             :                 GLfloat atmosphericReductionFactor =  1.0f - [PLAYER insideAtmosphereFraction];
     622             :                 // 182: square of ratio of radius to sun-witchpoint distance
     623             :                 // in default Lave
     624             :                 GLfloat distanceReductionFactor = OOClamp_0_1_f(([self radius] * [self radius] * 182.0) / HPdistance2([PLAYER position], [self position]));
     625             :                 GLfloat sunGlareFilterMultiplierLocal = [PLAYER sunGlareFilter];
     626             :                 GLfloat directVisionSunGlareColor[4] = {discColor[0], discColor[1], discColor[2], directVisionSunGlare *
     627             :                                                                                                         atmosphericReductionFactor * distanceReductionFactor * 
     628             :                                                                                                         (1.0f - sunGlareFilterMultiplierLocal) * 0.0085f};
     629             :                                                                                                         
     630             :                 OOGL(glColor4fv(directVisionSunGlareColor));
     631             :                 
     632             :                 OOGLBEGIN(GL_QUADS);
     633             :                 glVertex3f(siz.width, siz.height, z);
     634             :                 glVertex3f(siz.width, -siz.height, z);
     635             :                 glVertex3f(-siz.width, -siz.height, z);
     636             :                 glVertex3f(-siz.width, siz.height, z);
     637             :                 OOGLEND();
     638             :         }
     639             : #endif
     640             : }
     641             : 
     642             : 
     643             : - (void) drawStarGlare
     644             : {
     645             :         OO_ENTER_OPENGL();
     646             : 
     647             :         OOSetOpenGLState(OPENGL_STATE_OVERLAY);
     648             :         
     649             :         float sqrt_zero_distance = sqrtf(cam_zero_distance);
     650             :         float alt = sqrt_zero_distance - collision_radius;
     651             :         if (EXPECT_NOT(alt < 0))
     652             :         {
     653             :                 return;
     654             :         }
     655             :         float corona = cor16k/SUN_GLARE_CORONA_FACTOR;
     656             :         if (corona > alt)
     657             :         {
     658             :                 float alpha = (1-(alt/corona));
     659             :                 float alphaMult = _sunCoronaAlphaFactor * alpha;
     660             :                 alpha *= alphaMult;
     661             :                 GLfloat glareColor[4] = {discColor[0], discColor[1], discColor[2], alpha};
     662             :                 NSSize          siz =   [[UNIVERSE gui] size];
     663             :                 MyOpenGLView *gameView = [UNIVERSE gameView];
     664             :                 GLfloat aspectRatio = ([gameView viewSize].width / [gameView viewSize].height);
     665             :                 GLfloat z  = [gameView display_z] / (aspectRatio > 4.0f/3.0f ? aspectRatio : 1.0f / aspectRatio);
     666             :                 OOGL(glColor4fv(glareColor));
     667             : 
     668             :                 OOGLBEGIN(GL_QUADS);
     669             :                 glVertex3f(siz.width, siz.height, z);
     670             :                 glVertex3f(siz.width, -siz.height, z);
     671             :                 glVertex3f(-siz.width, -siz.height, z);
     672             :                 glVertex3f(-siz.width, siz.height, z);
     673             :                 OOGLEND();
     674             : 
     675             :         }
     676             : }
     677             : 
     678             : 
     679             : 
     680             : - (BOOL) changeSunProperty:(NSString *)key withDictionary:(NSDictionary*) dict
     681             : {
     682             :         id      object = [dict objectForKey:key];
     683             :         static GLfloat oldRadius = 0.0;
     684             :         if ([key isEqualToString:@"sun_radius"])
     685             :         {
     686             :                 oldRadius =     [object doubleValue];   // clamp corona_flare in case planetinfo.plist / savegame contains the wrong value
     687             :                 [self setRadius:oldRadius andCorona:[dict oo_floatForKey:@"corona_flare" defaultValue:0.0f]];
     688             :         }
     689             :         else if ([key isEqualToString:KEY_SUNNAME])
     690             :         {
     691             :                 [self setName:[dict oo_stringForKey:KEY_SUNNAME]];
     692             :         }
     693             :         else if ([key isEqualToString:@"corona_flare"])
     694             :         {
     695             :                 [self setRadius:collision_radius andCorona:[object floatValue]];
     696             :         }
     697             :         else if ([key isEqualToString:@"corona_shimmer"])
     698             :         {
     699             :                 corona_speed_factor=OOClamp_0_1_f([object floatValue]) * 2.0 + randf() * randf();
     700             :         }
     701             :         else if ([key isEqualToString:@"corona_hues"])
     702             :         {
     703             :                 corona_blending=OOClamp_0_1_f([object floatValue]);
     704             :         }
     705             :         else if ([key isEqualToString:@"sun_gone_nova"])
     706             :         {
     707             : 
     708             :                 if ([dict oo_boolForKey:key])
     709             :                 {
     710             :                         [self setGoingNova:YES inTime:0];
     711             :                 }
     712             :                 else
     713             :                 {
     714             :                         [self setGoingNova:NO inTime:0];
     715             :                         // oldRadius is always the radius we had before going nova...
     716             :                         [self setRadius: oldRadius andCorona:[dict oo_floatForKey:@"corona_flare" defaultValue:0.0f]];
     717             : 
     718             :                 }
     719             :         }
     720             :         else
     721             :         {
     722             :                 OOLogWARN(@"script.warning", @"Change to property '%@' not applied, will apply only after leaving this system.",key);
     723             :                 return NO;
     724             :         }
     725             :         return YES;
     726             : }
     727             : 
     728             : 
     729             : - (OOStellarBodyType) planetType
     730             : {
     731             :         return STELLAR_TYPE_SUN;
     732             : }
     733             : 
     734             : 
     735             : - (void) getDiffuseComponents:(GLfloat[4])components
     736             : {
     737             :         NSParameterAssert(components != NULL);
     738             :         memcpy(components, sun_diffuse, sizeof sun_diffuse);
     739             : }
     740             : 
     741             : 
     742             : - (void) getSpecularComponents:(GLfloat[4])components
     743             : {
     744             :         NSParameterAssert(components != NULL);
     745             :         memcpy(components, sun_specular, sizeof sun_specular);
     746             : }
     747             : 
     748             : 
     749           0 : - (double) radius
     750             : {
     751             :         return collision_radius;
     752             : }
     753             : 
     754             : 
     755             : - (void) setRadius:(GLfloat) rad andCorona:(GLfloat)corona
     756             : {
     757             :         collision_radius = rad;
     758             :         if (corona < 0.01f) {
     759             :                 corona = 0.01f;
     760             :         }
     761             :         cor16k = rad * 8 * corona;
     762             : 
     763             :         GLfloat corouter = rad * (1+(8*corona));
     764             : 
     765             :         lim16k = corouter * corouter * NO_DRAW_DISTANCE_FACTOR*NO_DRAW_DISTANCE_FACTOR;
     766             : }
     767             : 
     768             : 
     769           0 : - (void) setPosition:(HPVector) posn
     770             : {
     771             :         [super setPosition: posn];
     772             :         [UNIVERSE setMainLightPosition: HPVectorToVector(posn)];
     773             : }
     774             : 
     775             : 
     776             : - (BOOL) willGoNova
     777             : {
     778             :         return throw_sparks;
     779             : }
     780             : 
     781             : 
     782             : - (BOOL) goneNova
     783             : {
     784             :         return throw_sparks && _novaCountdown <= 0;
     785             : }
     786             : 
     787             : 
     788             : - (void) setGoingNova:(BOOL) yesno inTime:(double)interval
     789             : {
     790             :         throw_sparks = yesno;
     791             :         if (throw_sparks)
     792             :         {
     793             :                 _novaCountdown = fmax(interval, 0.0);
     794             :                 OOLog(@"script.debug.setSunNovaIn", @"NOVA activated! time until Nova : %.1f s", _novaCountdown);
     795             :         }
     796             :         
     797             :         _novaExpansionTimer = 0;
     798             :         _novaExpansionRate = 10000;
     799             : }
     800             : 
     801             : 
     802             : - (void) resetNova
     803             : {
     804             :         _novaExpansionTimer = 0.0;
     805             :         _novaExpansionRate = 0.0f;
     806             :         _novaCountdown = 0.0;
     807             : }
     808             : 
     809             : 
     810           0 : - (BOOL) isSun
     811             : {
     812             :         return YES;
     813             : }
     814             : 
     815             : 
     816           0 : - (BOOL) isVisible
     817             : {
     818             :         return YES;
     819             : }
     820             : 
     821             : 
     822           0 : - (NSString *) name
     823             : {
     824             :         return _name;
     825             : }
     826             : 
     827             : 
     828           0 : - (void) setName:(NSString *)name
     829             : {
     830             :         [_name release];
     831             :         _name = [name retain];
     832             : }
     833             : 
     834             : 
     835             : @end

Generated by: LCOV version 1.14