90- (id) initFromDictionary:(NSDictionary *)dict withAtmosphere:(BOOL)atmosphere andSeed:(
Random_Seed)seed forSystem:(
OOSystemID)systemID
92 if (dict ==
nil) dict = [NSDictionary dictionary];
96 if (
self ==
nil)
return nil;
98 scanClass = CLASS_NO_DRAW;
100 NSMutableDictionary *planetInfo = [[UNIVERSE generateSystemData:systemID] mutableCopy];
101 [planetInfo autorelease];
109 NSString *seedStr = [dict oo_stringForKey:@"seed"];
113 if (!
is_nil_seed(overrideSeed)) seed = overrideSeed;
114 else OOLogERR(
@"planet.fromDict",
@"could not interpret \"%@\
" as planet seed, using default.", seedStr);
121 [
self setName:OOExpand([dict oo_stringForKey:KEY_PLANETNAME defaultValue:[planetInfo oo_stringForKey:KEY_PLANETNAME defaultValue:@"%H"]])];
123 int radius_km = [dict oo_intForKey:KEY_RADIUS defaultValue:[planetInfo oo_intForKey:KEY_RADIUS]];
124 collision_radius = radius_km * 10.0;
125 OOTechLevelID techLevel = [dict oo_intForKey:KEY_TECHLEVEL defaultValue:[planetInfo oo_intForKey:KEY_TECHLEVEL]];
127 if (techLevel > 14) techLevel = 14;
128 _shuttlesOnGround = 1 + techLevel / 2;
129 _shuttleLaunchInterval = 3600.0 / (double)_shuttlesOnGround;
130 _lastLaunchTime = [UNIVERSE getTime] + 30.0 - _shuttleLaunchInterval;
133 int percent_land = [planetInfo oo_intForKey:@"percent_land" defaultValue:24 + (gen_rnd_number() % 48)];
134 [planetInfo setObject:[NSNumber numberWithFloat:0.01 * percent_land] forKey:@"land_fraction"];
136 int percent_ice = [planetInfo oo_intForKey:@"percent_ice" defaultValue:5];
137 [planetInfo setObject:[NSNumber numberWithFloat:0.01 * percent_ice] forKey:@"polar_fraction"];
144 _terminatorThresholdVector = [planetInfo oo_vectorForKey:@"terminator_threshold_vector" defaultValue:OO_TERMINATOR_THRESHOLD_VECTOR_DEFAULT];
148 [planetInfo setObject:[NSValue valueWithBytes:&planetNoiseSeed objCType:@encode(RANROTSeed)] forKey:@"noise_map_seed"];
152 _airColorMixRatio = 0.5f;
155 _illuminationColor = [[planetInfo objectForKey:@"illumination_color"] retain];
169 percent_land = 100 - [dict oo_intForKey:@"percent_cloud" defaultValue:100 - (3 + (gen_rnd_number() & 31)+(gen_rnd_number() & 31))];
170 [planetInfo setObject:[NSNumber numberWithFloat:0.01 * percent_land] forKey:@"cloud_fraction"];
173 _airColor = [[planetInfo objectForKey:@"air_color"] retain];
174 _airColorMixRatio = [planetInfo oo_floatForKey:@"air_color_mix_ratio"];
176 _airDensity = OOClamp_0_1_f([planetInfo oo_floatForKey:
@"air_density"]);
179 _materialParameters = [planetInfo dictionaryWithValuesForKeys:[NSArray arrayWithObjects:@"cloud_fraction", @"air_color", @"air_color_mix_ratio", @"air_density", @"cloud_color", @"polar_cloud_color", @"cloud_alpha", @"land_fraction", @"land_color", @"sea_color", @"polar_land_color", @"polar_sea_color", @"noise_map_seed", @"economy", @"polar_fraction", @"isMiniature", @"perlin_3d", @"terminator_threshold_vector", nil]];
192 _materialParameters = [planetInfo dictionaryWithValuesForKeys:[NSArray arrayWithObjects:@"land_fraction", @"land_color", @"sea_color", @"polar_land_color", @"polar_sea_color", @"noise_map_seed", @"economy", @"polar_fraction", @"isMiniature", @"perlin_3d", @"terminator_threshold_vector", @"illumination_color", nil]];
198 _normSpecMapName = [[dict oo_stringForKey:@"texture_normspec"] retain];
200 _textureName = [[dict oo_stringForKey:@"texture"] retain];
210 if ([dict objectForKey:
@"rotational_velocity"])
212 _rotationalVelocity = [dict oo_floatForKey:@"rotational_velocity" defaultValue:0.01f * randf()];
216 _rotationalVelocity = [planetInfo oo_floatForKey:@"rotation_speed" defaultValue:0.005f * randf()];
217 _rotationalVelocity *= [planetInfo oo_floatForKey:@"rotation_speed_factor" defaultValue:1.0f];
220 _atmosphereRotationalVelocity = [dict oo_floatForKey:@"atmosphere_rotational_velocity" defaultValue:0.01f * randf()];
223 energy = collision_radius * 1000.0f;
229 int deltaT = floor(fmod([
PLAYER clockTimeAdjusted], 86400));
234#ifdef OO_DUMP_PLANETINFO
235#define CPROP(PROP) OOLog(@"planetinfo.record",@#PROP " = %@;",[(OOColor *)[planetInfo objectForKey:@#PROP] descriptionComponents]);
236#define FPROP(PROP) OOLog(@"planetinfo.record",@#PROP " = %f;",[planetInfo oo_floatForKey:@"" #PROP]);
238 CPROP(illumination_color);
239 FPROP(air_color_mix_ratio);
242 FPROP(cloud_fraction);
244 FPROP(land_fraction);
245 CPROP(polar_cloud_color);
246 CPROP(polar_land_color);
247 CPROP(polar_sea_color);
249 OOLog(
@"planetinfo.record",
@"rotation_speed = %f",_rotationalVelocity);
295- (void) setUpTypeParametersWithSourceInfo:(NSDictionary *)sourceInfo targetInfo:(NSMutableDictionary *)targetInfo
297 [targetInfo oo_setBool:[sourceInfo oo_boolForKey:@"mainForLocalSystem"] forKey:@"mainForLocalSystem"];
298 [targetInfo oo_setBool:[sourceInfo oo_boolForKey:@"isMiniature"] forKey:@"isMiniature"];
303- (void) setUpTerrainParametersWithSourceInfo:(NSDictionary *)sourceInfo targetInfo:(NSMutableDictionary *)targetInfo
305 NSArray *keys = [NSArray arrayWithObjects:@"atmosphere_rotational_velocity",@"rotational_velocity",@"cloud_alpha",@"has_atmosphere",@"percent_cloud",@"percent_ice",@"percent_land",@"radius",@"seed",nil];
307 foreach (key, keys) {
308 id sval = [sourceInfo objectForKey:key];
310 [targetInfo setObject:sval forKey:key];
317- (void) setUpLandParametersWithSourceInfo:(NSDictionary *)sourceInfo targetInfo:(NSMutableDictionary *)targetInfo
319 [
self setUpColorParametersWithSourceInfo:sourceInfo targetInfo:targetInfo isAtmosphere:NO];
323- (void) setUpAtmosphereParametersWithSourceInfo:(NSDictionary *)sourceInfo targetInfo:(NSMutableDictionary *)targetInfo
325 [
self setUpColorParametersWithSourceInfo:sourceInfo targetInfo:targetInfo isAtmosphere:YES];
329- (void) setUpColorParametersWithSourceInfo:(NSDictionary *)sourceInfo targetInfo:(NSMutableDictionary *)targetInfo isAtmosphere:(BOOL)isAtmosphere
333 for (i = 0; i < 14; i++)
338 Vector landHSB, seaHSB, landPolarHSB, seaPolarHSB, illumHSB;
339 Vector terminatorThreshold;
342 landHSB = RandomHSBColor();
348 seaHSB = RandomHSBColor();
350 while (dot_product(landHSB, seaHSB) > .80f);
353 if (seaHSB.y < 0.22f) seaHSB.y = seaHSB.y * 0.3f + 0.2f;
355 if (landHSB.z > 0.66f) landHSB.z = 0.66f;
359 if (color !=
nil) landHSB = HSBColorWithColor(color);
363 if (color !=
nil) seaHSB = HSBColorWithColor(color);
367 if (color !=
nil) illumHSB = HSBColorWithColor(color);
370 NSString *illumHSBColorString = [sourceInfo oo_stringForKey:@"illumination_hsb_color"];
372 else illumHSB = HSBColorWithColor([
OOColor colorWithRed:0.8f green:0.8f blue:0.4f alpha:1.0f]);
379 landPolarHSB = HSBColorWithColor(color);
383 landPolarHSB = LighterHSBColor(landHSB);
389 seaPolarHSB = HSBColorWithColor(color);
393 seaPolarHSB = LighterHSBColor(seaHSB);
396 [targetInfo setObject:ColorWithHSBColor(landHSB) forKey:@"land_color"];
397 [targetInfo setObject:ColorWithHSBColor(seaHSB) forKey:@"sea_color"];
398 [targetInfo setObject:ColorWithHSBColor(landPolarHSB) forKey:@"polar_land_color"];
399 [targetInfo setObject:ColorWithHSBColor(seaPolarHSB) forKey:@"polar_sea_color"];
400 [targetInfo setObject:ColorWithHSBColor(illumHSB) forKey:@"illumination_color"];
404 landHSB = RandomHSBColor();
407 seaHSB = vector_add(landHSB,((Vector){1.333, 0.6, 2}));
408 scale_vector(&seaHSB, 0.333);
410 float cloudAlpha = OOClamp_0_1_f([sourceInfo oo_floatForKey:
@"cloud_alpha" defaultValue:1.0f]);
411 [targetInfo setObject:[NSNumber numberWithFloat:cloudAlpha] forKey:@"cloud_alpha"];
415 if (color !=
nil) seaHSB = HSBColorWithColor(color);
418 if (color !=
nil) landHSB = HSBColorWithColor(color);
421 landPolarHSB = vector_add(landHSB,LighterHSBColor(landHSB));
422 scale_vector(&landPolarHSB, 0.5);
425 if (color !=
nil) landPolarHSB = HSBColorWithColor(color);
427 [targetInfo setObject:ColorWithHSBColor(seaHSB) forKey:@"air_color"];
428 [targetInfo setObject:ColorWithHSBColor(landHSB) forKey:@"cloud_color"];
429 [targetInfo setObject:ColorWithHSBColor(landPolarHSB) forKey:@"polar_cloud_color"];
430 [targetInfo setObject:[NSNumber numberWithFloat:[sourceInfo oo_floatForKey:@"air_color_mix_ratio"]] forKey:@"air_color_mix_ratio"];
432 terminatorThreshold = [sourceInfo oo_vectorForKey:@"terminator_threshold_vector" defaultValue:OO_TERMINATOR_THRESHOLD_VECTOR_DEFAULT];
433 [targetInfo setObject:[NSString stringWithFormat:@"%f %f %f", terminatorThreshold.x, terminatorThreshold.y, terminatorThreshold.z] forKey:@"terminator_threshold_vector"];
447 if (
self ==
nil)
return nil;
449 scanClass = CLASS_NO_DRAW;
450 [
self setStatus:STATUS_COCKPIT_DISPLAY];
456 _rotationalVelocity = 0.04;
462 _planetDrawable = [planet->_planetDrawable copy];
463 [_planetDrawable setRadius:collision_radius];
466 _atmosphereDrawable = [planet->_atmosphereDrawable copy];
467 _cloudsShaderDrawable = [planet->_cloudsShaderDrawable copy];
468 _atmosphereShaderDrawable = [planet->_atmosphereShaderDrawable copy];
469 [_atmosphereDrawable setRadius:collision_radius + ATMOSPHERE_DEPTH * PLANET_MINIATURE_FACTOR * 2.0];
470 if (_cloudsShaderDrawable) [_cloudsShaderDrawable setRadius:collision_radius + ATMOSPHERE_DEPTH * PLANET_MINIATURE_FACTOR * 2.0];
471 if (_atmosphereShaderDrawable) [_atmosphereShaderDrawable setRadius:collision_radius + ATMOSPHERE_DEPTH * PLANET_MINIATURE_FACTOR * 2.0];
473 [_planetDrawable setLevelOfDetail:0.8f];
474 [_atmosphereDrawable setLevelOfDetail:0.8f];
475 if (_cloudsShaderDrawable) [_cloudsShaderDrawable setLevelOfDetail:0.8f];
476 if (_atmosphereShaderDrawable) [_atmosphereShaderDrawable setLevelOfDetail:0.8f];
487 DESTROY(_cloudsShaderDrawable);
488 DESTROY(_atmosphereShaderDrawable);
501- (NSString*) descriptionComponents
503 return [NSString stringWithFormat:@"position: %@ radius: %g m", HPVectorDescription([
self position]), [
self radius]];
507- (void) setOrientation:(Quaternion) quat
509 [
super setOrientation: quat];
516 return collision_radius;
528- (instancetype) miniatureVersion
530 return [[[[
self class] alloc] initAsMiniatureVersionOfPlanet:self] autorelease];
536 [
super update:delta_t];
540 BOOL canDrawShaderAtmosphere = _atmosphereShaderDrawable && [UNIVERSE detailLevel] >=
DETAIL_LEVEL_SHADERS;
541 if (
EXPECT_NOT(_atmosphereDrawable && cam_zero_distance < _mesopause2))
543 NSAssert(_airColor !=
nil,
@"Expected a non-nil air colour for normal planet. Exiting.");
544 double alt = (sqrt(cam_zero_distance) - collision_radius) /
kMesosphere;
545 double trueAlt = (sqrt(zero_distance) - collision_radius) /
kMesosphere;
549 if (alt <= 0.0) alt = 1e-4;
552 double aleph = 1.0 - alt;
553 double aleph2 = aleph * aleph;
563 double rate = ([PLAYER occlusionLevel] - 0.97)/0.06;
565 if (
EXPECT(rate <= 1.0 && rate > 0.0))
584 if (
PLAYER->isSunlit && _airColor !=
nil) mixColor = _airColor;
586 [UNIVERSE setSkyColorRed:[mixColor
redComponent] * aleph2
590 double atmosphereRadius = canDrawShaderAtmosphere ? collision_radius : collision_radius + (
ATMOSPHERE_DEPTH * alt);
591 [_atmosphereDrawable setRadius:atmosphereRadius];
592 if (_cloudsShaderDrawable) [_cloudsShaderDrawable setRadius: atmosphereRadius];
593 if (_atmosphereShaderDrawable) [_atmosphereShaderDrawable setRadius:collision_radius + (ATMOSPHERE_DEPTH * alt)];
596 [UNIVERSE setAirResistanceFactor:OOClamp_0_1_f(1.0 - trueAlt)];
603 [_atmosphereDrawable setRadius:collision_radius + ATMOSPHERE_DEPTH];
604 if (_cloudsShaderDrawable) [_cloudsShaderDrawable setRadius: collision_radius * ATMOSPHERE_DEPTH];
605 if (_atmosphereShaderDrawable) [_atmosphereShaderDrawable setRadius:collision_radius + ATMOSPHERE_DEPTH];
607 if (canDrawShaderAtmosphere && [_atmosphereDrawable radius] != collision_radius)
610 [_atmosphereDrawable setRadius:collision_radius];
611 if (_cloudsShaderDrawable) [_cloudsShaderDrawable setRadius: collision_radius];
613 if ([
PLAYER findNearestPlanet] ==
self)
615 [UNIVERSE setAirResistanceFactor:0.0f];
619 double time = [UNIVERSE getTime];
621 if (_shuttlesOnGround > 0 && time > _lastLaunchTime + _shuttleLaunchInterval) [
self launchShuttle];
628 [
self orientationChanged];
634- (BOOL) isFinishedLoading
637 if (material !=
nil && ![material isFinishedLoading])
return NO;
638 material = [
self atmosphereMaterial];
639 if (material !=
nil && ![material isFinishedLoading])
return NO;
640 material = [
self atmosphereShaderMaterial];
641 if (material !=
nil && ![material isFinishedLoading])
return NO;
646- (void) drawImmediate:(
bool)immediate translucent:(
bool)translucent
648 BOOL canDrawShaderAtmosphere = _atmosphereShaderDrawable && [UNIVERSE detailLevel] >=
DETAIL_LEVEL_SHADERS;
650 if ([
UNIVERSE breakPatternHide])
return;
651 if (_miniature && ![
self isFinishedLoading])
return;
654 if (magnitude(cameraRelativePosition) > [
self radius]*3000) {
667 [_planetDrawable calculateLevelOfDetailForViewDistance:cam_zero_distance];
668 [_atmosphereDrawable setLevelOfDetail:[_planetDrawable levelOfDetail]];
669 if (canDrawShaderAtmosphere)
671 if (_cloudsShaderDrawable) [_cloudsShaderDrawable setLevelOfDetail: [_planetDrawable levelOfDetail]];
672 [_atmosphereShaderDrawable setLevelOfDetail:[_planetDrawable levelOfDetail]];
688 [_planetDrawable renderOpaqueParts];
689 if (_atmosphereDrawable !=
nil)
693 if (canDrawShaderAtmosphere)
695 if(_cloudsShaderDrawable) [_cloudsShaderDrawable renderTranslucentPartsOnOpaquePass];
696 [_atmosphereShaderDrawable renderTranslucentPartsOnOpaquePass];
700 [_atmosphereDrawable renderTranslucentPartsOnOpaquePass];
705#if OOLITE_HAVE_FIXED_THE_ABOVE_DESCRIBED_BUG_WHICH_WE_HAVENT
712 if (_atmosphereDrawable !=
nil)
716 [_atmosphereDrawable renderTranslucentParts];
717 if (canDrawShaderAtmosphere) [_atmosphereShaderDrawable renderTranslucentParts];
723 [_planetDrawable renderOpaqueParts];
732- (BOOL) checkCloseCollisionWith:(
Entity *)other
739 if ([ship behaviour] == BEHAVIOUR_LAND_ON_PLANET)
749- (BOOL) planetHasStation
753 station = [UNIVERSE nearestShipMatchingPredicate:IsStationPredicate
755 relativeToEntity:self];
757 if (station && HPdistance([station position], position) < 4 * collision_radius)
765- (void) launchShuttle
767 if (_shuttlesOnGround == 0)
771 if ([
PLAYER status] == STATUS_START_GAME)
776 if (
self != [
UNIVERSE planet] && ![
self planetHasStation])
779 _shuttlesOnGround = 0;
785 float start_distance = collision_radius + 125.0f;
788 ShipEntity *shuttle_ship = [UNIVERSE newShipWithRole:@"shuttle"];
791 if ([[shuttle_ship crew]
count] == 0)
801 [shuttle_ship
switchAITo:@"oolite-shuttleAI.js"];
802 [UNIVERSE addEntity:shuttle_ship];
804 _lastLaunchTime = [UNIVERSE getTime];
806 [shuttle_ship release];
829- (double) rotationalVelocity
831 return _rotationalVelocity;
835- (void) setRotationalVelocity:(
double) v
837 if ([
self hasAtmosphere])
841 _rotationalVelocity = v;
846- (Vector) airColorAsVector
849 [_airColor getRed:&r green:&g blue:&b alpha:&a];
850 return make_vector(r, g, b);