Oolite 1.91.0.7604-240417-a536cbe
Loading...
Searching...
No Matches
OOSunEntity.m
Go to the documentation of this file.
1/*
2
3OOSunEntity.m
4
5Oolite
6Copyright (C) 2004-2013 Giles C Williams and contributors
7
8This program is free software; you can redistribute it and/or
9modify it under the terms of the GNU General Public License
10as published by the Free Software Foundation; either version 2
11of the License, or (at your option) any later version.
12
13This program is distributed in the hope that it will be useful,
14but WITHOUT ANY WARRANTY; without even the implied warranty of
15MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16GNU General Public License for more details.
17
18You should have received a copy of the GNU General Public License
19along with this program; if not, write to the Free Software
20Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
21MA 02110-1301, USA.
22
23*/
24
25#import "OOSunEntity.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"
38#import "OODebugFlags.h"
39#import "OOStringExpander.h"
40
41@interface OOSunEntity (Private)
42
43- (void) calculateGLArrays:(GLfloat)inner_radius width:(GLfloat)width zDistance:(GLfloat)z_distance;
44- (void) drawOpaqueParts;
46
47@end
48
49
50@implementation OOSunEntity
51
52#ifndef NDEBUG
53- (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
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- (void) dealloc
212{
213 DESTROY(_name);
214 [super dealloc];
215}
216
217
218- (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- (BOOL) canCollide
235{
236 return YES;
237}
238
239
240#ifndef NDEBUG
241- (BOOL) checkCloseCollisionWith:(Entity *)other
242{
244 {
245 OOLog(@"sun.collide", @"%@", @"SUN Collision!");
246 }
247
248 return [super checkCloseCollisionWith:other];
249}
250#endif
251
252
253- (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- (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- (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- (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
394
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
457 OOCheckOpenGLErrors(@"SunEntity after drawing %@", self);
458}
459
460
462{
463 if ([UNIVERSE reducedDetail])
464 {
465 return;
466 }
467
469
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- (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
609
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{
646
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- (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- (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- (BOOL) isSun
811{
812 return YES;
813}
814
815
816- (BOOL) isVisible
817{
818 return YES;
819}
820
821
822- (NSString *) name
823{
824 return _name;
825}
826
827
828- (void) setName:(NSString *)name
829{
830 [_name release];
831 _name = [name retain];
832}
833
834
835@end
NSUInteger gDebugFlags
Definition main.m:7
#define NO_DRAW_DISTANCE_FACTOR
Definition Entity.h:46
#define DESTROY(x)
Definition OOCocoa.h:77
@ DEBUG_COLLISIONS
Definition OODebugFlags.h:7
#define EXPECT_NOT(x)
#define OOLogWARN(class, format,...)
Definition OOLogging.h:113
#define OOLog(class, format,...)
Definition OOLogging.h:88
#define OO_ENTER_OPENGL()
#define M_PI
Definition OOMaths.h:73
OOMatrix OOMatrixForBillboard(HPVector bbPos, HPVector eyePos)
Definition OOMatrix.m:191
#define OOGLBEGIN
Definition OOOpenGL.h:253
@ OPENGL_STATE_ADDITIVE_BLENDING
Definition OOOpenGL.h:125
@ OPENGL_STATE_OVERLAY
Definition OOOpenGL.h:126
#define OOVerifyOpenGLState()
Definition OOOpenGL.h:136
BOOL OOCheckOpenGLErrors(NSString *format,...)
Definition OOOpenGL.m:39
void GLDrawBallBillboard(GLfloat radius, GLfloat step, GLfloat z_distance)
Definition OOOpenGL.m:111
#define OOSetOpenGLState(STATE)
Definition OOOpenGL.h:135
#define OOGL(statement)
Definition OOOpenGL.h:251
#define OOGLEND
Definition OOOpenGL.h:254
return nil
OOStellarBodyType
@ STELLAR_TYPE_SUN
#define MAX_SUBDIVIDE
#define SUN_GLARE_CORONA_FACTOR
Definition OOSunEntity.h:47
#define SUN_CORONA_SAMPLES
Definition OOSunEntity.h:35
double OOTimeDelta
Definition OOTypes.h:224
#define PLAYER
#define UNIVERSE
Definition Universe.h:833
#define KEY_SUNNAME
Definition Universe.h:130
GLfloat display_z
void getHue:saturation:brightness:alpha:(float *hue,[saturation] float *saturation,[brightness] float *brightness,[alpha] float *alpha)
Definition OOColor.m:438
OOColor * colorWithRed:green:blue:alpha:(float red,[green] float green,[blue] float blue,[alpha] float alpha)
Definition OOColor.m:95
float alphaComponent()
Definition OOColor.m:486
float blueComponent()
Definition OOColor.m:362
void getRed:green:blue:alpha:(float *red,[green] float *green,[blue] float *blue,[alpha] float *alpha)
Definition OOColor.m:368
OOColor * whiteColor()
Definition OOColor.m:256
OOColor * colorWithHue:saturation:brightness:alpha:(float hue,[saturation] float saturation,[brightness] float brightness,[alpha] float alpha)
Definition OOColor.m:87
float redComponent()
Definition OOColor.m:350
OOColor * blendedColorWithFraction:ofColor:(float fraction,[ofColor] OOColor *color)
Definition OOColor.m:328
float greenComponent()
Definition OOColor.m:356
float randf(void)